Implements spec `099-alerts-v1-teams-email`. - Monitoring navigation: Alerts as a cluster under Monitoring; default landing is Alert deliveries. - Tenant panel: Alerts points to `/admin/alerts` and the cluster navigation is hidden in tenant panel. - Guard compliance: removes direct `Gate::` usage from Alert resources so `NoAdHocFilamentAuthPatternsTest` passes. Verification: - Full suite: `1348 passed, 7 skipped` (EXIT=0). Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #121
10 KiB
| description |
|---|
| Task list for 099 Alerts v1 (Teams + Email) |
Tasks: 099 — Alerts v1 (Teams + Email)
Input: Design documents from /specs/099-alerts-v1-teams-email/
Prerequisites: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
- Spec:
/specs/099-alerts-v1-teams-email/spec.md - Plan:
/specs/099-alerts-v1-teams-email/plan.md - Research:
/specs/099-alerts-v1-teams-email/research.md - Data model:
/specs/099-alerts-v1-teams-email/data-model.md - Contracts:
/specs/099-alerts-v1-teams-email/contracts/openapi.yaml
Tests: REQUIRED (Pest) — this feature changes runtime behavior.
Operations: Jobs that perform queued delivery MUST create/update canonical OperationRun records and show “View run” via the Monitoring hub.
RBAC: Enforce 404 vs 403 semantics and use capability registry constants (no raw strings).
Format: [ID] [P?] [Story] Description
Phase 1: Setup (Shared Infrastructure)
Purpose: Basic structure required by the plan
- T001 Create alerts namespace directories via keep-files
app/Services/Alerts/.gitkeepandapp/Jobs/Alerts/.gitkeep
Phase 2: Foundational (Blocking Prerequisites)
Purpose: MUST complete before any user story work begins
- T002 Add Alerts capability constants to
app/Support/Auth/Capabilities.php(ALERTS_VIEW,ALERTS_MANAGE) - T003 Update role → capability mapping in
app/Services/Auth/WorkspaceRoleCapabilityMap.phpfor Alerts view/manage - T004 Add audit action IDs to
app/Support/Audit/AuditActionId.phpfor Alerts (destination/rule create/update/delete + enable/disable) - T005 [P] Add operation type labels in
app/Support/OperationCatalog.php(alerts.evaluate,alerts.deliver) - T006 [P] Implement workspace timezone resolver
app/Services/Alerts/WorkspaceTimezoneResolver.php(fallback toconfig('app.timezone')) - T007 Update the Alerts “UI Action Matrix” in
specs/099-alerts-v1-teams-email/spec.mdfor Targets/Rules/Deliveries surfaces (ensure it matches actual Filament actions)
Checkpoint: Capabilities + audit IDs + operation type labels exist.
Phase 3: User Story 1 — Configure alert destinations (Priority: P1) 🎯 MVP
Goal: Workspace members with manage permission can create Teams/email destinations.
Independent Test: Create a Teams destination and an Email destination; ensure secrets are never revealed after save; list/edit/disable.
Tests for User Story 1 ⚠️
- T008 [P] [US1] Add RBAC access tests (404 vs 403) in
tests/Feature/Filament/Alerts/AlertDestinationAccessTest.php - T009 [P] [US1] Add destination CRUD happy-path test in
tests/Feature/Filament/Alerts/AlertDestinationCrudTest.php
Implementation for User Story 1
- T010 [P] [US1] Create migration
database/migrations/*_create_alert_destinations_table.php(workspace_id, type, is_enabled, encrypted config, timestamps) - T011 [P] [US1] Create model
app/Models/AlertDestination.php(workspace relationship; encrypted config cast; hide config) - T012 [P] [US1] Create policy
app/Policies/AlertDestinationPolicy.php(404 non-member; 403 missing capability) - T013 [US1] Register policy mapping in
app/Providers/AuthServiceProvider.php - T014 [US1] Implement Filament resource
app/Filament/Resources/AlertDestinationResource.php(Targets; action-surface contract; max 2 visible row actions) - T015 [US1] Add Alerts navigation entry via Filament cluster (
app/Filament/Clusters/Monitoring/AlertsCluster.php) and register Targets resource under it - T016 [US1] Add audited mutations in
app/Filament/Resources/AlertDestinationResource.phpusingapp/Services/Audit/WorkspaceAuditLogger.php+app/Support/Audit/AuditActionId.php(no secrets) - T017 [US1] Ensure destructive actions confirm in
app/Filament/Resources/AlertDestinationResource.php(->action(...)+->requiresConfirmation())
Checkpoint: Destinations are functional and testable independently.
Phase 4: User Story 2 — Configure alert routing rules (Priority: P2)
Goal: Workspace members with manage permission can define routing rules that send to destination(s).
Independent Test: Create a rule, attach destinations, set tenant allowlist, and verify it is enforced during evaluation.
Tests for User Story 2 ⚠️
- T018 [P] [US2] Add RBAC access tests (404 vs 403) in
tests/Feature/Filament/Alerts/AlertRuleAccessTest.php - T019 [P] [US2] Add rule CRUD test (destinations attach) in
tests/Feature/Filament/Alerts/AlertRuleCrudTest.php
Implementation for User Story 2
- T020 [P] [US2] Create migrations
database/migrations/*_create_alert_rules_table.phpanddatabase/migrations/*_create_alert_rule_destinations_table.php - T021 [P] [US2] Create models
app/Models/AlertRule.phpandapp/Models/AlertRuleDestination.php(casts for allowlist + quiet-hours fields) - T022 [P] [US2] Create policy
app/Policies/AlertRulePolicy.php(404 non-member; 403 missing capability) - T023 [US2] Register policy mapping in
app/Providers/AuthServiceProvider.php - T024 [US2] Implement Filament resource
app/Filament/Resources/AlertRuleResource.php(Rules; action-surface contract; destination picker) - T025 [US2] Implement enable/disable actions with audit logging in
app/Filament/Resources/AlertRuleResource.php(use->action(...)and confirmations) - T026 [US2] Register Rules resource under Alerts cluster navigation (no manual
NavigationItemduplicates)
Checkpoint: Rules are functional and testable independently.
Phase 5: User Story 3 — Deliver alerts safely + review delivery history (Priority: P3)
Goal: Queue-driven delivery with fingerprint dedupe, cooldown suppression, quiet-hours deferral, and a delivery history viewer.
Independent Test: Trigger same event twice within cooldown → only one send + one suppressed record; quiet-hours → deferred; failures retry with exponential backoff then failed.
Tests for User Story 3 ⚠️
- T027 [P] [US3] Add delivery viewer access test in
tests/Feature/Filament/Alerts/AlertDeliveryViewerTest.php - T028 [P] [US3] Add fingerprint/cooldown suppression test in
tests/Unit/Alerts/AlertSuppressionTest.php - T029 [P] [US3] Add quiet-hours deferral test in
tests/Unit/Alerts/AlertQuietHoursTest.php - T030 [P] [US3] Add retry/backoff terminal failure test in
tests/Unit/Alerts/AlertRetryPolicyTest.php
Implementation for User Story 3
- T031 [P] [US3] Create deliveries migration
database/migrations/*_create_alert_deliveries_table.php(workspace_id, tenant_id NOT NULL, status, fingerprint, send_after, attempt_count, last_error_code/message, indexes) - T032 [P] [US3] Create model
app/Models/AlertDelivery.php(statuses incl.suppressed; prunable retention = 90 days default) - T033 [P] [US3] Create policy
app/Policies/AlertDeliveryPolicy.php(view requiresALERTS_VIEW; enforce tenant entitlement; 404/403 semantics) - T034 [US3] Register policy mapping in
app/Providers/AuthServiceProvider.php - T035 [P] [US3] Implement fingerprint + quiet-hours helpers
app/Services/Alerts/AlertFingerprintService.phpandapp/Services/Alerts/AlertQuietHoursService.php - T036 [US3] Implement dispatcher
app/Services/Alerts/AlertDispatchService.php(creates delivery rows; writessuppressedrows) with repo-grounded trigger sources:- High Drift: from
Finding(drift) severity high/critical wherestatus=new(unacknowledged); “newly active/visible” means first appearance (new finding created) - Compare Failed: from failed
OperationRunwheretype=drift_generate_findings - SLA Due: safe no-op until a due-date signal exists in persistence
- High Drift: from
- T037 [P] [US3] Implement Teams sender
app/Services/Alerts/TeamsWebhookSender.php(Laravel HTTP client; no secret logging) - T038 [P] [US3] Implement Email notification
app/Notifications/Alerts/EmailAlertNotification.php(no secrets) - T039 [P] [US3] Implement evaluate job
app/Jobs/Alerts/EvaluateAlertsJob.php(creates deliveries; recordsOperationRuntypealerts.evaluate) - T040 [P] [US3] Create dispatch command
app/Console/Commands/TenantpilotDispatchAlerts.php(tenantpilot:alerts:dispatch) that queues evaluation + delivery work idempotently - T041 [P] [US3] Wire scheduler in
routes/console.phpto runtenantpilot:alerts:dispatchevery minute with->withoutOverlapping() - T042 [P] [US3] Implement delivery job
app/Jobs/Alerts/DeliverAlertsJob.php(sends due deliveries; bounded retries + exponential backoff; recordsOperationRuntypealerts.deliver) - T043 [P] [US3] Implement send service
app/Services/Alerts/AlertSender.php(shared send orchestration for Teams/email; safe error capture; no secret logging) - T044 [US3] Add deliveries Filament resource
app/Filament/Resources/AlertDeliveryResource.php(read-only; inspection affordance; no secrets; list/query must not reveal deliveries for non-entitled tenants) - T045 [US3] Register Deliveries resource under Alerts cluster navigation (no manual
NavigationItemduplicates)
Checkpoint: Delivery pipeline works with retries, suppression, quiet-hours deferral, and safe history.
Phase 6: Polish & Cross-Cutting Concerns
- T046 Update quickstart queue command in
specs/099-alerts-v1-teams-email/quickstart.md(usequeue:work) - T047 Run formatting
vendor/bin/sail bin pint --dirtyonapp/**andtests/** - T048 Run focused tests
vendor/bin/sail artisan test --compactfortests/Feature/Filament/Alerts/**andtests/Unit/Alerts/**
Phase 7: Navigation UX (Monitoring)
- T049 Restructure Alerts navigation under Monitoring (no Overview page; no content sub-navigation; Deliveries is default landing)
- T050 Update OperateHubShell tests to use Alerts cluster landing and follow redirects
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1) → Foundational (Phase 2) → User stories → Polish
User Story Dependencies
- US1 → US2 → US3
Parallel Execution Examples
US1
- Tests: T008 + T009
- Model/migration/policy: T010 + T011 + T012
US2
- Tests: T018 + T019
- Model/migrations/policy: T020 + T021 + T022
US3
- Tests: T027–T030
- Building blocks: T031 + T032 + T035 + T037 + T038 + T039–T041
Implementation Strategy
MVP First (User Story 1 Only)
- Complete Phase 1 + Phase 2
- Complete US1
- Validate via
tests/Feature/Filament/Alerts/AlertDestination*
Incremental Delivery
- Add US2 next, then US3; each story remains independently demoable.