# Implementation Plan: RBAC UI Enforcement Helper v2 (Suite-wide, Mixed Visibility, Record-Scoped) **Branch**: `066-rbac-ui-enforcement-helper-v2` | **Date**: 2026-01-30 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/spec.md` **Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/spec.md` **Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts. ## Summary - Extend the RBAC UI enforcement suite (Feature 066 v1) with explicit primitives for: - mixed visibility composition (business visibility + RBAC visibility), - record-scoped tenant resolution (record == tenant, or record → tenant mapping), - deterministic bulk preflight authorization with all-or-nothing semantics (authorization-only by default). - Migrate the highest-risk remaining Filament surfaces (BackupSet/RestoreRun mixed visibility, TenantResource record-scoped actions), plus Tier 2 allowlist “easy wins”, shrinking the CI-failing guard allowlist. - Add focused integration tests per migrated surface to assert the RBAC-UX contract (hidden/disabled + tooltip + non-execution), and keep render DB-only (no outbound HTTP). ## Technical Context **Language/Version**: PHP 8.4 (Laravel 12) **Primary Dependencies**: Laravel 12 + Filament v5 + Livewire v4 **Storage**: PostgreSQL (Sail) **Testing**: Pest (PHPUnit) **Target Platform**: Web application (Sail/Docker locally; container deploy via Dokploy) **Project Type**: web **Performance Goals**: Membership/capability evaluation is O(1) per request after initial load; bulk preflight avoids N+1 (set-based where feasible) **Constraints**: DB-only render/hydration; no outbound HTTP during render; tenant isolation; hidden/disabled actions must not execute; destructive actions require confirmation **Scale/Scope**: Suite-wide helper primitives + targeted migrations (Tier 1 + Tier 2 hitlist) rather than a full Filament sweep ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Inventory-first, snapshots-second: N/A (helper only; no inventory semantics changed). - Read/write separation: PASS (no new write flows introduced; existing destructive flows remain confirmation-gated and server-authorized). - Single contract path to Graph: PASS (helper + UI rendering remain DB-only; no Graph calls introduced). - Deterministic capabilities: PASS (migrated surfaces reference `Capabilities::*` only; no ad-hoc ability strings). - RBAC Standard: PASS (tenant plane only; platform plane out of scope; non-member is deny-as-not-found/404). - Tenant isolation: PASS (record-scoped tenant resolution evaluates membership per tenant record; non-members receive 404 on direct access). - Operations / run observability standard: N/A (no changes to OperationRun orchestration; only UI authorization enforcement). - Automation (locks + idempotency): N/A (no new queued ops introduced). - Data minimization & safe logging: PASS (no new persisted payloads; enforcement must not log secrets/PII). - Badge semantics (BADGE-001): N/A. ## Project Structure ### Documentation (this feature) ```text specs/066-rbac-ui-enforcement-helper/ ├── plan.md # This file (/speckit.plan command output) ├── research.md # Phase 0 output (/speckit.plan command) ├── data-model.md # Phase 1 output (/speckit.plan command) ├── quickstart.md # Phase 1 output (/speckit.plan command) ├── contracts/ # Phase 1 output (/speckit.plan command) └── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan) ``` ### Source Code (repository root) ```text app/ ├── Filament/ │ └── Resources/ │ ├── BackupSetResource.php │ ├── RestoreRunResource.php │ ├── TenantResource.php │ ├── InventoryItemResource.php │ ├── InventorySyncRunResource.php │ ├── EntraGroupSyncRunResource.php │ └── ProviderConnectionResource.php ├── Support/ │ └── Auth/ │ ├── UiEnforcement.php # expected from Feature 066 v1 (verify in implementation worktree) │ └── UiTooltips.php # expected from Feature 066 v1 (verify in implementation worktree) └── Support/Auth/Capabilities.php tests/ ├── Feature/ │ ├── Filament/ │ └── Guards/ └── Unit/ └── Auth/ ``` **Structure Decision**: Single Laravel web application with Filament resources. v2 work focuses on `app/Support/Auth` helper primitives, a small set of Filament resources/pages, and regression tests. ## Complexity Tracking No constitution violations required for this feature. ## Phase 0 — Research (output: `research.md`) See: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/research.md` Goals: - Confirm Filament v5 action/table semantics needed for enforcement (visibility/disabled/tooltips; bulk action lifecycle). - Confirm the helper can compose business visibility deterministically without requiring “read back” of existing closures. - Confirm bulk selection preflight can be implemented without N+1 membership checks (set-based queries where feasible). - Verify the exact locations of the Feature 066 v1 helper + guard + allowlist in the implementation worktree (spec branch may not contain v1 code). ## Phase 1 — Design & Contracts (outputs: `data-model.md`, `contracts/`, `quickstart.md`) See: - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/data-model.md` - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/contracts/` - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/quickstart.md` Design focus: - Helper API: `preserveVisibility()` (tenant-scoped only), `andVisibleWhen(...)`, `andHiddenWhen(...)`. - Tenant resolution modes: `tenantFromFilament()` (default), `tenantFromRecord()` (record == tenant), and `tenantFrom(callable)` for custom mapping. - Bulk preflight: deterministic authorization-only all-or-nothing default; business eligibility handled separately with clear user feedback. - Test strategy: per-surface Filament integration tests for hidden/disabled/tooltips and no-execution; DB-only rendering enforced via `Http::preventStrayRequests()`. ## Phase 1 — Agent Context Update After Phase 1 artifacts are generated, update Codex context from the plan: - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/.specify/scripts/bash/update-agent-context.sh codex` ## Phase 2 — Implementation Outline (tasks created in `/speckit.tasks`) - Extend `UiEnforcement` helper primitives (mixed visibility composition + tenant resolvers + bulk preflight API). - Migrate Tier 1 surfaces: - BackupSet (resource + relation managers) for mixed visibility. - RestoreRun (resource + actions) for mixed visibility. - TenantResource row actions + bulk actions for record-scoped tenant enforcement and authorization-only bulk preflight. - Migrate Tier 2 allowlist “easy wins” (Inventory + Entra group runs + ProviderConnection mixed visibility where present). - Shrink the CI-failing allowlist: remove entries for every migrated file in the same batch. - Add integration tests per migrated surface: - non-member: hidden + cannot execute (deny-as-not-found / 404 where reachable), - member without capability: visible but disabled + standard tooltip + cannot execute, - member with capability: enabled and executes; destructive actions require confirmation. - Run quality gates per batch: `./vendor/bin/sail bin pint --dirty` + targeted Pest suites + guard tests. ## Constitution Check (Post-Design) Re-check result: PASS. Design artifacts keep enforcement DB-only, tenant-plane only, capabilities-first, and preserve deny-as-not-found behavior for non-members (including record-scoped tenant surfaces).