## 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
161 lines
8.4 KiB
Markdown
161 lines
8.4 KiB
Markdown
# Quickstart: Action Surface Enforcement, Enrollment, and Exception Closure
|
|
|
|
## Goal
|
|
|
|
Implement Spec 195 by making every residual action-bearing surface explicitly reviewable without widening the generic action-surface runtime contract.
|
|
|
|
## Implementation Sequence
|
|
|
|
### 1. Add the Spec 195 residual closure inventory
|
|
|
|
Touch:
|
|
|
|
- `apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php`
|
|
- `apps/platform/app/Support/Ui/ActionSurface/ActionSurfaceValidator.php`
|
|
|
|
Do:
|
|
|
|
- Add `spec195ResidualSurfaceInventory()` with one entry per residual target surface.
|
|
- Add validator support for:
|
|
- allowed closure decisions
|
|
- allowed reason categories
|
|
- required structured evidence descriptors
|
|
- duplicate key detection
|
|
- truthful `discoveryState`
|
|
- stale baseline-exemption detection
|
|
|
|
Do not:
|
|
|
|
- auto-discover every system page
|
|
- introduce new persistence
|
|
- add a new runtime resolver or registry outside the existing action-surface support layer
|
|
|
|
### 2. Close the non-discovered system/detail surfaces explicitly
|
|
|
|
Audit and classify:
|
|
|
|
- `App\Filament\System\Pages\Dashboard`
|
|
- `App\Filament\System\Pages\Ops\ViewRun`
|
|
- `App\Filament\System\Pages\Ops\Runbooks`
|
|
- `App\Filament\System\Pages\RepairWorkspaceOwners`
|
|
- `App\Filament\System\Pages\Directory\ViewTenant`
|
|
- `App\Filament\System\Pages\Directory\ViewWorkspace`
|
|
|
|
Expected direction:
|
|
|
|
- `Dashboard`, `ViewRun`, `Runbooks`, `RepairWorkspaceOwners` => `separately_governed`
|
|
- `ViewTenant`, `ViewWorkspace` => `harmless_special_case` if they remain read-mostly contextual drilldowns
|
|
|
|
Only move one of these pages into `actionSurfaceDeclaration()` if the implementation audit shows it already fits the existing declaration-backed list/detail model naturally.
|
|
|
|
### 3. Reclassify the currently baseline-exempt special pages
|
|
|
|
Audit and classify:
|
|
|
|
- `App\Filament\Pages\BreakGlassRecovery`
|
|
- `App\Filament\Pages\ChooseWorkspace`
|
|
- `App\Filament\Pages\ChooseTenant`
|
|
- `App\Filament\Pages\Tenancy\RegisterTenant`
|
|
- `App\Filament\Pages\Workspaces\ManagedTenantOnboardingWizard`
|
|
- `App\Filament\Pages\Workspaces\ManagedTenantsLanding`
|
|
- `App\Filament\Pages\TenantDashboard`
|
|
|
|
Expected direction:
|
|
|
|
- `BreakGlassRecovery` => retire if it remains inaccessible and actionless; otherwise keep it as `intentional_exemption` with `security_flow_exception`
|
|
- `ChooseWorkspace`, `ChooseTenant` => `harmless_special_case`
|
|
- `RegisterTenant`, `ManagedTenantOnboardingWizard` => `separately_governed`
|
|
- `ManagedTenantsLanding` => explicit closure plus focused test
|
|
- `TenantDashboard` => `harmless_special_case` for the page shell while widget behavior stays governed by existing tests
|
|
|
|
### 4. Add CI regression protection
|
|
|
|
Touch:
|
|
|
|
- `tests/Feature/Guards/ActionSurfaceContractTest.php`
|
|
- `tests/Feature/Guards/ActionSurfaceValidatorTest.php`
|
|
- `tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php`
|
|
|
|
Do:
|
|
|
|
- fail when a residual target has no closure entry
|
|
- fail when a non-enrolled residual target has no reason category
|
|
- fail when a discovered residual page remains in `baseline()` but has no matching Spec 195 inventory entry
|
|
- fail when a retired residual surface still keeps a baseline exemption
|
|
|
|
### Reviewer Classification Workflow
|
|
|
|
Use this path whenever an audit uncovers a residual page that is not already in the seed inventory.
|
|
|
|
1. Identify whether the page is inside primary discovery or outside it.
|
|
2. Add or update the residual inventory entry with `surfaceKey`, `surfaceName`, `pageClass`, `panelPlane`, `surfaceKind`, `discoveryState`, `closureDecision`, `reasonCategory` where relevant, `explicitReason`, structured `evidence`, and `followUpAction`.
|
|
3. If the page legitimately fits the generic contract, extend the existing contract tests instead of inventing a new local rule.
|
|
4. If the page remains separate, harmless, exempt, or retired, add or update focused guard and page-level evidence before merge.
|
|
5. Run the focused verification pack and confirm the reviewer can classify the page from guard output alone.
|
|
6. Treat the validator failure output as part of the workflow: missing Spec 195 entries should name the class and the concrete file path reviewers must classify next.
|
|
|
|
### 5. Fill current coverage gaps only where needed
|
|
|
|
Likely new tests:
|
|
|
|
- `tests/Feature/System/Spec195/SystemDirectoryResidualSurfaceTest.php`
|
|
- `tests/Feature/Workspaces/Spec195ManagedTenantsLandingTest.php`
|
|
|
|
Reuse existing evidence instead of duplicating it for:
|
|
|
|
- `ViewRun`
|
|
- `Runbooks`
|
|
- `RepairWorkspaceOwners`
|
|
- chooser flows
|
|
- tenant registration
|
|
- onboarding wizard
|
|
- tenant dashboard shell
|
|
|
|
## Suggested Test Pack
|
|
|
|
Run the minimum targeted verification pack through Sail.
|
|
|
|
```bash
|
|
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH"
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceValidatorTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/Spec195ResidualActionSurfaceClosureGuardTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/Spec194GovernanceActionSemanticsGuardTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/LivewireTrustedStateGuardTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/FilamentTableStandardsGuardTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/Spec113/AuthorizationSemanticsTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/Spec114/OpsTriageActionsTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/OpsRunbooks/FindingsLifecycleBackfillStartTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Auth/BreakGlassWorkspaceOwnerRecoveryTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Auth/TenantChooserSelectionTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Workspaces/ChooseWorkspacePageTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Workspaces/WorkspaceAuditTrailTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantRBAC/TenantSwitcherScopeTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Rbac/RegisterTenantAuthorizationTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantRBAC/TenantBootstrapAssignTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Rbac/OnboardingWizardUiEnforcementTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Onboarding/OnboardingDraftAccessTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantDashboardDbOnlyTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Rbac/TenantDashboardArrivalContextVisibilityTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/Spec195/SystemDirectoryResidualSurfaceTest.php
|
|
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Workspaces/Spec195ManagedTenantsLandingTest.php
|
|
cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
|
|
```
|
|
|
|
## Manual Review Checklist
|
|
|
|
1. Confirm that the primary discovery count does not grow unexpectedly when Spec 195 lands.
|
|
2. Confirm that every in-scope residual surface has exactly one closure decision.
|
|
3. Confirm that non-discovered system/detail pages are now reviewable through the residual inventory and guard output.
|
|
4. Confirm that discovered special pages still exempted from the generic contract now carry explicit reason categories, explicit reasons, and structured evidence.
|
|
5. Confirm that `BreakGlassRecovery` is either retired from active exemptions or explicitly kept as `intentional_exemption` with `security_flow_exception` and current evidence.
|
|
6. Confirm that the weakest surfaces, expected to be `ManagedTenantsLanding` and system directory detail pages, have explicit focused tests.
|
|
7. Confirm that any newly audited residual surface beyond the initial seed was added to the inventory, contract, and guard expectations.
|
|
|
|
## Deployment Notes
|
|
|
|
- No migration is expected.
|
|
- No provider registration change is expected.
|
|
- No new assets are expected.
|
|
- Existing `cd apps/platform && php artisan filament:assets` deploy handling remains sufficient but unchanged.
|