TenantAtlas/specs/100-alert-target-test-actions/data-model.md
ahmido d49d33ac27 feat(alerts): test message + last test status + deep links (#122)
Implements feature 100 (Alert Targets):

- US1: “Send test message” action (RBAC + confirmation + rate limit + audit + async job)
- US2: Derived “Last test” status badge (Never/Sent/Failed/Pending) on view + edit surfaces
- US3: “View last delivery” deep link + deliveries viewer filters (event_type, destination) incl. tenantless test deliveries

Tests:
- Full suite green (1348 passed, 7 skipped)
- Added focused feature tests for send test, last test resolver/badges, and deep-link filters

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #122
2026-02-18 23:12:38 +00:00

2.6 KiB

Phase 1 — Data Model (099.1 Add-on)

Entities

AlertDestination (existing)

  • Table: alert_destinations
  • Ownership: workspace-owned
  • Key fields (relevant here):
    • id
    • workspace_id
    • type (e.g. Teams webhook, Email)
    • config (Teams webhook URL or list of recipients)
    • is_enabled

AlertDelivery (existing, extended for test sends)

  • Table: alert_deliveries

  • Ownership:

    • v1 deliveries for real alerts remain tenant-associated
    • test deliveries for this add-on are tenantless (workspace-only)
  • Key fields (relevant here):

    • id
    • workspace_id (required)
    • tenant_id (nullable for test deliveries)
    • alert_rule_id (nullable for test deliveries)
    • alert_destination_id (required)
    • event_type (string, includes alerts.test)
    • status (queued|deferred|sent|failed|suppressed|canceled)
    • send_after (nullable; used for deferral/backoff)
    • sent_at (nullable)
    • attempt_count
    • last_error_code, last_error_message (sanitized)
    • payload (array/json)
    • timestamps: created_at, updated_at

Relationships

  • AlertDeliveryAlertDestination (belongsTo via alert_destination_id)
  • AlertDeliveryAlertRule (belongsTo via alert_rule_id, nullable)
  • AlertDeliveryTenant (belongsTo via tenant_id, nullable)

New derived concepts (no storage)

LastTestStatus (derived)

Derived from the most recent alert_deliveries record where:

  • alert_destination_id = {destination}
  • event_type = 'alerts.test'

Mapping:

  • no record → Never
  • status in (queued, deferred)Pending
  • status = sentSent
  • status = failedFailed

Associated timestamp (derived):

  • Sent → sent_at
  • Failed → updated_at
  • Pending → send_after (fallback created_at)

Validation / invariants

  • Creating a test delivery requires:
    • alert_destination_id exists and belongs to current workspace
    • destination is enabled (if disabled, refuse test request)
    • rate limit: no prior test delivery for this destination in last 60 seconds
  • Test delivery record must not persist secrets in payload or error message.

Migration notes

To support tenantless test deliveries:

  • Make alert_deliveries.tenant_id nullable and adjust the FK behavior.
  • Make alert_deliveries.alert_rule_id nullable and adjust the FK behavior.
  • Add or adjust indexes for efficient status lookup per destination + event type:
    • (workspace_id, alert_destination_id, event_type, created_at)

(Exact migration steps and DB constraint changes are specified in the implementation plan.)