TenantAtlas/specs/090-action-surface-contract-compliance/plan.md
2026-02-13 02:29:38 +01:00

7.8 KiB
Raw Blame History

Implementation Plan: Action Surface Contract Compliance & RBAC Hardening (Spec 090)

Branch: 090-action-surface-contract-compliance | Date: 2026-02-12 | Spec: specs/090-action-surface-contract-compliance/spec.md Input: Feature specification from specs/090-action-surface-contract-compliance/spec.md

Summary

Bring a focused set of Filament v5 action surfaces into compliance with the repos Filament UI Action Surface Contract, and harden RBAC semantics using the existing enforcement helpers.

This work primarily:

  • Shrinks ActionSurfaceExemptions::baseline() for the in-scope components.
  • Adds actionSurfaceDeclaration() to those components (or explicit exemptions with reasons).
  • Standardizes action ordering/grouping (“View → Edit → More → Destructive last”; max 2 visible row actions).
  • Ensures successful side-effect actions create AuditLog entries.

Technical Context

Language/Version: PHP 8.4.15 Framework: Laravel 12 Admin UI: Filament v5 + Livewire v4.0+ Storage: PostgreSQL (Sail) Testing: Pest v4 (vendor/bin/sail artisan test) Target Platform: Docker/Sail local; Dokploy staging/prod Project Type: Laravel monolith Performance Goals: Keep “start” surfaces enqueue-only; preserve guard test runtime Constraints:

  • No new dependencies
  • BackupSchedule retention is explicitly deferred
  • Use existing RBAC + audit primitives; no new tables Scale/Scope: Multi-tenant admin UI; targeted subset of Resources/Pages

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

  • Filament v5 targets Livewire v4.0+ (no Livewire v3)
  • Authorization is enforced server-side (UI visibility is not security)
  • RBAC-UX semantics: non-member → 404; member missing capability → 403 (and disabled + tooltip in UI)
  • Destructive actions execute via ->action(...) and include ->requiresConfirmation()
  • Action Surface Contract enforced via guard tests; exemptions must be explicit and minimized
  • Audit logs for successful side-effect actions (per spec clarification)

Project Structure

Documentation (this feature)

specs/090-action-surface-contract-compliance/
├── spec.md
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
└── contracts/
    └── action-surface-contract-v1.openapi.yaml

Source Code (relevant to this spec)

app/
├── Filament/Resources/
│   ├── ProviderConnectionResource.php
│   ├── BackupScheduleResource.php
│   ├── FindingResource.php
│   ├── TenantResource.php
│   ├── PolicyResource/Pages/ListPolicies.php
│   └── PolicyResource/Pages/ViewPolicy.php
├── Filament/Resources/Workspaces/WorkspaceResource.php
├── Support/Rbac/UiEnforcement.php
├── Support/Rbac/WorkspaceUiEnforcement.php
└── Support/Ui/ActionSurface/
    ├── ActionSurfaceDeclaration.php
    └── ActionSurfaceExemptions.php

tests/Feature/Guards/
├── ActionSurfaceContractTest.php
└── ActionSurfaceValidatorTest.php

Structure Decision: Laravel monolith; modifications are limited to existing Filament resources/pages + guard tests.

Phase 0 — Outline & Research (DOCS COMPLETE)

Completed in specs/090-action-surface-contract-compliance/research.md.

Key findings:

  • Action Surface Contract enforcement already exists via guard tests and ActionSurfaceDeclaration.
  • Many in-scope resources are currently excluded by ActionSurfaceExemptions::baseline().
  • RBAC enforcement helpers exist and already implement 404/403 semantics: UiEnforcement, WorkspaceUiEnforcement.
  • Audit logging services exist and sanitize metadata.

Phase 1 — Design & Contracts (DOCS COMPLETE)

Outputs:

  • data-model.md: No schema changes required.
  • contracts/action-surface-contract-v1.openapi.yaml: Internal contract artifact (no new HTTP endpoints).
  • quickstart.md: Local verification commands and checklist.

