# Tasks: Findings Notification Presentation Convergence **Input**: Design documents from `/specs/230-findings-notification-convergence/` **Prerequisites**: `plan.md`, `spec.md`, `research.md`, `data-model.md`, `contracts/findings-notification-convergence.logical.openapi.yaml`, `quickstart.md` **Tests**: Required. This feature changes runtime behavior in operator-facing database notification payload composition and preserved route targeting, so Pest coverage must be added or updated in `apps/platform/tests/Feature/Notifications/SharedDatabaseNotificationContractTest.php`, `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php`, `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`, and `apps/platform/tests/Feature/OpsUx/Constitution/LegacyNotificationGuardTest.php`. **Operations**: No new `OperationRun` is introduced. Existing queued and terminal operation notification consumers remain in scope only for presentation convergence in `apps/platform/app/Notifications/OperationRunQueued.php` and `apps/platform/app/Notifications/OperationRunCompleted.php`; emit policy and run lifecycle semantics must remain unchanged. **RBAC**: Finding notifications stay on the tenant `/admin/t/{tenant}/findings/{finding}` plane and operation notifications keep their current admin `/admin/operations/{run}` or platform `/system/ops/runs/{run}` destinations. The implementation must preserve non-member or hidden-scope `404`, in-scope missing-capability `403`, tenant-safe deep links, and current plane-specific visibility semantics. **UI / Surface Guardrails**: The existing Filament database-notification drawer remains the only collection surface and is a `global-context-shell` seam. Every in-scope card must keep exactly one primary action, no row click, no destructive action, and no custom notification shell. **Filament UI Action Surfaces**: `FindingEventNotification`, `OperationRunQueued`, and `OperationRunCompleted` remain utility or system notification entry points with one inspect model each. No new page family, no new action group, and no second notification center may be introduced. **Badges**: Existing severity, status, and outcome semantics remain authoritative. This feature must not introduce ad-hoc badge mappings or a new status taxonomy. **Organization**: Tasks are grouped by user story so each slice stays incrementally testable once the shared seam from earlier phases is present. Recommended delivery order is `US1 -> US2 -> US3` because the shared primary card structure must stabilize before route-truth and future-bypass guardrails are extended. ## Test Governance Checklist - [X] Lane assignment is named and is the narrowest sufficient proof for the changed behavior. - [X] New or changed tests stay in the smallest honest family, and any heavy-governance or browser addition is explicit. - [X] Shared helpers, factories, seeds, fixtures, and context defaults stay cheap by default; any widening is isolated or documented. - [X] Planned validation commands cover the change without pulling in unrelated lane cost. - [X] The declared surface test profile or `standard-native-filament` relief is explicit. - [X] Any material budget, baseline, trend, or escalation note is recorded in the active spec or PR. ## Phase 1: Setup (Shared Notification Test Surfaces) **Purpose**: Prepare the focused regression surfaces that will prove the shared notification contract. - [X] T001 [P] Create the shared contract test scaffold in `apps/platform/tests/Feature/Notifications/SharedDatabaseNotificationContractTest.php` - [X] T002 [P] Extend the finding notification test scaffold in `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php` - [X] T003 [P] Extend the operation notification test scaffold in `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php` **Checkpoint**: Shared contract, finding notification, and operation notification test surfaces are ready for implementation work. --- ## Phase 2: Foundational (Blocking Shared Presentation Seam) **Purpose**: Establish the canonical shared presentation path and repo guardrails before any story implementation begins. **CRITICAL**: No user story work should begin until this phase is complete. - [X] T004 Implement the shared operator database-notification builder, status-to-icon mapping, and supporting-line composition in `apps/platform/app/Support/OpsUx/OperationUxPresenter.php` - [X] T005 Add baseline cross-consumer contract assertions for shared structure and status-to-icon treatment in `apps/platform/tests/Feature/Notifications/SharedDatabaseNotificationContractTest.php` - [X] T006 Extend the in-scope local-payload bypass guard in `apps/platform/tests/Feature/OpsUx/Constitution/LegacyNotificationGuardTest.php` **Checkpoint**: The shared presentation seam exists, the baseline contract is testable, and CI can detect direct local bypasses of the in-scope notification family. --- ## Phase 3: User Story 1 - Scan Notifications Without Relearning The Surface (Priority: P1) **Goal**: Give finding and operation notifications one shared primary card structure so operators can read both without reinterpreting the surface. **Independent Test**: Trigger one finding notification and one operation notification, then verify both render the same primary structure: a title naming the target object, a primary body summarizing the change, one status emphasis with the existing Filament icon treatment, exactly one primary action, and optional supporting context that stays secondary. ### Tests for User Story 1 - [X] T007 [P] [US1] Add finding shared-card structure and status-to-icon assertions in `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php` - [X] T008 [P] [US1] Add queued and completed run shared-card structure and status-to-icon assertions in `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php` ### Implementation for User Story 1 - [X] T009 [P] [US1] Route `apps/platform/app/Notifications/Findings/FindingEventNotification.php` through the shared presentation builder while preserving `finding_event` metadata - [X] T010 [P] [US1] Route `apps/platform/app/Notifications/OperationRunQueued.php` through the shared presentation builder while preserving queued-state copy and one primary action - [X] T011 [P] [US1] Normalize `apps/platform/app/Notifications/OperationRunCompleted.php` onto the same primary structure while keeping summary and reason translation as secondary context **Checkpoint**: User Story 1 is independently functional and finding plus operation notifications share one primary card grammar. --- ## Phase 4: User Story 2 - Trust Notification Actions And Scope Rules (Priority: P1) **Goal**: Preserve correct finding and operation destinations plus current `404` versus `403` behavior while the shared presentation seam is introduced. **Independent Test**: After US1 is in place, open finding and operation notification actions as entitled and non-entitled users, then verify the correct tenant, admin, tenantless, or system destination opens and existing authorization semantics remain unchanged. ### Tests for User Story 2 - [X] T012 [P] [US2] Add tenant-safe `404` versus `403` action-link assertions in `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php` - [X] T013 [P] [US2] Add admin, tenantless, and system-plane action-link assertions in `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php` - [X] T014 [P] [US2] Keep Spec 224 finding event and routing behavior covered under the new presentation path in `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php` and `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php` ### Implementation for User Story 2 - [X] T015 [US2] Preserve the `Open finding` label and tenant detail route authority in `apps/platform/app/Notifications/Findings/FindingEventNotification.php` - [X] T016 [US2] Preserve admin, tenantless, and platform-user system destinations in `apps/platform/app/Notifications/OperationRunQueued.php` and `apps/platform/app/Notifications/OperationRunCompleted.php` - [X] T017 [US2] Verify canonical operation action labels and route helpers remain authoritative in `apps/platform/app/Support/OperationRunLinks.php` and `apps/platform/app/Support/System/SystemOperationRunLinks.php`, applying only minimal normalization if the shared contract requires it **Checkpoint**: User Story 2 is independently functional and the shared card structure does not alter route truth or authorization semantics. --- ## Phase 5: User Story 3 - Keep Future Work-Update Notifications Familiar (Priority: P2) **Goal**: Lock the new shared contract in place so later in-scope notification consumers cannot silently reintroduce a local primary grammar. **Independent Test**: After US1 and US2 are in place, assert that the in-scope finding and operation consumers expose exactly one primary action through the shared contract and that guard coverage fails if a future in-scope consumer builds its primary payload locally. ### Tests for User Story 3 - [X] T018 [P] [US3] Add regression assertions that all in-scope consumers expose exactly one primary action, keep shared status-to-icon treatment, and keep secondary metadata namespaced in `apps/platform/tests/Feature/Notifications/SharedDatabaseNotificationContractTest.php` - [X] T019 [P] [US3] Extend future-bypass and FR-015 boundary guard coverage in `apps/platform/tests/Feature/OpsUx/Constitution/LegacyNotificationGuardTest.php` ### Implementation for User Story 3 - [X] T020 [US3] Encapsulate consumer input mapping for finding, queued-run, and completed-run notifications inside `apps/platform/app/Support/OpsUx/OperationUxPresenter.php` - [X] T021 [US3] Keep consumer-specific metadata secondary in `apps/platform/app/Notifications/Findings/FindingEventNotification.php` and `apps/platform/app/Notifications/OperationRunCompleted.php` - [X] T022 [US3] Keep queued notification supporting context minimal and inside the shared contract in `apps/platform/app/Notifications/OperationRunQueued.php` and `apps/platform/app/Support/OpsUx/OperationUxPresenter.php` **Checkpoint**: User Story 3 is independently functional and future in-scope notification work is steered toward the shared contract instead of local payload composition. --- ## Phase 6: Polish & Cross-Cutting Concerns **Purpose**: Finish copy review, formatting, and the narrow proving workflow for the full feature. - [X] T023 Review operator-facing notification copy, status-emphasis grammar, and one-primary-action ordering in `apps/platform/app/Support/OpsUx/OperationUxPresenter.php`, `apps/platform/app/Notifications/Findings/FindingEventNotification.php`, `apps/platform/app/Notifications/OperationRunQueued.php`, and `apps/platform/app/Notifications/OperationRunCompleted.php` - [X] T024 Run formatting for `apps/platform/app/Support/OpsUx/OperationUxPresenter.php`, `apps/platform/app/Notifications/Findings/FindingEventNotification.php`, `apps/platform/app/Notifications/OperationRunQueued.php`, `apps/platform/app/Notifications/OperationRunCompleted.php`, `apps/platform/app/Support/OperationRunLinks.php`, `apps/platform/app/Support/System/SystemOperationRunLinks.php`, `apps/platform/tests/Feature/Notifications/SharedDatabaseNotificationContractTest.php`, `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php`, `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`, and `apps/platform/tests/Feature/OpsUx/Constitution/LegacyNotificationGuardTest.php` with `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - [X] T025 Run the focused validation workflow from `specs/230-findings-notification-convergence/quickstart.md` against `apps/platform/tests/Feature/Notifications/SharedDatabaseNotificationContractTest.php`, `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php`, `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`, and `apps/platform/tests/Feature/OpsUx/Constitution/LegacyNotificationGuardTest.php` --- ## Dependencies & Execution Order ### Phase Dependencies - **Setup (Phase 1)**: Starts immediately and prepares the focused test surfaces. - **Foundational (Phase 2)**: Depends on Setup and blocks all user story work until the shared presentation seam and baseline guard are in place. - **User Story 1 (Phase 3)**: Depends on Foundational completion and is the recommended MVP cut. - **User Story 2 (Phase 4)**: Depends on User Story 1 because route and scope truth must be validated against the converged primary structure, not the pre-convergence local grammars. - **User Story 3 (Phase 5)**: Depends on User Story 1 and User Story 2 because spread-control guardrails must lock the final shared contract and preserved route behavior, not an intermediate shape. - **Polish (Phase 6)**: Depends on all desired user stories being complete. ### User Story Dependencies - **US1**: No dependencies beyond Foundational. - **US2**: Follow-on slice after US1 establishes the shared primary structure. - **US3**: Follow-on slice after US1 and US2 establish the settled contract and preserved route rules. ### Within Each User Story - Write the story tests first and confirm they fail before implementation is considered complete. - Keep `apps/platform/app/Support/OpsUx/OperationUxPresenter.php` authoritative for shared primary structure instead of duplicating card grammar in notification classes. - Finish story-level verification before moving to the next priority slice. ### Parallel Opportunities - `T001`, `T002`, and `T003` can run in parallel during Setup. - `T007` and `T008` can run in parallel for User Story 1, followed by `T009`, `T010`, and `T011` in parallel after `T004` is complete. - `T012`, `T013`, and `T014` can run in parallel for User Story 2. - `T018` and `T019` can run in parallel for User Story 3. --- ## Parallel Example: User Story 1 ```bash # User Story 1 tests in parallel T007 apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php T008 apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php # User Story 1 implementation in parallel after T004 T009 apps/platform/app/Notifications/Findings/FindingEventNotification.php T010 apps/platform/app/Notifications/OperationRunQueued.php T011 apps/platform/app/Notifications/OperationRunCompleted.php ``` ## Parallel Example: User Story 2 ```bash # User Story 2 tests in parallel T012 apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php T013 apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php T014 apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php ``` ## Parallel Example: User Story 3 ```bash # User Story 3 guard and contract tests in parallel T018 apps/platform/tests/Feature/Notifications/SharedDatabaseNotificationContractTest.php T019 apps/platform/tests/Feature/OpsUx/Constitution/LegacyNotificationGuardTest.php ``` --- ## Implementation Strategy ### MVP First (User Story 1 Only) 1. Complete Phase 1: Setup. 2. Complete Phase 2: Foundational. 3. Complete Phase 3: User Story 1. 4. Validate the feature against the focused US1 tests before widening the slice. ### Incremental Delivery 1. Ship US1 to converge the primary card structure across findings and operations. 2. Add US2 to prove route truth and authorization semantics stayed intact. 3. Add US3 to lock the shared contract in place for future in-scope notification work. 4. Finish with copy review, formatting, and the focused validation pack. ### Parallel Team Strategy 1. One contributor can prepare the shared contract test and guard work while another extends finding and operation notification test surfaces. 2. After Foundational work lands, finding, queued-run, and completed-run notification classes can be aligned in parallel against the shared presenter seam. 3. Route-truth tests can proceed in parallel with preserved-link implementation once the shared primary structure is stable. --- ## Notes - `[P]` tasks target different files and can be worked independently once upstream blockers are cleared. - `[US1]`, `[US2]`, and `[US3]` map directly to the feature specification user stories. - The suggested MVP scope is Phase 1 through Phase 3 only. - All implementation tasks above follow the required checklist format with task ID, optional parallel marker, story label where applicable, and exact file paths.