TenantAtlas/specs/099-alerts-v1-teams-email/tasks.md
ahmido 3ed275cef3 feat(alerts): Monitoring cluster + v1 resources (spec 099) (#121)
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
2026-02-18 15:20:43 +00:00

10 KiB
Raw Blame History

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/.gitkeep and app/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.php for Alerts view/manage
  • T004 Add audit action IDs to app/Support/Audit/AuditActionId.php for 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 to config('app.timezone'))
  • T007 Update the Alerts “UI Action Matrix” in specs/099-alerts-v1-teams-email/spec.md for 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.php using app/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.php and database/migrations/*_create_alert_rule_destinations_table.php
  • T021 [P] [US2] Create models app/Models/AlertRule.php and app/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 NavigationItem duplicates)

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 requires ALERTS_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.php and app/Services/Alerts/AlertQuietHoursService.php
  • T036 [US3] Implement dispatcher app/Services/Alerts/AlertDispatchService.php (creates delivery rows; writes suppressed rows) with repo-grounded trigger sources:
    • High Drift: from Finding (drift) severity high/critical where status=new (unacknowledged); “newly active/visible” means first appearance (new finding created)
    • Compare Failed: from failed OperationRun where type=drift_generate_findings
    • SLA Due: safe no-op until a due-date signal exists in persistence
  • 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; records OperationRun type alerts.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.php to run tenantpilot:alerts:dispatch every minute with ->withoutOverlapping()
  • T042 [P] [US3] Implement delivery job app/Jobs/Alerts/DeliverAlertsJob.php (sends due deliveries; bounded retries + exponential backoff; records OperationRun type alerts.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 NavigationItem duplicates)

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 (use queue:work)
  • T047 Run formatting vendor/bin/sail bin pint --dirty on app/** and tests/**
  • T048 Run focused tests vendor/bin/sail artisan test --compact for tests/Feature/Filament/Alerts/** and tests/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: T027T030
  • Building blocks: T031 + T032 + T035 + T037 + T038 + T039T041

Implementation Strategy

MVP First (User Story 1 Only)

  1. Complete Phase 1 + Phase 2
  2. Complete US1
  3. Validate via tests/Feature/Filament/Alerts/AlertDestination*

Incremental Delivery

  • Add US2 next, then US3; each story remains independently demoable.