Design choices:

  • “View” requirement is interpreted as an inspection affordance (clickable row, primary linked column, or explicit View action) consistent with the constitution.
  • Audit logs are required for successful dispatch/execution surfaces only.
  • Directory groups (Entra groups) and inventory items already follow the inspection-affordance pattern (clickable rows) and have explicit declarations; they are verification-only in this spec to avoid expanding scope.

Note: Phases 01 are complete for documentation and design artifacts. Implementation and verification work begins in Phase 2 and is tracked in specs/090-action-surface-contract-compliance/tasks.md.

Phase 2 — Implementation Plan

Step 1 — Make contract guard the primary gate

Target guard tests:

  • tests/Feature/Guards/ActionSurfaceContractTest.php
  • tests/Feature/Guards/ActionSurfaceValidatorTest.php

Workflow:

  1. Add actionSurfaceDeclaration() to one component.
  2. Remove its baseline exemption.
  3. Run guard tests.
  4. Repeat.

Step 2 — Shrink baseline exemptions

File: app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php

Remove baseline exemptions for components once they have declarations:

  • ProviderConnectionResource
  • BackupScheduleResource
  • FindingResource
  • TenantResource
  • Workspaces/WorkspaceResource

Step 3 — Add action surface declarations (per component)

Add actionSurfaceDeclaration() and ensure required slots are satisfied.

Expected profile direction (final selection should match existing profiles in the repo):

  • CRUD list + inspect + edit: use a CRUD-capable profile; keep row actions to 2 max.
  • List-only read-only resources should use a read-only profile (already in repo patterns).

Step 4 — Fix known hotspots

(P1) Policy: Capture snapshot dispatch

File: app/Filament/Resources/PolicyResource/Pages/ViewPolicy.php

  • Wrap action with UiEnforcement::forAction(...) using the canonical capability.
  • Ensure the server-side before(...) aborts with 404/403 appropriately.
  • Add audit logging on successful dispatch via App\Services\Intune\AuditLogger.

(P1) Policy: Sync action confirmation semantics

File: app/Filament/Resources/PolicyResource/Pages/ListPolicies.php

  • Remove misuse of destructive() for non-destructive sync/run actions.
  • Keep confirmation if required, but with non-destructive semantics.

(P2) Findings: action ordering + grouping

File: app/Filament/Resources/FindingResource.php

  • Ensure View is first.
  • Move secondary actions (like acknowledge) into More.
  • Ensure bulk actions are grouped and capability gated via UiEnforcement.

(P2/P3) Backup schedules: empty-state CTA + grouping

File: app/Filament/Resources/BackupScheduleResource.php

  • Ensure empty-state action exists (create) and is capability gated.
  • Ensure “run now / retry” actions are gated and audited (audit already exists for manual dispatch; verify consistency).

(P1/P2) Tenant + Workspaces: RBAC semantics + bulk grouping

Files:

  • app/Filament/Resources/TenantResource.php
  • app/Filament/Resources/Workspaces/WorkspaceResource.php

Ensure:

  • Destructive actions are last and confirmed.
  • Bulk actions are grouped under a consistent More group.
  • Workspaces use WorkspaceUiEnforcement + WorkspaceAuditLogger for workspace-scoped side effects.

Step 5 — Testing plan

Minimum programmatic verification:

  • Guard tests stay green as exemptions shrink.
  • Add or extend focused Pest feature tests for:
    • 404 vs 403 RBAC semantics for at least one representative mutation action.
    • Successful audit log creation for at least one enqueue/dispatch surface.

Step 6 — Formatting

Run formatter before final handoff:

  • vendor/bin/sail bin pint --dirty

Deploy / Ops Notes

  • No migrations expected.
  • No new Filament assets expected; if any assets are registered, ensure deploy runs php artisan filament:assets.