## 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
212 lines
17 KiB
Markdown
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.
|