TenantAtlas/specs/224-findings-notifications-escalation/tasks.md
ahmido e15d80cca5
Some checks failed
Main Confidence / confidence (push) Failing after 48s
Heavy Governance Lane / heavy-governance (push) Has been skipped
Browser Lane / browser (push) Has been skipped
feat: implement findings notifications escalation (#261)
## Summary
- implement Spec 224 findings notifications and escalation v1 on top of the existing alerts and Filament database notification infrastructure
- add finding assignment, reopen, due soon, and overdue event handling with direct recipient routing, dedupe, and optional external alert fan-out
- extend alert rule and alert delivery surfaces plus add the Spec 224 planning bundle and candidate-list promotion cleanup

## Validation
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Findings/FindingsNotificationEventTest.php tests/Feature/Findings/FindingsNotificationRoutingTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Alerts/FindingsAlertRuleIntegrationTest.php tests/Feature/Alerts/SlaDueAlertTest.php tests/Feature/Notifications/FindingNotificationLinkTest.php`

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

## Manual Smoke Note
- integrated-browser smoke testing confirmed the new alert rule event options, notification drawer entries, alert delivery history row, and tenant finding detail route on the active Sail host
- local notification deep links currently resolve from `APP_URL`, so a local `localhost` vs `127.0.0.1:8081` host mismatch can break the browser session if the app is opened on a different host/port combination

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #261
2026-04-22 00:54:38 +00:00

212 lines
17 KiB
Markdown

# Tasks: Findings Notifications & Escalation v1
**Input**: Design documents from `/specs/224-findings-notifications-escalation/`
**Prerequisites**: `plan.md`, `spec.md`, `research.md`, `data-model.md`, `contracts/findings-notifications-escalation.logical.openapi.yaml`, `quickstart.md`
**Tests**: Required. This feature changes runtime behavior in finding workflow mutations, scheduled alert evaluation, Laravel database notifications, and existing Filament alert-management surfaces, so Pest coverage must be added in `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`, `apps/platform/tests/Feature/Alerts/FindingsAlertRuleIntegrationTest.php`, `apps/platform/tests/Feature/Alerts/SlaDueAlertTest.php`, and `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php`.
**Operations**: No new `OperationRun` is introduced. Scheduled due-soon and overdue evaluation must remain on the existing `alerts.evaluate` cadence via `apps/platform/app/Jobs/Alerts/EvaluateAlertsJob.php` and the existing `tenantpilot:alerts:dispatch` command.
**RBAC**: Workspace alert configuration stays on the admin `/admin` plane and finding follow-up stays on the tenant `/admin/t/{tenant}/findings/{finding}` plane. The implementation must preserve `ALERTS_VIEW`-gated read access to alert rules and alert deliveries, `ALERTS_MANAGE`-gated alert-rule mutation, non-member and hidden-scope `404`, in-scope missing-capability `403`, and send-time entitlement rechecks before direct personal delivery.
**UI / Surface Guardrails**: `Alert rules` and `Alert deliveries` stay `standard-native-filament` surfaces. The database notification drawer plus tenant finding detail link is a `global-context-shell` seam and must keep one calm `Open finding` drill-in path only.
**Filament UI Action Surfaces**: `AlertRuleResource` and `AlertDeliveryResource` remain existing resource patterns with no new page family, no new destructive action, and no second notification center. Direct finding notifications expose one inspect model only: the finding.
**Badges**: Existing finding severity, lifecycle, and alert-delivery status semantics remain authoritative. No page-local badge taxonomy or ad-hoc status mapping is introduced.
**Organization**: Tasks are grouped by user story so each slice stays independently testable. Recommended delivery order is `US1 -> US2 -> US3`, because direct responsible-user delivery closes the smallest workflow gap first, due-cycle reminders build on the same delivery seam second, and external-copy management is safest after direct-event truth is established.
## 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 (Notification Scaffolding)
**Purpose**: Prepare the shared delivery seam and focused regression suites used across all stories.
- [X] T001 [P] Create the finding notification service scaffold in `apps/platform/app/Services/Findings/FindingNotificationService.php`
- [X] T002 [P] Create the finding event database-notification scaffold in `apps/platform/app/Notifications/Findings/FindingEventNotification.php`
- [X] T003 [P] Create focused Pest scaffolding in `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`, `apps/platform/tests/Feature/Alerts/FindingsAlertRuleIntegrationTest.php`, and `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php`
**Checkpoint**: The shared service, notification class, and focused test files exist and are ready for implementation work.
---
## Phase 2: Foundational (Blocking Event Vocabulary And Delivery Seams)
**Purpose**: Establish the canonical finding event keys, direct-delivery baseline, and shared dispatch contract every story depends on.
**⚠️ CRITICAL**: No user story work should begin until this phase is complete.
- [X] T004 Add the four canonical finding event constants in `apps/platform/app/Models/AlertRule.php`
- [X] T005 Implement the shared finding-event envelope builder, recipient-resolution precedence, send-time entitlement recheck, fingerprint helpers, and direct-delivery dedupe baseline in `apps/platform/app/Services/Findings/FindingNotificationService.php`
- [X] T006 Implement the base Filament database notification payload, recipient-reason copy, and tenant finding deep link in `apps/platform/app/Notifications/Findings/FindingEventNotification.php`
- [X] T007 Add foundational database-notification payload-shape and tenant-safe `404` versus `403` link coverage in `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php`
- [X] T008 Wire the shared optional external-copy dispatch baseline from `apps/platform/app/Services/Findings/FindingNotificationService.php` into `apps/platform/app/Services/Alerts/AlertDispatchService.php`
**Checkpoint**: Shared event vocabulary, recipient resolution, direct personal delivery, and external-copy handoff are available for all stories.
---
## Phase 3: User Story 1 - Receive direct notification when work changes hands or reopens (Priority: P1) 🎯 MVP
**Goal**: Notify the directly responsible operator when an open finding is assigned to them or a previously terminal finding is reopened by system detection.
**Independent Test**: Assign an open finding to a new assignee and trigger a system reopen on a terminal finding, then verify one entitled recipient receives one tenant-safe notification with a deep link while owner-only changes remain silent.
### Tests for User Story 1
- [X] T009 [P] [US1] Add assignment and system-reopen event production plus rapid reassignment and repeated automatic-reopen dedupe coverage in `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`
- [X] T010 [P] [US1] Add recipient precedence, owner-only suppression, assignee-clear suppression, and entitlement-loss coverage for assignment and reopen flows in `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`
### Implementation for User Story 1
- [X] T011 [US1] Emit `findings.assigned` only after committed assignee changes and suppress owner-only, assignee-clear, and no-op saves in `apps/platform/app/Services/Findings/FindingWorkflowService.php`
- [X] T012 [US1] Emit `findings.reopened` only from the system-driven reopen path in `apps/platform/app/Services/Findings/FindingWorkflowService.php`
- [X] T013 [US1] Align assignment and reopen notification titles, bodies, and recipient-reason vocabulary in `apps/platform/app/Services/Findings/FindingNotificationService.php` and `apps/platform/app/Notifications/Findings/FindingEventNotification.php`
**Checkpoint**: User Story 1 is independently functional and the responsible operator no longer needs to poll findings pages to notice assignment or automatic reopen.
---
## Phase 4: User Story 2 - Get due-soon reminders and overdue escalation without spam (Priority: P1)
**Goal**: Turn finding due dates into one-per-cycle due-soon reminders and overdue escalations without duplicate personal notification noise.
**Independent Test**: Seed open findings across due-soon and overdue thresholds with different owner and assignee combinations, run alert evaluation, and verify correct recipient precedence, terminal suppression, same-user dedupe, and one notification per due cycle.
### Tests for User Story 2
- [X] T014 [P] [US2] Add due-soon and overdue window, one-per-cycle, and `due_at`-driven due-cycle-reset coverage in `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`
- [X] T015 [P] [US2] Add due recipient precedence, same-user dedupe, terminal-finding suppression, and no-entitled-recipient suppression coverage in `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`
### Implementation for User Story 2
- [X] T016 [US2] Add workspace-scoped due-soon and overdue candidate collection with a 24-hour reminder window and non-open-finding suppression in `apps/platform/app/Jobs/Alerts/EvaluateAlertsJob.php`
- [X] T017 [US2] Route due-soon and overdue candidates through the shared delivery seam and derive per-cycle fingerprints from the recalculated `due_at` value in `apps/platform/app/Services/Findings/FindingNotificationService.php`
- [X] T018 [US2] Add due-window and owner-versus-assignee factory states needed for due-cycle reminder coverage in `apps/platform/database/factories/FindingFactory.php`
**Checkpoint**: User Story 2 is independently functional and due dates now produce predictable, non-spammy direct reminders and overdue escalation.
---
## Phase 5: User Story 3 - Configure external copies through existing Alerts management (Priority: P2)
**Goal**: Let workspace operators configure and inspect optional external copies for the same finding events through the existing Alerts management surfaces.
**Independent Test**: Add the new finding event types to an alert rule, trigger a matching event through the shared delivery seam, and verify external deliveries appear in the existing viewer while direct personal delivery still works without a matching rule.
### Tests for User Story 3
- [X] T019 [US3] Add alert-rule event option exposure, alert-rule and alert-delivery non-member or hidden-scope `404` versus in-scope capability `403` coverage, `ALERTS_VIEW` read versus `ALERTS_MANAGE` mutation boundaries, inherited external-copy behavior covering minimum severity, tenant scoping, cooldown, quiet hours, dedupe, delivery-history label and filter coverage, and direct-without-rule behavior in `apps/platform/tests/Feature/Alerts/FindingsAlertRuleIntegrationTest.php`; extend `apps/platform/tests/Feature/Alerts/SlaDueAlertTest.php` to prove aggregate `sla_due` behavior remains unchanged
### Implementation for User Story 3
- [X] T020 [P] [US3] Expose the four finding notification event types in the existing selector and label mapping in `apps/platform/app/Filament/Resources/AlertRuleResource.php`
- [X] T021 [P] [US3] Render finding-event labels and filter options in the existing viewer in `apps/platform/app/Filament/Resources/AlertDeliveryResource.php`
- [X] T022 [US3] Finalize finding-event payload normalization and rule-driven external-copy fan-out behavior in `apps/platform/app/Services/Alerts/AlertDispatchService.php` and `apps/platform/app/Services/Findings/FindingNotificationService.php`
**Checkpoint**: User Story 3 is independently functional and workspace teams can reuse existing Alerts rules and delivery history for finding assignment, reopen, due-soon, and overdue copies.
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Finish guardrail alignment, formatting, and focused verification across the full feature.
- [X] T023 Review operator-facing finding vocabulary, recipient-reason copy, and guardrail alignment in `apps/platform/app/Services/Findings/FindingNotificationService.php`, `apps/platform/app/Notifications/Findings/FindingEventNotification.php`, `apps/platform/app/Filament/Resources/AlertRuleResource.php`, and `apps/platform/app/Filament/Resources/AlertDeliveryResource.php`
- [X] T024 Run formatting for `apps/platform/app/Services/Findings/FindingNotificationService.php`, `apps/platform/app/Notifications/Findings/FindingEventNotification.php`, `apps/platform/app/Services/Findings/FindingWorkflowService.php`, `apps/platform/app/Jobs/Alerts/EvaluateAlertsJob.php`, `apps/platform/app/Services/Alerts/AlertDispatchService.php`, `apps/platform/app/Models/AlertRule.php`, `apps/platform/app/Filament/Resources/AlertRuleResource.php`, `apps/platform/app/Filament/Resources/AlertDeliveryResource.php`, `apps/platform/database/factories/FindingFactory.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`, `apps/platform/tests/Feature/Alerts/FindingsAlertRuleIntegrationTest.php`, and `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php` with `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- [X] T025 Run the focused verification workflow from `specs/224-findings-notifications-escalation/quickstart.md` against `apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php`, `apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php`, `apps/platform/tests/Feature/Alerts/FindingsAlertRuleIntegrationTest.php`, `apps/platform/tests/Feature/Alerts/SlaDueAlertTest.php`, and `apps/platform/tests/Feature/Notifications/FindingNotificationLinkTest.php`
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)**: Starts immediately and prepares the shared service, notification class, and focused Pest files.
- **Foundational (Phase 2)**: Depends on Setup and blocks all user stories until shared event vocabulary, recipient resolution, and dispatch seams exist.
- **User Story 1 (Phase 3)**: Depends on Foundational completion and is the recommended MVP cut.
- **User Story 2 (Phase 4)**: Depends on Foundational completion and extends the same direct-delivery seam with scheduled due evaluation.
- **User Story 3 (Phase 5)**: Depends on Foundational completion and extends the existing Alerts management surfaces with the same event vocabulary.
- **Polish (Phase 6)**: Depends on all desired user stories being complete.
### User Story Dependencies
- **US1**: No dependencies beyond Foundational.
- **US2**: No hard dependency on US1, but it reuses the same delivery seam and should preserve direct-delivery vocabulary established there.
- **US3**: No hard dependency on US1 or US2 after Foundational, but it must stay aligned with the shared event vocabulary and direct-delivery contract they use.
### Within Each User Story
- Write the story tests first and confirm they fail before implementation is considered complete.
- Keep shared delivery behavior authoritative in `FindingNotificationService.php` before duplicating logic in `FindingWorkflowService.php` or `EvaluateAlertsJob.php`.
- Finish story-level verification before moving to the next priority slice.
### Parallel Opportunities
- `T001`, `T002`, and `T003` can run in parallel during Setup.
- `T009` and `T010` can run in parallel for User Story 1.
- `T014` and `T015` can run in parallel for User Story 2.
- `T020` and `T021` can run in parallel for User Story 3.
---
## Parallel Example: User Story 1
```bash
# User Story 1 tests in parallel
T009 apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php
T010 apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php
```
## Parallel Example: User Story 2
```bash
# User Story 2 tests in parallel
T014 apps/platform/tests/Feature/Findings/FindingsNotificationEventTest.php
T015 apps/platform/tests/Feature/Findings/FindingsNotificationRoutingTest.php
```
## Parallel Example: User Story 3
```bash
# User Story 3 surface work in parallel
T020 apps/platform/app/Filament/Resources/AlertRuleResource.php
T021 apps/platform/app/Filament/Resources/AlertDeliveryResource.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 close the direct assignment and automatic-reopen feedback gap.
2. Add US2 to turn due dates into actionable reminders and overdue escalation.
3. Add US3 to let workspace teams configure optional external copies through the existing Alerts UI.
4. Finish with copy review, formatting, and the focused verification pack.
### Parallel Team Strategy
1. One contributor can scaffold the shared service and notification class while another prepares the focused Pest suites.
2. After Foundational work lands, one contributor can wire workflow-event production while another implements due-evaluation logic.
3. Alert-rule and delivery-viewer surface work can proceed in parallel with direct-delivery trigger work once the shared event vocabulary 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.