TenantAtlas/specs/402-resource-policy-authorization-proof-matrix/plan.md
Ahmed Darrazi eaf28229e0
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m7s
feat: add resource policy authorization proof matrix
2026-06-23 09:44:21 +02:00

22 KiB

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)

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:

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.