TenantAtlas/specs/230-findings-notification-convergence/data-model.md
ahmido 742d65f0d9
Some checks failed
Main Confidence / confidence (push) Failing after 51s
feat: converge findings notification presentation (#265)
## Summary
- converge finding, queued, and completed database notifications on one shared `OperationUxPresenter` presentation contract
- preserve existing finding and operation deep-link authorities while standardizing title, body, status/icon treatment, and single primary action
- add focused notification, findings, and guard coverage plus the full feature 230 spec artifacts

## Validation
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Notifications/SharedDatabaseNotificationContractTest.php tests/Feature/Notifications/OperationRunNotificationTest.php tests/Feature/Notifications/FindingNotificationLinkTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Findings/FindingsNotificationEventTest.php tests/Feature/Findings/FindingsNotificationRoutingTest.php tests/Feature/OpsUx/Constitution/LegacyNotificationGuardTest.php`

## Filament / Platform Notes
- Livewire v4.0+ compliance preserved on Filament v5 primitives
- provider registration remains unchanged in `apps/platform/bootstrap/providers.php`
- no globally searchable resource behavior changed in this feature
- no destructive actions were introduced
- asset strategy is unchanged; the existing `cd apps/platform && php artisan filament:assets` deploy step remains sufficient

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #265
2026-04-22 20:26:18 +00:00

6.2 KiB

Data Model: Findings Notification Presentation Convergence

Overview

This feature introduces no new persisted business entity. Existing finding truth, operation-run truth, deep-link helpers, and database-notification rows remain canonical. The new work is a bounded derived presentation layer over those existing records.

Existing Persistent Entities

Database Notification (notifications table)

Purpose: Existing persisted delivery artifact for operator-facing in-app notifications.

Key fields used by this feature:

  • id
  • type
  • notifiable_type
  • notifiable_id
  • data
  • read_at
  • created_at

Rules relevant to convergence:

  • The feature changes only the derived primary payload shape stored in data.
  • Existing namespaced metadata such as finding_event, reason_translation, and diagnostic_reason_code remains secondary and consumer-specific.
  • No new table or projection is added.

Finding

Purpose: Canonical tenant-scoped truth for finding identity, severity, lifecycle, and notification-event context.

Key fields used by this feature:

  • id
  • tenant_id
  • workspace_id
  • severity
  • status
  • owner_user_id
  • assignee_user_id
  • due_at

Rules relevant to convergence:

  • The feature does not change how finding events are generated.
  • Finding links continue to resolve against the existing tenant-panel detail route.
  • Finding-event metadata remains available for downstream consumers and tests.

OperationRun

Purpose: Canonical truth for operation lifecycle, scope, outcome, and supporting notification context.

Key fields used by this feature:

  • id
  • type
  • status
  • outcome
  • tenant_id
  • context
  • summary_counts
  • failure_summary

Rules relevant to convergence:

  • The feature does not change queued or terminal notification emit rules.
  • Existing admin-plane, tenantless, and system-plane link resolution remains authoritative.
  • Completed-run guidance and reason translation remain derived from current run truth.

Notifiable Context

Purpose: Determines which route family and supporting context a notification may expose.

Relevant notifiable cases:

  • tenant-scoped operator receiving a finding notification
  • workspace operator receiving an admin-plane operation notification
  • platform user receiving a system-plane operation notification

Rules relevant to convergence:

  • Shared presentation must not erase plane-specific destination behavior.
  • The shared contract can adapt the action URL by notifiable context, but it cannot widen visibility or flatten authorization semantics.

Derived Models

OperatorDatabaseNotificationPresentation

Purpose: Shared derived contract for the primary structure rendered in the existing Filament notification drawer.

Fields:

  • title
  • body
  • status
  • primaryAction.label
  • primaryAction.url
  • primaryAction.target
  • supportingLines[]
  • metadata

Validation rules:

  • Every in-scope consumer provides exactly one primary action.
  • status remains the single source for the existing Filament icon treatment; the feature does not introduce a second icon taxonomy.
  • supportingLines is optional and never replaces body or the primary action.
  • metadata may carry consumer-specific namespaced fields, but the shared primary structure remains stable.

NotificationPrimaryAction

Purpose: Canonical one-action model for secondary context notifications.

Fields:

  • label
  • url
  • target

Allowed targets:

  • finding_detail
  • admin_operation_run
  • tenantless_operation_run
  • system_operation_run

Rules:

  • There is exactly one primary action per in-scope card.
  • The action source remains the existing canonical link helper for that domain and plane.

FindingNotificationPresentationInput

Purpose: Consumer-specific derived input used by the shared contract for FindingEventNotification.

Fields:

  • findingId
  • tenantId
  • eventType
  • title
  • body
  • recipientReason
  • tenantName
  • severity
  • fingerprintKey
  • dueCycleKey

Rules:

  • Primary wording remains finding-first and uses Open finding as the action label.
  • recipientReason stays supporting context, not the headline.

OperationRunNotificationPresentationInput

Purpose: Consumer-specific derived input used by the shared contract for queued and terminal run notifications.

Fields:

  • runId
  • operationType
  • status
  • outcome
  • targetPlane
  • openUrl
  • openLabel
  • guidanceLines[]
  • summaryLine
  • reasonTranslation

Rules:

  • Queued notifications keep their existing queued vocabulary but adopt the shared card structure.
  • Completed notifications preserve terminal explanation, summary, and diagnostic fields as supporting context.
  • Platform users resolve to the system-panel run detail route; non-platform users keep current admin or tenantless behavior.

Consumer Matrix

Consumer Source truth Primary action target Required shared fields Preserved secondary metadata
FindingEventNotification Finding plus existing event envelope tenant finding detail title, body, status with existing icon treatment, Open finding, tenant-safe URL finding_event with recipient reason, fingerprint, tenant name, severity
OperationRunQueued OperationRun queued state admin or tenantless operation run view title, body, status with existing icon treatment, open-run label, resolved URL minimal context derived from current run state only
OperationRunCompleted OperationRun terminal state admin, tenantless, or system operation run view title, body, status with existing icon treatment, open-run label, resolved URL reason_translation, diagnostic_reason_code, summary lines, failure guidance

Persistence Boundaries

  • No new table, enum-backed persistence, or presentation-only cache is introduced.
  • The shared notification contract remains derived from existing finding and operation-run truth.
  • Existing notifications.data remains the only persisted artifact for in-app delivery.
  • Existing event semantics from Spec 224 and current operation notification behavior remain unchanged.