285 lines
22 KiB
Markdown
285 lines
22 KiB
Markdown
# 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.
|