# Spec 402 Implementation Report - Resource Policy & Authorization Proof Matrix ## A. Candidate Gate Result **Result: PASS.** No P0 or P1 authorization blocker remains in the inspected high-risk proof set. The confirmed Spec 401 residual around provider action visibility was fixed and covered by focused Livewire/Filament UI and direct execution tests plus browser smoke proof for representative rendered authorization behavior. ## B. Scope Included: - Repository-truth authorization inventory across admin resources, system surfaces, controller-backed exports/downloads, relation managers, global search posture, and representative custom pages. - Minimal hardening in `ProviderConnectionResource` to separate business visibility from capability authorization for provider high-impact actions. - Focused test and browser proof for provider action UI enforcement, provider disabled-action UX, provider direct execution blocking, backup hidden mutation behavior, admin global-search safety, and system/admin separation. Not included: - New roles, capabilities, permission model, migrations, persisted entities, JSONB work, product taxonomy/status families, new pages, navigation changes, or broad RBAC redesign. - Completed historical spec rewrites. - Full browser audit of every page. ## C. Dirty State - Starting branch: `402-resource-policy-authorization-proof-matrix` - Starting HEAD: `e1a7752f chore: finalize high risk admin action proof pack (#472)` - Starting dirty state: active untracked `specs/402-resource-policy-authorization-proof-matrix/`; no tracked runtime changes. - Starting `git diff --check`: passed. - Ending changed files: - `apps/platform/app/Filament/Resources/ProviderConnectionResource.php` - `apps/platform/tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php` - `apps/platform/tests/Browser/Spec402ResourcePolicyAuthorizationSmokeTest.php` - `specs/402-resource-policy-authorization-proof-matrix/spec.md` - `specs/402-resource-policy-authorization-proof-matrix/plan.md` - `specs/402-resource-policy-authorization-proof-matrix/implementation-report.md` - `specs/402-resource-policy-authorization-proof-matrix/tasks.md` - No unrelated dirty files were reset, deleted, or cleaned. ## D. Resource Policy & Authorization Matrix | Resource / Surface | Panel | Model | Category | Scope | Policy | Gate / Capability | CRUD | Custom Actions | Bulk | Relations | Global Search | Query Scope Proof | Direct Access Proof | Tests | Decision | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Provider connections | Admin | `ProviderConnection` | B | Workspace + environment | `ProviderConnectionPolicy` | `provider.view`, `provider.manage`, `provider.manage_dedicated`, `provider.run` | View/create/edit gated | Check, sync, snapshot, default, lifecycle, dedicated credential actions | None | N/A | Disabled | `applyMembershipScope()` | Non-member 404 route tests | Provider UI enforcement + direct execution denial + Spec 402 browser | PASS | | Backup schedules | Admin | `BackupSchedule` | B | Environment | `BackupSchedulePolicy` | tenant view/manage/run/delete | View allowed; mutations gated | Run, retry, archive, restore, force delete | Run/retry | Operation runs | Disabled | tenant-owned query trait | Non-member 404 + forged-key tests | Backup lifecycle/run tests + browser | PASS | | Backup sets | Admin | `BackupSet` | B | Environment | Query/gate path | tenant view/restore capabilities | Read/detail scoped | Add policies via relation | None | Backup items | Disabled | tenant-owned query | Existing parity tests | Backup set/RBAC tests | PASS | | Restore runs | Admin | `RestoreRun` | B | Environment | Query/gate path | restore/tenant capabilities | Read/create gated | Execute/confirm safety flow | None | N/A | Disabled | tenant-owned query | Restore UI tests | Restore run enforcement | PASS | | Policies | Admin | `Policy` | B | Environment | Query/gate path | tenant view/sync/restore | Read scoped | Sync/restore actions gated | None | Versions | Disabled | tenant-owned query | Existing route/search tests | Policy resource/search tests | PASS | | Policy versions | Admin | `PolicyVersion` | B | Environment | Query/gate path | tenant view/restore | Read scoped | Restore gated | None | N/A | Disabled | tenant-owned query | Existing tests | Policy version RBAC/search | PASS | | Inventory items | Admin | `InventoryItem` | A | Environment | Query/gate path | tenant view | Read scoped | None | None | N/A | Existing scoped posture | scoped query | Existing tests | Inventory item tests | PASS | | Entra groups | Admin | `EntraGroup` | A/B | Environment | `EntraGroupPolicy` | Entra roles view/manage | Read/mutate gated | Sync/manage actions gated | None | N/A | Existing scoped URL | scoped query | Existing tests | Directory group tests | PASS | | Findings | Admin | `Finding` | B | Environment/workspace | `FindingPolicy` | finding view/triage/assign/resolve | Read/mutate gated | Workflow actions gated | Bulk triage | Exceptions | Existing scoped posture | scoped query | Existing workflow tests | Findings tests | PASS | | Finding exceptions | Admin | `FindingException` | B | Environment/workspace | `FindingExceptionPolicy` | exception view/manage/approve | Read/mutate gated | Approval/renewal/decision actions | None | Decisions | Disabled | scoped query | Existing lifecycle tests | Exception RBAC tests | PASS | | Environment reviews | Admin | `EnvironmentReview` | B/C | Environment/customer-safe output | `EnvironmentReviewPolicy` | review view/manage/acknowledge | Read/mutate gated | Export/acknowledge gated | None | Sections | Disabled | scoped query | Existing tests | Review UI/export tests | PASS | | Review packs | Admin | `ReviewPack` | C | Environment/customer output | `ReviewPackPolicy` + `CustomerOutputGate` | review pack view/manage | Read/mutate gated | Download/publish/resolve gated | None | Reports | Disabled | scoped query | Controller tests | Review pack/customer output tests | PASS | | Stored reports | Admin | `StoredReport` | C | Environment/customer output | Query/gate path | review/report capabilities | Read/create/edit/delete gated | Download gated | None | Review pack | Disabled | scoped query | Existing tests | Stored report tests | PASS | | Evidence snapshots | Admin | `EvidenceSnapshot` | C | Environment/evidence | `EvidenceSnapshotPolicy` | evidence view/manage | Read/mutate gated | Capture/publish gated | None | N/A | Disabled | scoped query | Existing tests | Evidence tests | PASS | | Baseline profiles | Admin | `BaselineProfile` | B | Workspace/environment assignment | Query/gate path | baseline/manage capabilities | Read/mutate gated | Compare/capture gated | None | Assignments | Disabled | scoped query | Existing tests | Baseline action tests | PASS | | Baseline snapshots | Admin | `BaselineSnapshot` | B | Environment | Query/gate path | tenant view/baseline | Read scoped | Compare/details | None | N/A | Disabled | scoped query | Existing tests | Snapshot auth tests | PASS | | Alerts | Admin | `AlertRule`, `AlertDestination`, `AlertDelivery` | B | Workspace/environment | Alert policies | alert view/manage | Read/mutate gated | Test/send/ack gated | None | Deliveries | Disabled | scoped queries | Existing access tests | Alert access/viewer tests | PASS | | Operation runs | Admin | `OperationRun` | A/C | Environment/workspace | `OperationRunPolicy` | ops/tenant view | Read scoped | Retry/view links gated by source | None | N/A | Disabled | scoped query | Existing tests | Ops/run tests | PASS | | Managed environments | Admin | `ManagedEnvironment` | D | Workspace | Query/gate path | tenant/workspace capabilities | Read/manage gated | Onboarding/verify/setup gated | None | Memberships | Disabled by query | workspace scope | Existing tests | Tenant action tests | PASS | | Workspaces | Admin | `Workspace` | D | Workspace | `WorkspacePolicy` | workspace view/manage | Read/manage gated | Membership/settings | None | Memberships | Existing scoped posture | workspace query | Existing tests | Workspace RBAC tests | PASS | | Custom admin pages | Admin | Multiple/read models | A-D | Workspace/environment | Page-level gates/resolvers | Existing tenant/workspace capabilities | Page access scoped | Page actions gated | N/A | N/A | N/A | context middleware + page queries | Existing page tests | Surface guard tests | PASS | | System panel pages | System | `PlatformUser`, ops/directory models | D/E | System only | Platform guard + page capabilities | `PlatformCapabilities::*` | Page access gated | Repair/ops controls gated | N/A | N/A | System-only | `platform` guard + middleware | Tenant session 404; missing capability 403 | System boundary tests + browser | PASS | | Review/download controllers | HTTP | Review/report models | C | Environment/customer output | Controller authorization + output gates | review pack view/customer output gate | Download only | Stream/export | N/A | N/A | N/A | tenant/workspace checks | Controller tests | Review/report tests | PASS | | Provider callbacks/context routes | HTTP | Provider/workspace context | D | Workspace/environment | Middleware + controller checks | provider/manage/context | Callback/context only | Consent/RBAC callbacks | N/A | N/A | N/A | guarded routes | Existing route tests | Provider/onboarding tests | PASS | | Relation managers | Admin | Related models | B/C/D | Owner record scope | Owner resource + relation checks | owner capabilities | Related CRUD/attach gated | Add/remove/update gated | N/A | Owner scoped | N/A | relation owner scoping | Existing relation tests | Relation-manager RBAC tests | PASS | ## E. Runtime Changes - `ProviderConnectionResource` now uses `recordAllowsProviderMemberVisibility()` for action visibility and leaves capability decisions to `UiEnforcement::requireCapability()`. - The change covers provider edit, run/check/sync/snapshot, default, lifecycle, and dedicated credential actions. - Result: non-members remain hidden/404, members missing capability get visible-disabled or non-exposed rendered behavior depending on Filament action-group rendering, and server-side guards remain capability-backed. ## F. Policies / Gates / Capabilities - Added policies: none. - Added capabilities: none. - Updated gates: none. - Existing provider capabilities remain authoritative: `provider.manage`, `provider.manage_dedicated`, `provider.run`. - Documented exception: models with sufficient existing scoped query + capability paths were not given cosmetic policies. ## G. Tests Added / Updated - Updated `ProviderConnectionsUiEnforcementTest` with manager-without-dedicated-capability proof and direct Livewire execution denial for disabled provider operations. - Added `Spec402ResourcePolicyAuthorizationSmokeTest` browser smoke. - Reused existing focused tests for global search, system/admin separation, backup hidden/disabled mutation behavior, and direct resource denial. ## H. Proof Summary - Direct access: provider non-member route tests and backup schedule non-member tests prove deny-as-not-found behavior. - UI visibility/action execution: provider actions are disabled for members missing capabilities; direct Livewire calls to disabled provider check/sync/snapshot actions do not queue jobs or create OperationRuns; backup readonly cannot dispatch run/retry. - Workspace/environment isolation: backup browser smoke proves cross-workspace denied path; feature tests cover provider guessed URLs. - System/admin separation: feature tests prove tenant users get 404 on `/system`; browser smoke covers rendered denial. - Customer/internal boundary: review/report controllers retain existing authorization and customer output gates; no runtime changes. - Global search: representative high-risk admin resources remain disabled; global-search safety tests passed. - Relation managers and bulk actions: existing relation/bulk tests remain the proof source; no relation or bulk runtime changes. ## I. Focused Browser Proof Command: ```bash cd apps/platform && ./vendor/bin/sail artisan test tests/Browser/Spec402ResourcePolicyAuthorizationSmokeTest.php --compact ``` Result: passed, 1 test / 22 assertions. Covered: - Authorized admin provider detail for owner. - Readonly provider detail renders provider verification/edit/sync/snapshot actions as visible but disabled, with no JavaScript or console errors. - Readonly backup schedule list renders without exposing `Run now` and creates no operation run; this is the browser high-impact hidden-action proof. - Cross-workspace backup schedule path denied. - Workspace web session denied on `/system`. - No JavaScript or console errors on checked pages. Not covered by the focused browser smoke: - Provider direct disabled-action execution is covered by `ProviderConnectionsUiEnforcementTest`. - Global-search disabled/scoped posture is covered by `AdminGlobalSearchContextSafetyTest`; the browser smoke intentionally does not claim global-search UI coverage. Note: stale Playwright run-server processes from previous browser work initially caused `SIGKILL`; those orphaned runner processes were stopped, and the final browser proof passed. No runner processes remained after cleanup. ## J. Remaining Findings - P0: none. - P1: none. - P2: full browser audit across every matrix row and global-search browser UI proof remain intentionally out of scope. - P3: some low-risk/read-only resources rely on scoped query + capability paths rather than dedicated policy classes; documented as sufficient existing architecture. ## K. Deferred Items - Evidence currentness closure: deferred to the evidence/review feature stream. - Management PDF staging validation: deferred; no PDF behavior changed. - Governance lifecycle expansion: deferred. - JSONB migration/index work: deferred. - Full browser audit: deferred. - Product decision changes for roles/capabilities: none requested and none added. ## L. Validation Commands ```bash cd apps/platform && ./vendor/bin/sail pint app/Filament/Resources/ProviderConnectionResource.php tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php tests/Browser/Spec402ResourcePolicyAuthorizationSmokeTest.php ``` Result: passed. ```bash cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php --compact ``` Result: passed, 7 tests / 97 assertions. ```bash cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php tests/Feature/Rbac/AdminGlobalSearchContextSafetyTest.php tests/Feature/Rbac/SystemPanelAccessBoundaryTest.php --compact ``` Result: passed, 13 tests / 112 assertions. ```bash cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php tests/Feature/Rbac/AdminGlobalSearchContextSafetyTest.php tests/Feature/Rbac/SystemPanelAccessBoundaryTest.php tests/Feature/BackupScheduling/BackupScheduleLifecycleAuthorizationTest.php tests/Feature/BackupScheduling/RunNowRetryActionsTest.php --filter='provider|global search|system panel|readonly|members without manage capability|dedicated' --compact ``` Result: passed, 14 tests / 134 assertions. ```bash cd apps/platform && ./vendor/bin/sail artisan test tests/Browser/Spec402ResourcePolicyAuthorizationSmokeTest.php --compact ``` Result: passed, 1 test / 22 assertions. ```bash git diff --check ``` Result: passed. ## M. Recommended Next Action Proceed to Spec 403 only after review of this proof matrix and runtime hardening. The next spec should not introduce new roles/capabilities unless a product decision explicitly requires it. Product Surface Contract close-out: - No-legacy posture: no legacy surface introduced. - Product Surface Impact: existing authorization hardening only. - UI Surface Impact: existing Filament action visibility/disabled posture only; no new page, navigation, widget, or copy-heavy surface. - Page archetype: standard native Filament resources. - Surface budgets: unchanged. - Technical Annex / deep-link demotion: N/A. - Canonical status vocabulary: unchanged. - Product Surface exceptions: none. - Focused browser proof: completed via `Spec402ResourcePolicyAuthorizationSmokeTest`. - Human Product Sanity: visible disabled affordances increased intentionally inside existing provider More/action surfaces to satisfy RBAC-UX; the focused browser smoke verified the readonly provider actions are rendered disabled. No new page, navigation, widget, or copy-heavy surface was added, and readonly users are not offered executable high-impact controls. - Livewire v4: compliant with installed Livewire 4.1.4. - Provider registration: panels remain registered in `apps/platform/bootstrap/providers.php`. - Global search: no globally searchable resource was enabled; high-risk resources remain disabled or existing scoped. - Destructive/high-impact actions: existing `->requiresConfirmation()` retained; authorization remains enforced by `UiEnforcement` and policies/gates. - Asset strategy: no assets added; `filament:assets` deployment step unchanged and not newly required by this spec. - Deployment impact: no migrations, env vars, queues, storage, or asset build changes.