# Feature Specification: Alert Targets Test Actions

**Feature Branch**: `feat/100-alert-target-test-actions`  
**Created**: 2026-02-18  
**Status**: Draft  
**Input**: User description: "099.1 — Alert Targets: Send Test Message + Last Test Status (Teams + Email)"

## Spec Scope Fields *(mandatory)*

- **Scope**: workspace
- **Primary Routes**: Alert Target View, Alert Target Edit, Deliveries viewer (filtered deep links)
- **Data Ownership**:
  - Workspace-owned: alert targets
  - Tenant-owned: alert delivery history (non-test)
  - Workspace-scoped: test deliveries (`event_type=alerts.test`) may be tenantless (`tenant_id` nullable)
- **RBAC**:
  - Workspace membership is required to access Alert Targets and Deliveries.
  - Users with manage capability can request a test send.
  - Users with view-only capability can see test status but cannot request a test send.

For canonical-view specs, the spec MUST define:

- **Default filter behavior when tenant-context is active**: Not applicable (workspace scope).
- **Explicit entitlement checks preventing cross-tenant leakage**: Targets and deliveries are only visible within the current workspace; non-members must not receive any existence hints.

## Clarifications

### Session 2026-02-18

- Q: Which timestamps should the “Last test … at <timestamp>” subtext use? → A: Sent → `sent_at`; Failed → `updated_at`; Pending → `send_after`.
- Q: What should the test-send rate limit be per target? → A: 60 seconds per target.
- Q: What should “View last delivery” open? → B: Deliveries list viewer filtered to `alert_destination_id` + `event_type=alerts.test`.
- Q: When should “View last delivery” be shown on the Alert Target pages? → B: Show only if at least one test delivery exists.

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Send a test message for a target (Priority: P1)

As an admin, I want to send a test alert to a configured Alert Target so I can verify the integration works before relying on it in production.

**Why this priority**: This is the fastest way to detect misconfiguration (wrong destination, blocked network path, invalid credentials) and reduce support/incident time.

**Independent Test**: Can be fully tested by requesting a test send and confirming a new test delivery record exists and can be inspected.

**Acceptance Scenarios**:

1. **Given** I am a workspace member with manage permission, **When** I confirm “Send test message” on an Alert Target, **Then** the system creates exactly one new test delivery record for that target and indicates the request was queued.
2. **Given** I am a workspace member without manage permission, **When** I attempt to execute “Send test message”, **Then** the action is blocked and no delivery record is created.
3. **Given** I have requested a test very recently for the same target, **When** I attempt another test immediately, **Then** the system refuses the request and does not create a new delivery record.

---

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

As an admin, I want to see whether the last test send for an Alert Target succeeded, failed, was never executed, or is still pending so I can assess health without digging through deliveries.

**Why this priority**: Health visibility reduces troubleshooting time and prevents silent failures.

**Independent Test**: Can be fully tested by viewing a target with (a) no test deliveries, (b) a successful test delivery, (c) a failed test delivery and verifying the badge and timestamp.

**Acceptance Scenarios**:

1. **Given** a target has no test delivery records, **When** I open the target View or Edit page, **Then** I see a badge “Last test: Never”.
2. **Given** the most recent test delivery record is successful, **When** I open the target View or Edit page, **Then** I see a badge “Last test: Sent” and an associated timestamp.
3. **Given** the most recent test delivery record is failed, **When** I open the target View or Edit page, **Then** I see a badge “Last test: Failed” and an associated timestamp.
4. **Given** the most recent test delivery record is queued or deferred, **When** I open the target View or Edit page, **Then** I see a badge “Last test: Pending”.

---

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

As an admin, I want a quick link from the Alert Target to the most recent test delivery details so I can troubleshoot outcomes efficiently.

**Why this priority**: It reduces clicks and prevents mistakes when searching through delivery history.

**Independent Test**: Can be tested by clicking a “View last delivery” link and verifying the deliveries view is pre-filtered for this target and the test event type.

**Acceptance Scenarios**:

1. **Given** a target has at least one test delivery record, **When** I click “View last delivery” from the target page, **Then** I am taken to the deliveries list viewer scoped to the same workspace and filtered to that target and the test event type.

### Edge Cases

- Target exists but has never been tested.
- Target has multiple test deliveries; only the most recent one is used for status.
- The most recent test delivery is queued/deferred; status must show pending without implying success.
- Users without workspace membership attempt to access targets or deliveries (must be deny-as-not-found).
- Failure details must not expose secrets (destination URLs, recipients).
- Rapid repeated test requests (anti-spam / rate limiting) must not create additional delivery records.

## Requirements *(mandatory)*

