# Spec 321 Decision: Alerts / Audit Log Environment Filter Contract **Status**: Draft decision artifact **Date**: 2026-05-17 **Branch**: `321-alerts-audit-log-environment-filter-contract-decision` ## Decision Summary Alerts and Audit Log remain Workspace-owned surfaces. The canonical Environment filter key is: ```text environment_id ``` No legacy aliases are accepted. No remembered Environment fallback is accepted. No Filament tenant fallback is accepted. ## Surface Decisions | Surface | Current behavior | Data model supports environment attribution? | Chosen contract | Reason | Implementation impact | Test impact | | --- | --- | --- | --- | --- | --- | --- | | Alerts overview / Alert Center | Registered workspace hub, but Spec 318 found `/admin/alerts?environment_id=...` redirects/drops query or lacks full filter contract. | Partially, through environment-attributable alert delivery signal. Alert rules/destinations are workspace configuration. | `environment_filterable_workspace_hub` | Alerts are an operational signal hub. Operators need "show me alerts for this Environment" behavior, and the delivery signal has reliable `managed_environment_id`. | Resolve canonical `environment_id`, show shared chip, scope environment-attributable KPI/signal data, keep shell Workspace-only, clear with shared resetter. | Clean URL, filtered URL, visible chip, clear, reload, legacy alias rejection, cross-workspace guard. | | Alert Deliveries | Registered workspace hub/table resource. Has current table filter for `managed_environment_id`, but no canonical visible workspace-hub chip contract. | Yes. `alert_deliveries.managed_environment_id` exists, is nullable, workspace-constrained, and indexed. | `environment_filterable_workspace_hub` | Deliveries are the table-backed alert event/signal surface and can be filtered without inference. | Apply canonical `environment_id` to query/table state using shared resolver, render chip, clear stale Filament/session table filters. | Filtered rows prove data scope; clear and reload safety; legacy aliases ignored. | | Alert Rules | Registered under Alerts. Workspace configuration surface. Uses workspace-level rule configuration, including targeting settings. | No page-level filter attribution. Rule targeting config is not the same as page ownership/filter state. | `configuration_workspace_surface` | Rules configure workspace alert behavior and should not appear Environment-owned or Environment-filtered. | Do not render chip. Do not accept `environment_id` as filter state. Keep clean links from navigation/CTAs. | Assert `environment_id` does not create chip/filter and Environment CTAs do not emit filters to this surface. | | Alert Destinations | Registered under Alerts. Workspace configuration surface. | No. Destinations are workspace notification targets. | `configuration_workspace_surface` | Notification destinations are workspace-level configuration, not Environment-scoped operational signal. | Do not render chip. Do not accept `environment_id` as filter state. Keep clean links from navigation/CTAs. | Assert `environment_id` does not create chip/filter and Environment CTAs do not emit filters to this surface. | | Audit Log | Registered workspace hub. Spec 318 found `/admin/audit-log?environment_id=...` preserves query but shows no visible chip. | Yes. `audit_logs.managed_environment_id` exists, is nullable, indexed, and tied to workspace attribution. | `environment_filterable_workspace_hub` | Audit Log is a workspace governance surface, but many records are reliably Environment-attributable. Filtering by direct attribution is useful and safe. | Resolve canonical `environment_id`, filter by `audit_logs.managed_environment_id`, render chip, keep shell Workspace-only, clear stale query/table/session state. | Clean URL, filtered URL, visible chip, filtered rows, selected event consistency, clear, reload, legacy alias rejection, cross-workspace guard. | | Audit event detail / selected event state | Same Audit Log page, usually selected through query/state. | Yes when the selected event row has `managed_environment_id`. | `environment_filterable_workspace_hub` | Event detail is metadata inside the Audit Log surface, not a separate Environment-owned page. | If a filter is active, selected event state must remain inside the filtered query scope or be neutralized. Show Environment metadata as event data, not shell ownership. | Assert selected event outside active Environment filter is not shown as the selected detail. | | Environment Dashboard CTAs to Alerts / Alert Deliveries / Audit Log | Must be inspected during implementation. | Yes for the filterable destinations above. | `environment_filterable_workspace_hub` destinations use canonical `environment_id`. | Environment-origin navigation may preserve Environment focus only when the destination supports the full filter contract. | Add or update links to use `environment_id` only. No legacy params. | Assert CTAs use canonical `environment_id` and no legacy aliases. | | Environment Dashboard CTAs to Alert Rules / Alert Destinations | Must be inspected during implementation. | No page-level filter attribution. | `configuration_workspace_surface` destinations use clean workspace links or are omitted. | Configuration surfaces should not imply Environment-specific state. | Remove Environment filter params from these destinations. | Assert CTAs emit no Environment filter params. | ## Final Contract Values Allowed values used in this decision: ```text environment_filterable_workspace_hub configuration_workspace_surface ``` No surface in scope remains ambiguous. ## Runtime Constraints - Shell remains Workspace-only for all surfaces in this decision. - Filterable surfaces accept only `environment_id`. - Legacy aliases are invalid as Environment filter input. - Cross-workspace or unauthorized Environment IDs must be rejected safely. - Clear behavior must remove URL, table, deferred table, session, and page Environment filter state. - No migrations are expected. ## Reopen Conditions Update this decision before implementation continues if: - Runtime discovery shows `audit_logs.managed_environment_id` or `alert_deliveries.managed_environment_id` is not reliable. - A migration or new persisted attribution field becomes necessary. - A new Alert or Audit sub-surface is discovered that cannot be classified by this artifact.