TenantAtlas/specs/195-action-surface-closure/tasks.md
ahmido 1c291fb9fe feat: close spec 195 action surface residuals (#230)
## Summary
- add the full Spec 195 residual action-surface design package under `specs/195-action-surface-closure`
- implement residual surface inventory and validator enforcement for uncatalogued system and special Filament pages
- add focused regression coverage for residual guards, system directory pages, managed-tenants landing, and readonly register-tenant / tenant-dashboard access
- fix the system workspace detail surface by loading tenant route keys and disabling lazy system database notifications to avoid the Livewire 404 on `/system/directory/workspaces/{workspace}`

## Testing
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/Spec195/SystemDirectoryResidualSurfaceTest.php tests/Feature/Filament/DatabaseNotificationsPollingTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`

## Notes
- branch: `195-action-surface-closure`
- target: `dev`
- no new assets, migrations, or provider-registration changes

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #230
2026-04-13 07:47:58 +00:00

18 KiB

description
Task list for Spec 195 action-surface closure implementation

Tasks: Action Surface Enforcement, Enrollment, and Exception Closure

Input: Design documents from /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/195-action-surface-closure/ Prerequisites: plan.md, spec.md, research.md, data-model.md, quickstart.md, contracts/action-surface-closure.logical.openapi.yaml

Tests: Runtime behavior changes in this repo require Pest coverage. This task list includes guard, feature, and focused residual-surface tests. Operations: This feature does not add new long-running or queued work. Existing OperationRun and audit behavior on residual surfaces must remain unchanged. RBAC: Existing 404 vs 403 semantics, capability checks, and destructive-action confirmations remain mandatory across the admin, tenant-context admin, and system planes. UI Naming: No new operator-facing vocabulary is introduced; existing action copy remains domain-first and consistent. Operator Surfaces: The affected surfaces are already classified in the spec and must be kept aligned with those classifications during implementation. Filament UI Action Surfaces: This feature governs existing Filament pages and utilities without introducing a new page framework. Proportionality / Anti-Bloat: Keep the implementation to one bounded residual inventory, validator checks, and focused tests. Do not add new persistence, enums, or runtime registries unless the implementation proves they are unavoidable.

Phase 1: Setup (Shared Review Inputs)

Purpose: Confirm the current residual-surface scope and evidence sources before editing the shared support layer.

  • T001 Audit the current primary discovery and exemption entry points in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceDiscovery.php, apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php, and apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php
  • T002 [P] Audit the existing focused evidence sources for residual surfaces in apps/platform/tests/Feature/System/Spec114/OpsTriageActionsTest.php, apps/platform/tests/Feature/System/OpsRunbooks/FindingsLifecycleBackfillStartTest.php, apps/platform/tests/Feature/Auth/BreakGlassWorkspaceOwnerRecoveryTest.php, apps/platform/tests/Feature/Auth/TenantChooserSelectionTest.php, apps/platform/tests/Feature/Rbac/RegisterTenantAuthorizationTest.php, apps/platform/tests/Feature/Rbac/OnboardingWizardUiEnforcementTest.php, and apps/platform/tests/Feature/Filament/TenantDashboardDbOnlyTest.php

Phase 2: Foundational (Blocking Prerequisites)

Purpose: Add the shared Spec 195 inventory and validation scaffolding that all user stories depend on.

⚠️ CRITICAL: No user story work should begin until this phase is complete.

  • T003 [P] Add shared residual-inventory schema assertions for Spec 195 in apps/platform/tests/Feature/Guards/ActionSurfaceValidatorTest.php
  • T004 [P] Add shared contract-harness expectations for Spec 195 residual inventory consumption in apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php
  • T005 Implement the spec195ResidualSurfaceInventory() skeleton, required surfaceName field, and allowed closure vocabulary in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php
  • T006 Implement a validator-side residual-candidate boundary helper that preserves the existing primary discovery contract in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php
  • T007 Extend apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php with reusable Spec 195 schema validation for allowed values, duplicate keys, evidence presence, and truthful discovery state

Checkpoint: Shared residual inventory and validator scaffolding are ready; user story work can now proceed.


Phase 3: User Story 1 - Close the residual inventory (Priority: P1) 🎯 MVP

Goal: Make every in-scope residual surface appear exactly once with one closure decision, reason category where needed, and explicit evidence.

Independent Test: Review the final residual inventory and guard output alone and verify that the initial seed plus any additional audited residual surfaces have exactly one decision, no duplicates, and no missing evidence.

Tests for User Story 1

  • T008 [P] [US1] Add completeness expectations for all Spec 195 residual surface keys in apps/platform/tests/Feature/Guards/ActionSurfaceValidatorTest.php
  • T009 [P] [US1] Add contract assertions for unique closure decisions, structured evidence descriptors, and baseline-alignment expectations in apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php

Implementation for User Story 1

  • T010 [US1] Populate the initial seed and any newly audited Spec 195 residual closure entries with surfaceName, discovery state, closure decision, reason category, explicitReason, structured evidence, and followUpAction in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php
  • T011 [US1] Wire Spec 195 residual inventory consumption into apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php so every residual surface is checked exactly once

Checkpoint: User Story 1 is complete when the repo has a single complete Spec 195 inventory and its completeness is guard-tested.


Phase 4: User Story 2 - Remove silent system and utility exceptions (Priority: P1)

Goal: Explicitly classify the currently uncatalogued system and utility surfaces so dangerous or decision-bearing system pages no longer live outside review discipline.

Independent Test: Review the system residual entries plus focused system tests and verify that ViewRun, Runbooks, RepairWorkspaceOwners, ViewTenant, and ViewWorkspace all have explicit closure states and no silent fallback path.

Tests for User Story 2

  • T012 [P] [US2] Add residual guard coverage for App\Filament\System\Pages\Ops\ViewRun, App\Filament\System\Pages\Ops\Runbooks, and App\Filament\System\Pages\RepairWorkspaceOwners in apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php
  • T013 [P] [US2] Add focused read-mostly closure coverage for App\Filament\System\Pages\Directory\ViewTenant and App\Filament\System\Pages\Directory\ViewWorkspace in apps/platform/tests/Feature/System/Spec195/SystemDirectoryResidualSurfaceTest.php

Implementation for User Story 2

  • T014 [US2] Audit apps/platform/app/Filament/System/Pages/Ops/ViewRun.php, apps/platform/app/Filament/System/Pages/Ops/Runbooks.php, and apps/platform/app/Filament/System/Pages/RepairWorkspaceOwners.php and, if implementation reality differs from the design seed, update the matching entries in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php, apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php, and apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php
  • T015 [US2] Audit apps/platform/app/Filament/System/Pages/Directory/ViewTenant.php and apps/platform/app/Filament/System/Pages/Directory/ViewWorkspace.php and, if the pages are not truly read-mostly harmless cases, update the matching entries in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php, apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php, and apps/platform/tests/Feature/System/Spec195/SystemDirectoryResidualSurfaceTest.php
  • T016 [US2] Tighten apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php so outside-primary-discovery system and utility pages cannot pass without Spec 195 closure data and, if any audited system page is promoted into generic contract enrollment, extend apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php and apps/platform/tests/Feature/Guards/ActionSurfaceValidatorTest.php to enforce inherited contract continuity

Checkpoint: User Story 2 is complete when the system/detail residual tail is explicitly classified and validated instead of relying on discovery accidents.


Phase 5: User Story 3 - Keep only justified exemptions (Priority: P2)

Goal: Remove stale exemptions and require every remaining discovered exception to carry an explicit reason category and coverage note.

Independent Test: Review the discovered-page exemption set alone and verify that every remaining entry has a reason category, explicit reason, structured evidence, and no stale BreakGlassRecovery carry-over.

Tests for User Story 3

  • T017 [P] [US3] Add stale-exemption and reason-category failure cases in apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php
  • T018 [P] [US3] Add stale-exemption and baseline-removal assertions for apps/platform/app/Filament/Pages/BreakGlassRecovery.php in apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php and apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php

Implementation for User Story 3

  • T019 [US3] Audit apps/platform/app/Filament/Pages/BreakGlassRecovery.php and either retire it from live baseline handling or keep it as a live intentional_exemption with security_flow_exception in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php, apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php, and apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php
  • T020 [US3] Tighten stale-baseline cleanup rules for retired or reasonless discovered exceptions in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php and apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php
  • T021 [US3] Extend apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php to reject reasonless discovered exemptions and retired surfaces that still remain in baseline()

Checkpoint: User Story 3 is complete when every surviving discovered-page exception is explicit, reasoned, and evidence-backed.


Phase 6: User Story 4 - Block future unclassified residuals (Priority: P2)

Goal: Fail fast when future residual surfaces or exemptions appear without an explicit closure decision.

Independent Test: Introduce representative missing-classification and missing-reason cases in the guard suite and verify CI-style failures occur with actionable output.

Tests for User Story 4

  • T022 [P] [US4] Create regression cases for missing closure decision, missing reason category, missing structured evidence, and stale baseline entries in apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php
  • T023 [P] [US4] Extend apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php with a representative uncatalogued residual-surface failure path

Implementation for User Story 4

  • T024 [US4] Extend apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php with namespace-scoped residual-candidate checks that preserve the existing generic discovery boundary and require Spec 195 inventory coverage for qualifying pages
  • T025 [US4] Improve apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php failure output and update specs/195-action-surface-closure/quickstart.md so missing Spec 195 classifications report actionable class and file context plus the reviewer classification workflow

Checkpoint: User Story 4 is complete when new residual surfaces or exemptions cannot merge silently without a closure decision.


Phase 7: User Story 5 - Preserve good special surfaces without forced churn (Priority: P3)

Goal: Keep legitimately special selector, registration, onboarding, landing, and dashboard surfaces outside the generic contract where that is the safer and clearer choice.

Independent Test: Review the special-surface entries plus focused tests and verify that selectors, onboarding, registration, landing, and dashboard shells can remain separately governed or harmless without being mislabeled as defects.

Tests for User Story 5

  • T026 [P] [US5] Create focused landing-surface coverage in apps/platform/tests/Feature/Workspaces/Spec195ManagedTenantsLandingTest.php
  • T027 [P] [US5] Extend special-surface evidence coverage with explicit positive and negative authorization paths in apps/platform/tests/Feature/Rbac/RegisterTenantAuthorizationTest.php, apps/platform/tests/Feature/Rbac/OnboardingWizardUiEnforcementTest.php, and apps/platform/tests/Feature/Filament/TenantDashboardDbOnlyTest.php
  • T028 [P] [US5] Extend selector-surface evidence coverage in apps/platform/tests/Feature/Workspaces/ChooseWorkspacePageTest.php and apps/platform/tests/Feature/Auth/TenantChooserSelectionTest.php

Implementation for User Story 5

  • T029 [US5] If audit changes the design-seed classification for apps/platform/app/Filament/Pages/ChooseWorkspace.php, apps/platform/app/Filament/Pages/ChooseTenant.php, apps/platform/app/Filament/Pages/TenantDashboard.php, apps/platform/app/Filament/Pages/Tenancy/RegisterTenant.php, apps/platform/app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php, or apps/platform/app/Filament/Pages/Workspaces/ManagedTenantsLanding.php, update the matching entry in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php and the paired expectation in apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php
  • T030 [US5] Align apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php so discovered special surfaces can remain separately_governed or harmless_special_case without forced actionSurfaceDeclaration() enrollment

Checkpoint: User Story 5 is complete when good special surfaces remain explicitly governed without unnecessary normalization.


Phase 8: Polish & Cross-Cutting Verification

Purpose: Run the focused verification pack, format the touched files, and confirm the implementation matches the planning contract.

  • T031 Run the focused Spec 195 Sail verification pack from specs/195-action-surface-closure/quickstart.md against apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php, apps/platform/tests/Feature/Guards/ActionSurfaceValidatorTest.php, apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php, apps/platform/tests/Feature/Guards/Spec194GovernanceActionSemanticsGuardTest.php, apps/platform/tests/Feature/Guards/LivewireTrustedStateGuardTest.php, apps/platform/tests/Feature/Guards/FilamentTableStandardsGuardTest.php, apps/platform/tests/Feature/System/Spec113/AuthorizationSemanticsTest.php, apps/platform/tests/Feature/System/Spec114/OpsTriageActionsTest.php, apps/platform/tests/Feature/System/OpsRunbooks/FindingsLifecycleBackfillStartTest.php, apps/platform/tests/Feature/Auth/BreakGlassWorkspaceOwnerRecoveryTest.php, apps/platform/tests/Feature/Auth/TenantChooserSelectionTest.php, apps/platform/tests/Feature/Workspaces/ChooseWorkspacePageTest.php, apps/platform/tests/Feature/Workspaces/WorkspaceAuditTrailTest.php, apps/platform/tests/Feature/TenantRBAC/TenantSwitcherScopeTest.php, apps/platform/tests/Feature/Rbac/RegisterTenantAuthorizationTest.php, apps/platform/tests/Feature/TenantRBAC/TenantBootstrapAssignTest.php, apps/platform/tests/Feature/Rbac/OnboardingWizardUiEnforcementTest.php, apps/platform/tests/Feature/Onboarding/OnboardingDraftAccessTest.php, apps/platform/tests/Feature/Filament/TenantDashboardDbOnlyTest.php, apps/platform/tests/Feature/Rbac/TenantDashboardArrivalContextVisibilityTest.php, apps/platform/tests/Feature/System/Spec195/SystemDirectoryResidualSurfaceTest.php, and apps/platform/tests/Feature/Workspaces/Spec195ManagedTenantsLandingTest.php
  • T032 Run cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent and resolve formatting issues in apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceDiscovery.php, apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php, apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php, apps/platform/tests/Feature/Guards/ActionSurfaceContractTest.php, apps/platform/tests/Feature/Guards/ActionSurfaceValidatorTest.php, apps/platform/tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php, apps/platform/tests/Feature/System/Spec195/SystemDirectoryResidualSurfaceTest.php, and apps/platform/tests/Feature/Workspaces/Spec195ManagedTenantsLandingTest.php
  • T033 Verify the final residual inventory matches specs/195-action-surface-closure/contracts/action-surface-closure.logical.openapi.yaml, includes human-readable surfaceName values, and covers the initial seed plus any newly audited residual surfaces described in specs/195-action-surface-closure/data-model.md

Dependencies

  • Setup tasks T001-T002 precede all implementation work.
  • Foundational tasks T003-T007 block all user stories.
  • User Story 1 depends on Phase 2 and unlocks the actual residual inventory.
  • User Story 2, User Story 3, and User Story 5 depend on User Story 1 because they classify concrete residual entries inside the shared inventory.
  • User Story 4 depends on User Story 1, User Story 2, User Story 3, and User Story 5 because the regression guard must validate the final closure state.
  • Polish tasks T031-T033 depend on all user stories being complete.

Parallel Execution Examples

  • After T001, run T002 in parallel with any remaining setup review.
  • In Phase 2, T003 and T004 can run in parallel before T005-T007 land.
  • In User Story 1, T008 and T009 can run in parallel.
  • In User Story 2, T012 and T013 can run in parallel.
  • In User Story 3, T017 and T018 can run in parallel.
  • In User Story 4, T022 and T023 can run in parallel.
  • In User Story 5, T026, T027, and T028 can run in parallel.

Implementation Strategy

  • Start with Phase 2 and User Story 1 to establish the residual inventory and validator contract.
  • Deliver User Story 2 next to close the highest-risk system and utility surfaces first.
  • Follow with User Story 3 and User Story 5 to normalize discovered exceptions and preserve legitimate special workflows.
  • Complete User Story 4 only after the closure states are finalized so the new guard enforces the finished model instead of a moving target.
  • Finish with the focused Sail verification pack and Pint formatting from Phase 8.