*/ function spec195DiscoveredClasses(): array { return array_map( static fn (ActionSurfaceDiscoveredComponent $component): string => $component->className, ActionSurfaceValidator::withBaselineExemptions()->discoveredComponents(), ); } /** * @param array $issues */ function spec195FormattedIssues(array $issues): string { return implode("\n", array_map( static fn ($issue): string => $issue->format(), $issues, )); } it('keeps every spec 195 residual surface classified exactly once with structured evidence', function (): void { $inventory = ActionSurfaceExemptions::spec195ResidualSurfaceInventory(); expect(array_keys($inventory))->toEqualCanonicalizing([ \App\Filament\System\Pages\Dashboard::class, \App\Filament\System\Pages\Ops\ViewRun::class, \App\Filament\System\Pages\Ops\Runbooks::class, \App\Filament\System\Pages\RepairWorkspaceOwners::class, \App\Filament\System\Pages\Directory\ViewTenant::class, \App\Filament\System\Pages\Directory\ViewWorkspace::class, \App\Filament\Pages\BreakGlassRecovery::class, \App\Filament\Pages\ChooseWorkspace::class, \App\Filament\Pages\ChooseTenant::class, \App\Filament\Pages\Tenancy\RegisterTenant::class, \App\Filament\Pages\Workspaces\ManagedTenantOnboardingWizard::class, \App\Filament\Pages\Workspaces\ManagedTenantsLanding::class, \App\Filament\Pages\TenantDashboard::class, ]); $surfaceKeys = collect($inventory)->pluck('surfaceKey')->all(); expect($surfaceKeys)->toHaveCount(count(array_unique($surfaceKeys))); foreach ($inventory as $className => $surface) { expect($surface['closureDecision'] ?? null) ->not->toBeNull("{$className} must keep a closure decision.") ->and(trim((string) ($surface['surfaceName'] ?? ''))) ->not->toBe('', "{$className} must keep a human-readable surfaceName.") ->and($surface['evidence'] ?? []) ->not->toBeEmpty("{$className} must keep structured evidence."); } }); it('keeps the residual system tail explicitly classified instead of silently baseline-exempted', function (): void { $inventory = ActionSurfaceExemptions::spec195ResidualSurfaceInventory(); $baselineExemptions = ActionSurfaceExemptions::baseline()->all(); expect($inventory[\App\Filament\System\Pages\Ops\ViewRun::class]['closureDecision'] ?? null)->toBe('separately_governed') ->and($inventory[\App\Filament\System\Pages\Ops\Runbooks::class]['closureDecision'] ?? null)->toBe('separately_governed') ->and($inventory[\App\Filament\System\Pages\RepairWorkspaceOwners::class]['closureDecision'] ?? null)->toBe('separately_governed') ->and($inventory[\App\Filament\System\Pages\Directory\ViewTenant::class]['closureDecision'] ?? null)->toBe('harmless_special_case') ->and($inventory[\App\Filament\System\Pages\Directory\ViewWorkspace::class]['closureDecision'] ?? null)->toBe('harmless_special_case') ->and($inventory[\App\Filament\System\Pages\Dashboard::class]['closureDecision'] ?? null)->toBe('separately_governed'); foreach ([ \App\Filament\System\Pages\Dashboard::class, \App\Filament\System\Pages\Ops\ViewRun::class, \App\Filament\System\Pages\Ops\Runbooks::class, \App\Filament\System\Pages\RepairWorkspaceOwners::class, \App\Filament\System\Pages\Directory\ViewTenant::class, \App\Filament\System\Pages\Directory\ViewWorkspace::class, ] as $className) { expect(array_key_exists($className, $baselineExemptions)) ->toBeFalse("{$className} must not rely on baseline() for Spec 195 closure."); } }); it('retires break glass recovery from live baseline handling', function (): void { $surface = ActionSurfaceExemptions::spec195ResidualSurface(\App\Filament\Pages\BreakGlassRecovery::class); expect($surface)->not->toBeNull() ->and($surface['closureDecision'] ?? null)->toBe('retired_no_longer_relevant') ->and($surface['reasonCategory'] ?? null)->toBe('disabled_or_actionless_surface') ->and(ActionSurfaceExemptions::baseline()->hasClass(\App\Filament\Pages\BreakGlassRecovery::class))->toBeFalse(); }); it('fails when a residual candidate is missing a closure decision entry', function (): void { $inventory = ActionSurfaceExemptions::spec195ResidualSurfaceInventory(); unset($inventory[\App\Filament\System\Pages\Dashboard::class]); $issues = ActionSurfaceValidator::validateSpec195ResidualInventoryFixture( inventory: $inventory, discoveredClasses: spec195DiscoveredClasses(), baselineExemptions: ActionSurfaceExemptions::baseline()->all(), residualCandidateClasses: [\App\Filament\System\Pages\Dashboard::class], ); expect(spec195FormattedIssues($issues)) ->toContain('Residual action surface is missing a Spec 195 closure entry') ->toContain(\App\Filament\System\Pages\Dashboard::class); }); it('fails when a discovered residual exemption loses its reason category', function (): void { $inventory = ActionSurfaceExemptions::spec195ResidualSurfaceInventory(); $inventory[\App\Filament\Pages\ChooseTenant::class]['reasonCategory'] = null; $issues = ActionSurfaceValidator::validateSpec195ResidualInventoryFixture( inventory: $inventory, discoveredClasses: spec195DiscoveredClasses(), baselineExemptions: ActionSurfaceExemptions::baseline()->all(), ); expect(spec195FormattedIssues($issues)) ->toContain(\App\Filament\Pages\ChooseTenant::class) ->toContain('reason category is invalid or missing'); }); it('fails when a residual surface loses its structured evidence', function (): void { $inventory = ActionSurfaceExemptions::spec195ResidualSurfaceInventory(); $inventory[\App\Filament\System\Pages\Directory\ViewTenant::class]['evidence'] = []; $issues = ActionSurfaceValidator::validateSpec195ResidualInventoryFixture( inventory: $inventory, discoveredClasses: spec195DiscoveredClasses(), baselineExemptions: ActionSurfaceExemptions::baseline()->all(), ); expect(spec195FormattedIssues($issues)) ->toContain(\App\Filament\System\Pages\Directory\ViewTenant::class) ->toContain('require at least one structured evidence descriptor'); }); it('fails when a retired surface is reintroduced as a stale baseline exemption', function (): void { $baselineExemptions = ActionSurfaceExemptions::baseline()->all(); $baselineExemptions[\App\Filament\Pages\BreakGlassRecovery::class] = 'Stale retired page exemption.'; $issues = ActionSurfaceValidator::validateSpec195ResidualInventoryFixture( inventory: ActionSurfaceExemptions::spec195ResidualSurfaceInventory(), discoveredClasses: spec195DiscoveredClasses(), baselineExemptions: $baselineExemptions, ); expect(spec195FormattedIssues($issues)) ->toContain(\App\Filament\Pages\BreakGlassRecovery::class) ->toContain('must not remain baseline-exempt'); });