---

description: "Task list for 100 — Alert Targets: Send Test Message + Last Test Status (input: 099.1)"
---

# Tasks: Alert Targets — Send Test Message + Last Test Status (Teams + Email)

**Input**: Design documents from `specs/100-alert-target-test-actions/`

**Prerequisites**:
- `specs/100-alert-target-test-actions/spec.md` (user stories + priorities)
- `specs/100-alert-target-test-actions/plan.md` (implementation approach)
- `specs/100-alert-target-test-actions/research.md` (decisions)
- `specs/100-alert-target-test-actions/data-model.md` (tenantless test deliveries)
- `specs/100-alert-target-test-actions/contracts/` (event type + deep link filters)

**Tests**: REQUIRED (Pest) for all runtime behavior changes.

## Format: `- [ ] [TaskID] [P?] [Story?] Description with file path`

- **[P]**: can run in parallel (different files, no dependencies on incomplete tasks)
- **[US1] [US2] [US3]**: user story mapping (required for story phases)

---

## Phase 1: Setup (Shared)

**Purpose**: Ensure local dev/test workflow is concrete for this feature.

- [X] T001 Update test quickstart commands in specs/100-alert-target-test-actions/quickstart.md

---

## Phase 2: Foundational (Blocking Prerequisites)

**Purpose**: Enable tenantless test deliveries + keep workspace isolation and RBAC correct.

- [X] T002 Create migration to allow tenantless test deliveries + add supporting index in database/migrations/2026_02_18_000001_make_alert_deliveries_tenant_and_rule_nullable_for_test_deliveries.php
- [X] T003 Create tenant-optional workspace isolation trait in app/Support/Concerns/DerivesWorkspaceIdFromTenantWhenPresent.php
- [X] T004 Switch AlertDelivery to tenant-optional isolation in app/Models/AlertDelivery.php
- [X] T005 Add AlertDeliveryFactory support for tenantless deliveries in database/factories/AlertDeliveryFactory.php
- [X] T006 Add audit action id for test request in app/Support/Audit/AuditActionId.php

**Checkpoint**: Tenantless `alert_deliveries` records can be created safely, and audit IDs exist.

---

## Phase 3: User Story 1 — Send a test message for a target (Priority: P1) 🎯 MVP

**Goal**: Capability-gated “Send test message” action creates a test delivery record and queues delivery asynchronously.

**Independent Test**: A manage-capable workspace member can request a test send; a new `alert_deliveries` row exists with `event_type=alerts.test`, and the queue has a `DeliverAlertsJob`.

### Tests (write first)

- [X] T007 [P] [US1] Add send-test action happy-path test in tests/Feature/Alerts/AlertDestinationSendTestMessageTest.php
- [X] T008 [P] [US1] Add rate-limit refusal test in tests/Feature/Alerts/AlertDestinationSendTestMessageTest.php
- [X] T009 [P] [US1] Add authorization (readonly forbidden) test in tests/Feature/Alerts/AlertDestinationSendTestMessageTest.php
- [X] T010 [P] [US1] Add non-member deny-as-not-found (404) regression test in tests/Feature/Alerts/AlertDestinationSendTestMessageTest.php
- [X] T011 [P] [US1] Add audit log assertion test in tests/Feature/Alerts/AlertDestinationSendTestMessageTest.php
- [X] T012 [P] [US1] Add confirmation requirement test for the Filament action in tests/Feature/Alerts/AlertDestinationSendTestMessageTest.php

### Implementation

- [X] T013 [US1] Add canonical test event type constant in app/Models/AlertDelivery.php
- [X] T014 [US1] Implement test delivery creation service in app/Services/Alerts/AlertDestinationTestMessageService.php
- [X] T015 [US1] Add "Send test message" header action on edit page in app/Filament/Resources/AlertDestinationResource/Pages/EditAlertDestination.php

**Checkpoint**: US1 passes its feature tests and performs no outbound calls in the request thread.

---

## Phase 4: User Story 2 — See the last test status at a glance (Priority: P2)

**Goal**: Show derived “Last test: Never/Sent/Failed/Pending” badge with deterministic, DB-only semantics.

**Independent Test**: With controlled `alert_deliveries` rows, the target page shows the correct derived status and timestamp without external calls.

### Tests (write first)

- [X] T016 [P] [US2] Add badge semantics tests for delivery + last-test domains in tests/Feature/Badges/AlertDeliveryAndLastTestBadgeSemanticsTest.php
- [X] T017 [P] [US2] Add derived last-test mapping test (never/sent/failed/pending) in tests/Feature/Alerts/AlertDestinationLastTestStatusTest.php

### Implementation

