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
64 lines
2.7 KiB
Markdown
64 lines
2.7 KiB
Markdown
# Quickstart: RBAC UI Enforcement Helper v2
|
|
|
|
**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`
|
|
|
|
## Local setup
|
|
|
|
1. Start the app stack:
|
|
- `./vendor/bin/sail up -d`
|
|
2. Install dependencies (if needed):
|
|
- `./vendor/bin/sail composer install`
|
|
|
|
## Recipes (once implemented)
|
|
|
|
> Scope: Tenant plane only (`/admin/t/{tenant}`). Platform plane (`/system`) is out of scope.
|
|
|
|
### Tenant-scoped action (default tenant from Filament)
|
|
|
|
- Use `UiEnforcement` with the required `Capabilities::*` constant.
|
|
- Non-members should never see the action (routing already denies them).
|
|
- Members without capability see a disabled action + standard tooltip.
|
|
|
|
### Mixed visibility (business visibility + RBAC)
|
|
|
|
- If the surface already has business visibility rules, use composition:
|
|
- **Tenant-scoped**: you may use `preserveVisibility()` to keep existing visibility closures unchanged.
|
|
- **Record-scoped / cross-tenant lists**: do not use `preserveVisibility()`; instead use `andVisibleWhen(...)` / `andHiddenWhen(...)` so non-members cannot discover actions.
|
|
|
|
### Record-scoped tenant (record == tenant)
|
|
|
|
- Configure enforcement with `tenantFromRecord()` so membership/capability checks are evaluated per row/record tenant.
|
|
- Non-members must be deny-as-not-found (404) on direct access/execution attempts.
|
|
|
|
### Bulk actions (authorization-only all-or-nothing)
|
|
|
|
- Use bulk preflight to disable the action if any selected record is unauthorized.
|
|
- Keep business eligibility separate (e.g., skip inactive/archived records with deterministic feedback).
|
|
|
|
## Notes on Filament execution semantics
|
|
|
|
- Hidden actions do not execute (silent no-op). This is acceptable for the non-member contract.
|
|
- Disabled actions do not execute (silent no-op). This is acceptable for member-without-capability.
|
|
- Server-side authorization remains required (UI is not security). Where reachable:
|
|
- Non-member: deny-as-not-found (404)
|
|
- Member without capability: 403
|
|
|
|
## Manual QA checklist (once implemented)
|
|
|
|
- Log in as a tenant member without the capability:
|
|
- Action visible but disabled, with tooltip “Insufficient permission — ask a tenant Owner.”
|
|
- Clicking does not execute.
|
|
- Remove membership:
|
|
- Action hidden; direct access returns 404.
|
|
- Bulk selection with mixed authorization:
|
|
- Bulk action is disabled; no partial execution.
|
|
|
|
## Test run (once implemented)
|
|
|
|
- `./vendor/bin/sail bin pint --dirty`
|
|
- `./vendor/bin/sail artisan test tests/Feature/Guards --compact`
|
|
- `./vendor/bin/sail artisan test tests/Feature/Filament --compact`
|
|
- `./vendor/bin/sail artisan test tests/Feature/Rbac --compact`
|