# Implementation Plan: Spec 402 - Resource Policy & Authorization Proof Matrix **Branch**: `402-resource-policy-authorization-proof-matrix` | **Date**: 2026-06-23 | **Spec**: `specs/402-resource-policy-authorization-proof-matrix/spec.md` **Input**: Feature specification from `specs/402-resource-policy-authorization-proof-matrix/spec.md` ## Summary Spec 402 converts TenantPilot resource authorization from implicit/scattered proof into an auditable matrix and targeted hardening package. The implementation must inventory existing admin and system resource-backed surfaces, classify each policy/gate/capability/scoped-query decision, add focused negative tests for high-risk authorization paths, and apply only minimal hardening for confirmed gaps. Do not start by adding policies. Build the matrix first, classify gaps, then fix only the smallest confirmed in-scope authorization defects. ## Technical Context **Language/Version**: PHP 8.4.15, Laravel 12.52.0 **Primary Dependencies**: Filament 5.2.1, Livewire 4.1.4, Laravel Sail, Pest 4.3.1, PHPUnit 12.5.4 **Storage**: PostgreSQL; no schema changes allowed **Testing**: Pest Feature/Filament/Policy tests, focused Pest Browser smoke where available **Validation Lanes**: confidence for Feature/Filament authorization tests; browser for representative UI proof; heavy-governance only if a matrix/discovery guard is implemented **Target Platform**: TenantPilot Laravel monolith under `apps/platform` **Project Type**: Laravel + Filament application **Performance Goals**: No material runtime or suite-cost increase; avoid broad browser/full-suite expansion **Constraints**: No new roles, permission product model, persisted truth, migrations, product surfaces, navigation, or broad refactor **Scale/Scope**: Existing `/admin` resources/pages/actions and `/system` pages/actions with resource-backed authorization impact ## Preparation Context - Dirty state before preparation: clean on `platform-dev` at `e1a7752f chore: finalize high risk admin action proof pack (#472)`. - Spec Kit script used: `.specify/scripts/bash/create-new-feature.sh --json --number 402 --short-name resource-policy-authorization-proof-matrix "Resource Policy & Authorization Proof Matrix"`. - Generated branch/path: `402-resource-policy-authorization-proof-matrix`, `specs/402-resource-policy-authorization-proof-matrix/`. - Existing conflict note: local and remote branch `402-screwfast-website-rebuild` existed before preparation, but no `specs/402-*` package existed. - Candidate source: direct user-provided Spec 402 draft, promoted from Spec 400 P1 resource-policy matrix condition. - Completed-spec guardrail: Specs 400 and 401 are read-only context. Do not rewrite their close-out, validation, completed tasks, implementation reports, or browser evidence. ## Existing Repository Surfaces ### Panels and routes - Admin panel provider: `apps/platform/app/Providers/Filament/AdminPanelProvider.php`, registered in `apps/platform/bootstrap/providers.php`, path `/admin`, discovers `App\Filament\Resources`. - System panel provider: `apps/platform/app/Providers/Filament/SystemPanelProvider.php`, registered in `apps/platform/bootstrap/providers.php`, path `/system`, discovers `App\Filament\System\Pages`. - Admin route families include workspace/environment resource routes under `/admin/workspaces/{workspace}/environments/{environment}/...`. - System route families include `/system/directory/...`, `/system/ops/...`, `/system/security/access-logs`, and `/system/repair-workspace-owners`. ### Authorization foundations - Tenant/admin capabilities are registered in `apps/platform/app/Providers/AuthServiceProvider.php` from `App\Support\Auth\Capabilities`. - Platform/system capabilities are registered in `AuthServiceProvider` from `App\Support\Auth\PlatformCapabilities`. - Some policies are registered via `$policies` in `AuthServiceProvider`. - Additional policies are manually bound in `apps/platform/app/Providers/AppServiceProvider.php` for `BackupSchedule`, `Finding`, `EntraGroup`, and `OperationRun`. - Existing central paths include `App\Services\Auth\CapabilityResolver`, `App\Services\Auth\WorkspaceCapabilityResolver`, `App\Support\Rbac\UiEnforcement`, and `App\Support\Rbac\WorkspaceUiEnforcement`. ### Resource inventory seed The implementation must verify this list rather than treating it as complete: - Admin resources: `AlertDeliveryResource`, `AlertDestinationResource`, `AlertRuleResource`, `BackupScheduleResource`, `BackupSetResource`, `BaselineProfileResource`, `BaselineSnapshotResource`, `EntraGroupResource`, `EnvironmentReviewResource`, `EvidenceSnapshotResource`, `FindingExceptionResource`, `FindingResource`, `InventoryItemResource`, `ManagedEnvironmentResource`, `OperationRunResource`, `PolicyResource`, `PolicyVersionResource`, `ProviderConnectionResource`, `RestoreRunResource`, `ReviewPackResource`, `StoredReportResource`, `Workspaces\WorkspaceResource`. - Admin model-backed pages/custom flows: `BaselineSubjectResolution`, `EnvironmentDashboard`, `EnvironmentDiagnostics`, `EnvironmentRequiredPermissions`, `FindingsIntakeQueue`, `MyFindingsInbox`, `DecisionRegister`, `GovernanceInbox`, `AuditLog`, `EvidenceOverview`, `Operations`, `TenantlessOperationRunViewer`, `CustomerReviewWorkspace`, `ReviewRegister`, `WorkspaceSettings`, `ManagedEnvironmentOnboardingWizard`. - Relation managers: backup schedule operation runs, backup items, baseline tenant assignments, managed environment memberships, policy versions, workspace memberships, and any relation managers discovered during implementation. - System pages: dashboard, directory tenants/workspaces/detail pages, ops controls/failures/runbooks/runs/stuck/view run, repair workspace owners, security access logs. - Controller-backed routes: review-pack downloads/rendered reports, management-report PDF downloads, provider consent/RBAC callbacks, finding exception queue deep links, workspace/environment context switching. ## UI / Surface Guardrail Plan - **Guardrail scope**: existing operator/admin/system surfaces may be authorization-hardened; no new surfaces. - **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: exact touched surfaces named in implementation report after matrix inventory. - **No-impact class, if applicable**: N/A because rendered authorization behavior may change. - **Native vs custom classification summary**: native Filament resources/pages plus existing Laravel controllers and shared authorization helpers. - **Shared-family relevance**: authorization, global search, high-impact actions, relation managers, downloads/exports, system panel access. - **State layers in scope**: page, table/action, relation manager, route/query, global search, controller route. - **Audience modes in scope**: operator-MSP, readonly/customer where existing tests/surfaces represent it, support-platform/system. - **Decision/diagnostic/raw hierarchy plan**: unchanged; do not expose new raw technical evidence. - **Raw/support gating plan**: preserve or tighten existing capability gating. - **One-primary-action / duplicate-truth control**: unchanged; do not add UI layers. - **Handling modes by drift class or surface**: review-mandatory for high-risk authorization paths; exception-required for any policy/gate exception; hard-stop for P0 unsafe access. - **Repository-signal treatment**: review-mandatory for missing policy proof, direct invocation gaps, relation/bulk/search uncertainty, and system/admin boundary gaps. - **Special surface test profiles**: standard-native-filament, global-context-shell, system-admin, browser representative proof. - **Required tests or manual smoke**: Feature/Filament/policy tests plus focused browser smoke. - **Exception path and spread control**: documented exception in matrix and implementation report only; no runtime exception framework. - **Active feature PR close-out entry**: `Guardrail / Exception / Smoke Coverage`. - **UI/Productization coverage decision**: existing-surface authorization hardening only; no route-inventory/design matrix update unless implementation materially changes a reachable surface beyond authorization. - **Coverage artifacts to update**: none planned. - **No-impact rationale**: N/A. - **Navigation / Filament provider-panel handling**: no provider registration changes; system/admin provider locations must be stated in close-out. - **Screenshot or page-report need**: no page-report set; focused browser proof is sufficient. ## Product Surface Contract Plan - **Product Surface Contract reference**: `docs/product/standards/product-surface-contract.md` - **No-legacy posture**: canonical current authorization, no compatibility exception. - **Page archetype and surface budget plan**: existing archetypes only; neutral budget impact expected. - **Technical Annex and deep-link demotion plan**: unchanged; do not promote OperationRun/evidence/raw IDs/source keys/payloads. - **Canonical status vocabulary plan**: unchanged. - **Product Surface exceptions**: none planned. - **Browser verification plan**: focused representative authorization paths. - **Human Product Sanity plan**: focused authorization sanity over changed rendered behavior. - **Visible complexity outcome target**: neutral or decreased. - **Implementation report target**: `specs/402-resource-policy-authorization-proof-matrix/implementation-report.md`. ## Filament / Livewire / Deployment Posture - **Livewire v4 compliance**: Livewire 4.1.4 confirmed by Laravel Boost; no Livewire v3 APIs allowed. - **Panel provider registration location**: unchanged; Laravel 12 providers are registered in `apps/platform/bootstrap/providers.php`. - **Global search posture**: every resource must be classified; do not enable global search merely for completeness. Globally searchable resources need View/Edit pages, `$recordTitleAttribute`, scoped queries, and tests. - **Destructive/high-impact action posture**: all touched destructive/high-impact actions must be action-backed, `->requiresConfirmation()` where destructive/high-impact, server-authorized, audited when mutating, and tested. - **Asset strategy**: no new assets. `filament:assets` is not newly required unless implementation unexpectedly registers assets, which is out of scope by default. - **Testing plan**: policy/gate tests, Filament page/action tests, relation manager tests, direct route access tests, global search posture tests, system/admin separation tests, focused browser smoke. - **Deployment impact**: no env vars, migrations, queues, scheduler, storage, assets, routes, panels, or navigation changes expected. If authorization hardening changes runtime behavior, deployment notes must call out safer access enforcement only. ## Shared Pattern & System Fit - **Cross-cutting feature marker**: yes. - **Systems touched**: policies, gates, capability resolvers, UI enforcement helpers, scoped Filament resource queries, relation managers, system capability middleware, controller authorization. - **Shared abstractions reused**: `CapabilityResolver`, `WorkspaceCapabilityResolver`, policy classes, `UiEnforcement`, `WorkspaceUiEnforcement`, platform capability middleware, existing scoped query helpers. - **New abstraction introduced? why?**: none planned. - **Why the existing abstraction was sufficient or insufficient**: existing abstractions are the correct sources of product authorization semantics; the gap is proof consistency and any missing direct/access tests. - **Bounded deviation / spread control**: gate/capability exception acceptable only when matrix documents why adding a policy would duplicate existing tested contract without increasing safety. ## OperationRun UX Impact - **Touches OperationRun start/completion/link UX?**: proof only, possible if OperationRun-linked actions/resources are hardened. - **Central contract reused**: existing OperationRun policies and links. - **Delegated UX behaviors**: unchanged. - **Surface-owned behavior kept local**: existing initiation inputs only. - **Queued DB-notification policy**: unchanged. - **Terminal notification path**: unchanged. - **Exception path**: none planned. ## Provider Boundary & Portability Fit - **Shared provider/platform boundary touched?**: yes, for provider connection/resource/readiness authorization proof. - **Provider-owned seams**: provider connection credentials/readiness/permissions details. - **Platform-core seams**: workspace/environment authorization, operations, evidence, audit, capabilities, system/admin planes. - **Neutral platform terms / contracts preserved**: workspace, managed environment, provider connection, operation, evidence, audit, capability. - **Retained provider-specific semantics and why**: Microsoft/Graph/Entra terms remain only where existing provider-owned implementation uses them. - **Bounded extraction or follow-up path**: none; provider productization is a later candidate if proof reveals UX friction rather than auth defect. ## Constitution Check - Inventory-first: PASS planned. Authorization proof inspects existing inventory/resource truth and does not alter external truth. - Read/write separation: PASS planned. Any touched mutating action keeps server authorization, confirmation where high-impact/destructive, audit, and tests. - Graph contract path: PASS planned. No new Graph calls. - Deterministic capabilities: PASS planned. Use existing capability resolvers and registries. - RBAC-UX: PASS planned. Admin `/admin` and system `/system` planes remain separate; non-member/wrong-scope access deny-as-not-found; missing capability forbidden at execution level. - Workspace isolation: PASS planned. Cross-workspace direct access tests are required. - Tenant isolation: PASS planned. ManagedEnvironment-scoped resources must remain workspace/environment safe. - Run observability: PASS planned. Existing OperationRun behavior only. - OperationRun start UX: PASS planned. No new local start UX. - Data minimization: PASS planned. No secrets/raw provider payloads in reports/tests. - Test governance: PASS planned. Confidence/browser lanes are explicit; heavy-governance cost remains visible if used. - Proportionality: PASS planned. Matrix/report is review evidence, not runtime framework. - No premature abstraction: PASS planned. No new helper unless spec/plan is updated. - Persisted truth: PASS. No new persistence. - Behavioral state: PASS. No new states. - UI semantics: PASS. No new presentation taxonomy. - Shared pattern first: PASS. Existing authorization helpers preferred. - Provider boundary: PASS. Provider-specific semantics stay bounded. - V1 explicitness / few layers: PASS. Direct tests and targeted hardening only. - Spec discipline / bloat check: PASS. One coherent authorization proof spec rather than many micro-specs. - Filament-native UI: PASS planned. Existing Filament authorization/action patterns preserved. - UI/Productization coverage: PASS planned. Existing-surface authorization hardening only. - Product Surface Contract Gate: PASS planned. Spec/plan/tasks name no-legacy, UI impact, browser proof, human sanity, global search, destructive/high-impact actions, and close-out fields. ## Test Governance Check - **Test purpose / classification by changed surface**: Policy/Gate for authorization decisions; Feature/Filament for resources/actions/relation managers; Browser for representative rendered proof; Heavy-Governance only for broad matrix/discovery guard. - **Affected validation lanes**: confidence, browser, optional heavy-governance. - **Why this lane mix is the narrowest sufficient proof**: resource authorization cannot be proven by unit tests only; browser proof is limited to representative high-risk paths. - **Narrowest proving command(s)**: - `cd apps/platform && ./vendor/bin/sail artisan test --filter=Policy` - `cd apps/platform && ./vendor/bin/sail artisan test --filter=Authorization` - `cd apps/platform && ./vendor/bin/sail artisan test --filter=Capability` - `cd apps/platform && ./vendor/bin/sail artisan test --filter=Filament` - `cd apps/platform && ./vendor/bin/sail artisan test --filter=Resource` - `cd apps/platform && ./vendor/bin/sail artisan test --filter=System` - targeted Spec 402 test files - focused Spec 402 browser smoke if browser test support is available - `git diff --check` - conditional project formatter check for changed PHP runtime/test files - report/test/log redaction check for secrets, tokens, raw credential payloads, and sensitive raw provider payloads - **Fixture / helper / factory / seed / context cost risks**: workspace/environment/user/platform-user setup; keep helpers existing or opt-in. - **Expensive defaults or shared helper growth introduced?**: no by default. - **Heavy-family additions, promotions, or visibility changes**: none planned except explicit matrix/discovery guard if implementation chooses it. - **Surface-class relief / special coverage rule**: standard-native-filament for ordinary resource pages; special coverage for global-context-shell and system-admin boundary. - **Closing validation and reviewer handoff**: implementation report records command results, lane fit, browser proof, and residual findings. - **Budget / baseline / trend follow-up**: none expected; document any material test runtime growth. - **Review-stop questions**: Does every fixed gap have a negative test? Did any policy duplicate capability logic? Did relation/search/bulk proof cover direct access? Did `/system` remain platform-only? - **Escalation path**: document-in-feature by default; follow-up-spec for structural unresolved authorization decisions; reject-or-split for scope creep. - **Active feature PR close-out entry**: `Guardrail / Exception / Smoke Coverage`. - **Why no dedicated follow-up spec is needed**: this spec itself is the bounded authorization proof package; only remaining P0/P1 blockers require a remediation spec. ## Project Structure ### Documentation (this feature) ```text specs/402-resource-policy-authorization-proof-matrix/ ├── spec.md ├── plan.md ├── tasks.md ├── checklists/ │ └── requirements.md └── implementation-report.md # created during implementation ``` ### Source Code (repository root) Implementation may inspect and, if required by confirmed gaps, minimally edit: ```text apps/platform/app/Filament/Resources/ apps/platform/app/Filament/Pages/ apps/platform/app/Filament/System/Pages/ apps/platform/app/Http/Controllers/ apps/platform/app/Http/Middleware/ apps/platform/app/Policies/ apps/platform/app/Providers/AuthServiceProvider.php apps/platform/app/Providers/AppServiceProvider.php apps/platform/app/Services/Auth/ apps/platform/app/Support/Auth/ apps/platform/app/Support/Rbac/ apps/platform/routes/web.php apps/platform/tests/ ``` **Structure Decision**: Use the existing Laravel monolith structure. Do not create new base folders or new runtime packages. Add tests under existing domain folders or focused `Spec402...` files. ## Complexity Tracking | Violation | Why Needed | Simpler Alternative Rejected Because | |---|---|---| | Spec-local authorization matrix/report | Required to prove fragmented resource authorization across admin/system panels | Blind policy generation or local fixes would not prove relation/search/bulk/direct/system boundaries | | Focused browser proof | Required because UI-hidden/disabled state and panel separation are rendered behavior | Feature tests alone cannot prove representative browser/Filament runtime behavior | No runtime abstraction, persisted truth, enum/status family, or UI framework is planned. ## Implementation Phases ### Phase 1 - Baseline and inventory Run required dirty-state commands, inspect panels/resources/routes/policies/gates/tests, and build the internal inventory. No edits before this phase is complete. ### Phase 2 - Resource authorization matrix Create the implementation-report matrix before adding policies or hardening code. Include all columns required by the spec. ### Phase 3 - Gap classification Classify each gap as missing proof only, sufficient gate/capability without policy, missing policy and insufficient path, UI/execution inconsistency, scope risk, system/admin boundary risk, global-search risk, relation/bulk risk, or product-decision required. ### Phase 4 - Tests first for high-risk gaps Add or update negative tests for direct access, action execution, cross-workspace denial, system/admin separation, global search, relation managers, and bulk actions before runtime hardening when feasible. ### Phase 5 - Minimal hardening Only after matrix and tests, apply the smallest safe fix: policy class, policy registration, action-level authorization, search disable/restrict, bulk/relation scoping, controller authorization, or documented exception. ### Phase 6 - Focused browser proof Run a representative browser smoke for allowed admin access, cross-workspace denial, system-only denial to workspace admin, and unauthorized high-impact action visibility/execution. Global-search posture may remain feature-level proof when exercising the search UI would turn the focused smoke into a broader browser audit. ### Phase 7 - Implementation report and validation Complete `implementation-report.md`, classify remaining findings, run targeted validation, record dirty state, and recommend PASS/PASS WITH CONDITIONS/FAIL. ## Risk Controls - Stop and update spec/plan before introducing new roles, capabilities, product surfaces, database changes, or a shared authorization framework. - Treat missing product semantics as `DEFERRED: product decision required`. - Preserve completed specs and historical close-out evidence. - Do not conflate UI visibility with execution authorization. - Do not treat global search as safe unless scoped and tested. - Do not count route middleware alone as record-level authorization proof. ## Rollout Considerations - Staging: run targeted authorization tests and browser proof before merge. - Production: no migrations or env changes expected. If authorization hardening changes access outcomes, release notes should mention stricter authorization enforcement. - Queues/scheduler/storage/assets: no expected impact. - `filament:assets`: no new requirement unless unexpected asset registration occurs, which is out of scope. ## Candidate Readiness - Candidate Selection Gate: planned PASS because the operator explicitly promoted Spec 402, no existing spec package existed, and the scope is bounded to authorization proof/hardening. - Spec Readiness Gate: should pass when `spec.md`, `plan.md`, `tasks.md`, and `checklists/requirements.md` are complete, placeholders are removed, and preparation analysis finds no blocking artifact drift.