- [ ] T018 [P] [US2] Add last-test status enum + result DTO in app/Support/Alerts/AlertDestinationLastTestStatus.php
- [ ] T019 [US2] Implement last-test resolver (latest alerts.test row) in app/Services/Alerts/AlertDestinationLastTestResolver.php
- [ ] T020 [US2] Add badge domains for alert delivery + destination last-test in app/Support/Badges/BadgeDomain.php
- [ ] T021 [US2] Register new badge mappers in app/Support/Badges/BadgeCatalog.php
- [ ] T022 [P] [US2] Implement badge mapper for delivery status in app/Support/Badges/Domains/AlertDeliveryStatusBadge.php
- [ ] T023 [P] [US2] Implement badge mapper for destination last-test status in app/Support/Badges/Domains/AlertDestinationLastTestStatusBadge.php
- [ ] T024 [US2] Refactor delivery status badges to use BadgeCatalog in app/Filament/Resources/AlertDeliveryResource.php
- [ ] T025 [US2] Add read-only View page for alert destinations in app/Filament/Resources/AlertDestinationResource/Pages/ViewAlertDestination.php
- [ ] T026 [US2] Register view page and route view-only users from list in app/Filament/Resources/AlertDestinationResource.php
- [ ] T027 [US2] Render “Last test” badge + timestamp on view page in app/Filament/Resources/AlertDestinationResource/Pages/ViewAlertDestination.php
- [ ] T028 [US2] Render “Last test” badge + timestamp on edit page in app/Filament/Resources/AlertDestinationResource/Pages/EditAlertDestination.php

**Checkpoint**: US2 is fully readable by view-only users (via View page) and meets BADGE-001.

---

## Phase 5: User Story 3 — Jump from target to the relevant delivery details (Priority: P3)

**Goal**: Provide a “View last delivery” deep link into the Deliveries viewer filtered by `alerts.test` and destination.

**Independent Test**: When at least one test delivery exists, the link appears and routes to `/admin/alert-deliveries` with the correct `filters[...]` query string.

### Tests (write first)

- [X] T029 [P] [US3] Add deep-link visibility + URL contract test in tests/Feature/Alerts/AlertDestinationViewLastDeliveryLinkTest.php
- [X] T030 [P] [US3] Add deliveries viewer filter coverage test in tests/Feature/Alerts/AlertDeliveryDeepLinkFiltersTest.php

### Implementation

- [X] T031 [US3] Add table filters for event_type + alert_destination_id in app/Filament/Resources/AlertDeliveryResource.php
- [X] T032 [US3] Allow tenantless deliveries in deliveries list query in app/Filament/Resources/AlertDeliveryResource.php
- [X] T033 [US3] Update tenant entitlement policy to allow tenantless delivery records in app/Policies/AlertDeliveryPolicy.php
- [X] T034 [US3] Add "View last delivery" header action (view page) in app/Filament/Resources/AlertDestinationResource/Pages/ViewAlertDestination.php
- [X] T035 [US3] Add "View last delivery" header action (edit page) in app/Filament/Resources/AlertDestinationResource/Pages/EditAlertDestination.php

**Checkpoint**: US3 deep links match the contract in specs/100-alert-target-test-actions/contracts/filament-deep-link-filters.md.

---

## Phase 6: Polish & Cross-Cutting Concerns

- [X] T036 [P] Run Pint on changed files with vendor/bin/sail bin pint --dirty
- [X] T037 Run focused test suite for this feature with vendor/bin/sail artisan test --compact tests/Feature/Alerts/AlertDestinationSendTestMessageTest.php
- [X] T038 Run focused badge tests with vendor/bin/sail artisan test --compact tests/Feature/Badges/AlertDeliveryAndLastTestBadgeSemanticsTest.php

---

## Dependencies & Execution Order

### Dependency graph (user stories)

```mermaid
graph TD
  F[Phase 2: Foundational] --> US1[US1: Send test message]
  F --> US2[US2: Last test status]
  US2 --> US3[US3: View last delivery deep link]
```

- **Foundational (Phase 2)** blocks all user stories.
- **US1** can be delivered as MVP after Phase 2.
- **US2** adds read-only visibility and centralized badge semantics.
- **US3** depends on US2 resolver/view surface (or duplicate a small existence query if needed).

---

## Parallel execution examples

### US1

- `T007–T012` can be written in parallel (single test file, but separate assertions can be split across commits).
- `T013` (model constant) and `T014` (service) can be done before `T015` (Filament action).

### US2

- `T022` and `T023` (badge mappers) can be implemented in parallel.
- `T018` (enum/DTO) and `T019` (resolver) can be done before wiring UI.

### US3

- `T031–T033` (deliveries viewer plumbing) can proceed in parallel with `T034–T035` (target header actions) once the resolver is available.

---

## Implementation strategy

### MVP first

1. Complete Phase 2 (Foundational)
2. Implement and ship US1 (Send test message)
3. Validate with focused tests

### Incremental delivery

- Add US2 (Last test status + View page) after US1 is stable
- Add US3 (Deep link + deliveries filters) last
