# Implementation Plan: Alerts / Audit Log Environment Filter Contract Decision **Branch**: `321-alerts-audit-log-environment-filter-contract-decision` **Date**: 2026-05-17 **Spec**: `specs/321-alerts-audit-log-environment-filter-contract-decision/spec.md` **Decision Artifact**: `specs/321-alerts-audit-log-environment-filter-contract-decision/decision.md` **Status**: Draft ## Summary Make Alerts and Audit Log unambiguous Workspace-owned surfaces. Alerts overview, Alert Deliveries, and Audit Log become canonical `environment_id` filterable workspace hubs with visible chip and clear behavior. Alert Rules and Alert Destinations remain workspace-level configuration surfaces and must not accept Environment filter state. No runtime implementation is performed by this preparation. Runtime work must follow this plan and the tasks file. ## Technical Context **Language / Version**: PHP 8.4.15 **Primary Framework**: Laravel 12.52.0 **Admin UI**: Filament 5.2.1 **Reactive Layer**: Livewire 4.1.4 **Database**: PostgreSQL **Testing**: Pest 4.3.1, PHPUnit 12 **Local Runtime**: Laravel Sail first Relevant package posture: - Filament v5 requires Livewire v4.0+; this app uses Livewire 4.1.4. - Laravel 12 provider registration remains in `apps/platform/bootstrap/providers.php`; this spec does not add a panel provider. - No frontend asset registration or `filament:assets` deployment change is planned. ## Constitutional Check ### Pre-Implementation - **LEAN-001 Hard Cutover**: Pass. No legacy aliases, compatibility redirects, or dual contracts are allowed. - **Tenant / Workspace Isolation**: Pass with implementation requirement. `environment_id` must be resolved through workspace and user access checks. - **Shared Pattern First**: Pass. Reuse `WorkspaceHubEnvironmentFilter`, `WorkspaceHubFilterStateResetter`, clear trait, and shared chip partial. - **Proportionality**: Pass. No new persisted entity, enum/status family, taxonomy, framework, migration, or dependency. - **Test Governance**: Pass with required tests and browser verification listed below. - **Spec Candidate Gate**: Pass. User manually promoted a direct follow-up to Spec 318 findings; completed specs 313-320 were inspected as context. ### Post-Design - No constitutional violation is expected. - If implementation discovers missing reliable Environment attribution, the spec and decision artifact must be updated before runtime work continues. - If implementation requires a new persisted attribute or abstraction, the proportionality review must be reopened before code changes continue. ## Project Structure ### Documentation / Spec Artifacts ```text specs/321-alerts-audit-log-environment-filter-contract-decision/spec.md specs/321-alerts-audit-log-environment-filter-contract-decision/plan.md specs/321-alerts-audit-log-environment-filter-contract-decision/tasks.md specs/321-alerts-audit-log-environment-filter-contract-decision/decision.md specs/321-alerts-audit-log-environment-filter-contract-decision/checklists/requirements.md specs/321-alerts-audit-log-environment-filter-contract-decision/artifacts/screenshots/ ``` ### Runtime Areas For Later Implementation ```text apps/platform/app/Support/Navigation/WorkspaceHubRegistry.php apps/platform/app/Support/Navigation/AdminSurfaceScope.php apps/platform/app/Support/Navigation/WorkspaceSidebarNavigation.php apps/platform/app/Support/Navigation/WorkspaceHubEnvironmentFilter.php apps/platform/app/Support/Navigation/WorkspaceHubFilterStateResetter.php apps/platform/app/Filament/Concerns/ClearsWorkspaceHubEnvironmentFilterState.php apps/platform/app/Filament/Pages/Monitoring/Alerts.php apps/platform/app/Filament/Widgets/AlertsKpiHeader.php apps/platform/app/Filament/Resources/AlertDeliveryResource.php apps/platform/app/Filament/Resources/AlertRuleResource.php apps/platform/app/Filament/Resources/AlertDestinationResource.php apps/platform/app/Filament/Pages/Monitoring/AuditLog.php apps/platform/resources/views/filament/pages/monitoring/alerts.blade.php apps/platform/resources/views/filament/pages/monitoring/audit-log.blade.php apps/platform/resources/views/filament/partials/workspace-hub-environment-filter-chip.blade.php apps/platform/app/Support/ManagedEnvironmentLinks.php apps/platform/app/Support/Operations/OperationRunLinks.php apps/platform/tests/Feature/Navigation apps/platform/tests/Feature/Filament ``` ## Data Model Decision No migration is planned. Discovered attribution support: - `alert_deliveries.managed_environment_id`: reliable nullable Environment attribution with workspace constraint and index. - `audit_logs.managed_environment_id`: reliable nullable Environment attribution with workspace constraint and indexes. - `alert_rules`: workspace configuration; no page-level Environment filter contract. - `alert_destinations`: workspace configuration; no page-level Environment filter contract. Filtering must use direct normalized attribution only. It must not infer Environment from text, labels, JSON payload contents, actor/session context, remembered state, provider tenant IDs, or Filament tenant context. ## UI / Filament Plan ### Alerts Overview - Keep Workspace-only shell. - Resolve canonical `environment_id` if present and valid. - Render the shared Environment filter chip in filtered state. - Ensure KPI/header data that is Environment-attributable is scoped by the active filter. - Ensure configuration counts are either not presented as Environment-filtered or are clearly workspace-level. - Link to Alert Deliveries with `environment_id` when filtered. - Link to Alert Rules and Alert Destinations without Environment filter params. ### Alert Deliveries - Keep table-backed workspace hub behavior. - Apply `environment_id` as canonical URL filter and synchronize table query state without accepting legacy query aliases. - Use visible chip and shared clear behavior. - Filter rows by `managed_environment_id`. ### Alert Rules / Alert Destinations - Remain workspace configuration surfaces. - Do not render Environment filter chip. - Do not accept `environment_id` as filter state. - Keep sidebar/global navigation clean. ### Audit Log - Keep Workspace-only shell. - Resolve canonical `environment_id` if present and valid. - Render visible shared chip in filtered state. - Filter rows by `audit_logs.managed_environment_id`. - Ensure selected event/detail state cannot show an event outside the active filter. - Clear URL, chip, table/session filter state, and selected stale filter state. ## Authorization / Security Plan - Use the existing workspace/user access model for Environment resolution. - Cross-workspace or unauthorized Environment IDs must result in 404 / safe no-access behavior. - UI visibility is not authorization. - No page may use remembered Environment, Filament tenant context, or provider tenant aliases as access control input. ## Navigation / CTA Plan - Sidebar and global entries remain clean workspace URLs. - Environment-owned CTAs to Alerts, Alert Deliveries, and Audit Log may include canonical `environment_id` when preserving Environment focus. - Environment-owned CTAs to Alert Rules and Alert Destinations must use clean workspace links or be omitted. - No CTA may emit `tenant`, `tenant_id`, `managed_environment_id`, `environment`, `tenant_scope`, or `tableFilters` as Environment filter input. ## Testing Plan Use Pest 4 feature/browser style matching existing tests. Target tests: - Decision artifact static guard. - Alerts overview filtered/clean/chip/clear behavior. - Alert Deliveries filtered rows/chip/clear behavior. - Audit Log filtered rows/chip/clear behavior. - Legacy alias guard for Alerts and Audit Log. - Cross-workspace Environment guard for filterable surfaces. - Sidebar/global clean URL regression. - Environment CTA contract. - Alert configuration surfaces reject Environment filter state. Regression lanes: ```bash cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHubEnvironmentFilterContractTest cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHubClearFilterContractTest cd apps/platform && ./vendor/bin/sail artisan test --filter=LegacyTenantPlatformContextCleanup cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceOwnedAnalysisSurface cd apps/platform && ./vendor/bin/sail artisan test --filter=BaselineCompare ``` Exact class/filter names may be adjusted to match the repository during implementation. ## Browser Verification Plan Use the in-app browser or project browser smoke workflow after runtime code changes: - Alerts clean - Alerts filtered - Alerts after clear - Alerts after reload - Alert Deliveries filtered - Audit Log clean - Audit Log filtered - Audit Log after clear - Audit Log after reload - Environment Dashboard CTA to Alerts/Audit Log Save screenshots under: ```text specs/321-alerts-audit-log-environment-filter-contract-decision/artifacts/screenshots/ ``` ## Filament v5 Output Contract 1. **Livewire v4.0+ compliance**: Required. The app uses Livewire 4.1.4; implementation must not introduce Livewire v3 references. 2. **Provider registration location**: No new panel provider is planned. If one is unexpectedly required, Laravel 12 registration belongs in `apps/platform/bootstrap/providers.php`, not `bootstrap/app.php`. 3. **Global search resources**: `AlertDeliveryResource`, `AlertRuleResource`, and `AlertDestinationResource` currently disable global search. Alerts and Audit Log are pages, not globally searchable resources. This spec must not make them globally searchable without Edit/View page review. 4. **Destructive actions**: This spec should not introduce destructive actions. Existing destructive alert rule/destination actions must preserve confirmation and authorization. Any new destructive action is forbidden unless it executes through `Action::make(...)->action(...)`, has `->requiresConfirmation()`, and enforces authorization. 5. **Asset strategy**: No global or on-demand assets are planned. No deployment `filament:assets` change is required. 6. **Testing plan**: Cover Filament pages/resources as Livewire components and table/action behavior using Filament/Pest patterns already present in the repo. ## Implementation Phases 1. Confirm decision artifact and static guards. 2. Add failing contract tests. 3. Implement shared filter resolution/chip/clear on Alerts overview, Alert Deliveries, and Audit Log. 4. Ensure Alert Rules and Alert Destinations reject Environment filter state. 5. Update CTA and navigation helpers. 6. Run targeted tests and regression lanes. 7. Perform focused browser verification and capture screenshots. 8. Run formatting and diff checks. ## Complexity Tracking No complexity violation is expected. Potential implementation complexity: - Audit Log selected event state may require careful reconciliation with the active Environment filter. - Alert overview KPIs combine workspace configuration counts and delivery signal counts. - Existing persisted Filament table filters must be cleared without resurrecting legacy aliases. These risks should be handled within existing shared patterns. ## Deployment / Operations Impact Expected: - No migrations. - No seeders. - No package changes. - No environment variable changes. - No queue, scheduler, storage, or volume changes. - No Dokploy deployment changes. - No asset build/deploy changes. Implementation should still mention staging validation because this changes admin navigation/filter behavior.