7.8 KiB
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 repo’s 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
AuditLogentries.
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 0–1 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.phptests/Feature/Guards/ActionSurfaceValidatorTest.php
Workflow:
- Add
actionSurfaceDeclaration()to one component. - Remove its baseline exemption.
- Run guard tests.
- Repeat.
Step 2 — Shrink baseline exemptions
File: app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php
Remove baseline exemptions for components once they have declarations:
ProviderConnectionResourceBackupScheduleResourceFindingResourceTenantResourceWorkspaces/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
Viewis 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.phpapp/Filament/Resources/Workspaces/WorkspaceResource.php
Ensure:
- Destructive actions are last and confirmed.
- Bulk actions are grouped under a consistent
Moregroup. - Workspaces use
WorkspaceUiEnforcement+WorkspaceAuditLoggerfor 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.