Ziel: Spec/Plan/Tasks für “RBAC UI Enforcement Helper v2” (suite-wide, mixed visibility, record-scoped tenant) bereitstellen, damit die anschließende Implementierung sauber reviewbar ist.
Enthält
Feature-Spec inkl. RBAC-UX Contract (Non-member 404/hidden, member-no-cap disabled + Tooltip, member-with-cap enabled).
Implementation Plan + Research/Decisions.
Contracts:
UiEnforcement v2 (mixed visibility composition, tenant resolvers, bulk preflight).
Guardrails (CI-failing allowlist guard gegen ad-hoc Filament auth patterns).
Data-model/Quickstart/Tasks inkl. “Definition of Done”.
Review-Fokus
Scope: Tenant plane only (/admin/t/{tenant}), Platform plane out of scope.
Bulk semantics: authorization-only all-or-nothing; eligibility separat mit Feedback.
preserveVisibility() nur tenant-scoped, verboten für record-scoped/cross-tenant.
Standard tooltip copy: “Insufficient permission — ask a tenant Owner.”
Keine Code-Änderungen
PR ist spec-only (keine Runtime-Änderungen).
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #82
144 lines
8.4 KiB
Markdown
144 lines
8.4 KiB
Markdown
# 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
|
|
|
|
<!--
|
|
ACTION REQUIRED: Replace the content in this section with the technical details
|
|
for the project. The structure here is presented in advisory capacity to guide
|
|
the iteration process.
|
|
-->
|
|
|
|
**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).
|