**Constitution alignment (required):** This feature introduces a user-triggered action that creates a delivery record and schedules work to be executed asynchronously.
The spec requires: confirmation, RBAC enforcement, anti-spam rate limiting, audit logging, tenant/workspace isolation, and tests.

**Constitution alignment (RBAC-UX):**

- Authorization planes involved: Admin UI (workspace-scoped).
- 404 vs 403 semantics:
  - Non-member / not entitled to workspace scope → 404 (deny-as-not-found)
  - Workspace member but missing manage capability → 403 for executing the test action
- All mutations (test request) require server-side authorization.

**Constitution alignment (BADGE-001):** “Last test: Sent/Failed/Pending/Never” MUST use centralized badge semantics (no ad-hoc mappings).

**Constitution alignment (Filament Action Surfaces):** This feature modifies Filament pages (Alert Target view/edit) and therefore includes a UI Action Matrix.

### Functional Requirements

- **FR-001 (Derived status, no new fields)**: The system MUST display a “Last test status” indicator on Alert Target View and Edit pages derived solely from existing alert delivery records.
- **FR-002 (Deterministic selection)**: The “Last test status” MUST be derived from the single most recent delivery record for the given target where the delivery event type is “alerts.test”, ordered by `created_at` (desc) then `id` (desc).
- **FR-003 (Status mapping)**: The system MUST map the most recent test delivery record to one of: Never (no record), Sent, Failed, or Pending.
- **FR-004 (Timestamp semantics)**: The UI MUST display a timestamp that reflects when the outcome occurred: Sent → `sent_at`; Failed → `updated_at`; Pending → `send_after`.
- **FR-005 (DB-only UI)**: Requesting a test send MUST not perform synchronous external delivery attempts in the user’s request/response flow.
- **FR-006 (Confirmation)**: The “Send test message” action MUST require explicit confirmation, explaining that it will contact the configured destination.
- **FR-007 (Anti-spam rate limit)**: The system MUST prevent repeated test requests for the same target within 60 seconds.
- **FR-008 (RBAC)**: Only workspace members with manage permission can request a test send; view-only users can see the action but cannot execute it.
- **FR-009 (Deny-as-not-found)**: Users without workspace membership MUST receive deny-as-not-found behavior for targets and deliveries.
- **FR-010 (Auditability)**: The system MUST record an audit event when a test is requested, without including destination secrets.
- **FR-011 (Deep link)**: The system SHOULD provide a “View last delivery” link from the target to the Deliveries list viewer filtered to that target and `event_type=alerts.test`.
- **FR-012 (Deep link visibility)**: The system SHOULD show “View last delivery” only when at least one test delivery exists for the target.

### Assumptions

- Alerts v1 already provides Alert Targets, Alert Deliveries, and a Deliveries viewer.
- A test send is represented as a delivery record with event type “alerts.test”.

### Non-Goals

- No new database fields for storing “last test status”.
- No bulk “test all targets” feature.
- No destination setup wizard.
- No per-row list view badge (avoids performance/N+1 concerns in v1).

## UI Action Matrix *(mandatory when Filament is changed)*

| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Alert Target (View) | Alert Target view page | Send test message (confirm, manage-only), View last delivery (navigate) | Not changed in this feature | Not changed in this feature | None | None | Same as Header Actions | Not applicable | Yes | View-only users see disabled “Send test message”. |
| Alert Target (Edit) | Alert Target edit page | Send test message (confirm, manage-only), View last delivery (navigate) | Not changed in this feature | Not changed in this feature | None | None | Same as Header Actions | Existing save/cancel | Yes | “Last test status” appears above the form. |
| Deliveries viewer | Deliveries list/details | None (existing) | Filtered via deep link | Existing row actions | Existing | Existing | Existing | Not applicable | Existing | Must remain workspace-scoped. |

### Key Entities *(include if feature involves data)*

- **Alert Target**: A destination configuration for alerts (e.g., Teams webhook or email destination), scoped to a workspace.
- **Alert Delivery**: A delivery attempt record that captures event type (including “alerts.test”), status, timestamps, and safe diagnostic details.
- **Audit Event**: A workspace-scoped audit entry representing a user-triggered test request.

## Success Criteria *(mandatory)*

### Measurable Outcomes

- **SC-001**: An admin can determine “last test status” for a target within 5 seconds from the target page.
- **SC-002**: An admin can request a test send in under 30 seconds (including confirmation) without leaving the target page.
- **SC-003**: A test request always results in either (a) a new test delivery record being created, or (b) a clear refusal due to rate limiting or missing permissions.
- **SC-004**: Troubleshooting time for “alerts not delivered” issues is reduced because the last test outcome and a direct link to details are immediately available.
