# Phase 0 — Research (099.1 Add-on) This research resolves the open technical questions from the feature spec and anchors decisions to existing code in this repository. ## Decision 1 — Where “Alert Target View/Edit” lives in code - **Decision**: Implement “Last test status” + “Send test message” on the Alert Target **Edit** page only. - **Rationale**: The current Filament resource for alert targets is `AlertDestinationResource` and only defines `index/create/edit` pages (no View page). - **Alternatives considered**: - Add a new View page for `AlertDestinationResource` (rejected: expands UX surface and is not required for this add-on). ## Decision 2 — Canonical event type string - **Decision**: Use a single canonical event type string for test sends: `alerts.test`. - **Rationale**: The add-on spec requires deriving status from `alert_deliveries.event_type`. Keeping this string stable allows deterministic filtering and deep links. - **Alternatives considered**: - Use `test` or `destination_test` (rejected: deviates from spec and makes intent less explicit). ## Decision 3 — Timestamp mapping vs actual schema - **Decision**: Map timestamps using existing columns: - **Sent** → `sent_at` - **Failed** → `updated_at` (no `failed_at` column exists) - **Pending** → `send_after` if set, else `created_at` - **Rationale**: The `alert_deliveries` schema only has `send_after`, `sent_at`, and `updated_at`. The spec’s `deliver_at` / `failed_at` naming is treated as conceptual. - **Alternatives considered**: - Add `failed_at` / `deliver_at` columns (rejected: violates “no new DB fields”). ## Decision 4 — How to represent test deliveries given current tenant enforcement - **Decision**: Store test deliveries in `alert_deliveries` as **workspace-scoped, tenantless** records: - `workspace_id` set - `tenant_id` nullable - `alert_rule_id` nullable - `alert_destination_id` set - **Rationale**: - Alert targets (`AlertDestination`) are workspace-owned and accessible without a selected tenant. - Current enforcement (`DerivesWorkspaceIdFromTenant`) requires a tenant and would make test deliveries invisible/uneven across users due to tenant entitlements. - Deliver job execution (`DeliverAlertsJob`) does not require a tenant; it only needs the destination + payload. - **Alternatives considered**: - Pick an arbitrary tenant ID for test deliveries (rejected: would be invisible to some operators and breaks “single truth” per target). - Create a synthetic “workspace tenant” record (rejected: adds data-model complexity). ## Decision 5 — Deep link mechanics for the Deliveries viewer - **Decision**: Deep link into `AlertDeliveryResource` list view using Filament v5 filter query-string binding: - `?filters[event_type][value]=alerts.test&filters[alert_destination_id][value]={DESTINATION_ID}` - **Rationale**: Filament v5 `ListRecords` binds `tableFilters` to the URL under the `filters` key; `SelectFilter` uses `value`. - **Alternatives considered**: - Custom dedicated “Test deliveries” page (rejected: new surface beyond spec). ## Decision 6 — Badge semantics centralization (BADGE-001) - **Decision**: Introduce centralized badge domains/mappers for: - `AlertDeliveryStatus` (queued/deferred/sent/failed/suppressed/canceled) - `AlertDestinationLastTestStatus` (never/pending/sent/failed) - **Rationale**: Current `AlertDeliveryResource` implements ad-hoc status label/color helpers. This add-on must comply with BADGE-001 and should not add more local mappings. - **Alternatives considered**: - Keep ad-hoc mappings in the new code (rejected: violates BADGE-001). ## Decision 7 — OperationRun usage - **Decision**: Do **not** create a new per-test `OperationRun`. - **Rationale**: - The user-triggered action is DB-only (authorization + rate limit + create delivery + audit), typically <2s. - The external work runs via the existing `alerts.deliver` operation run (created by `DeliverAlertsJob`). - **Alternatives considered**: - Create a dedicated operation run type (rejected: higher complexity for small UX add-on).