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
76 lines
2.6 KiB
Markdown
76 lines
2.6 KiB
Markdown
# Data Model: 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`
|
|
|
|
## Overview
|
|
|
|
This feature does not introduce new database tables. It defines contracts and behaviors that compose existing tenant-plane RBAC (membership + capability gates) into consistent Filament UI states across tenant-scoped and record-scoped surfaces.
|
|
|
|
## Entities (existing)
|
|
|
|
### Tenant
|
|
|
|
The isolation boundary for all tenant-plane actions.
|
|
|
|
**Identity**
|
|
- `tenants.id` (PK)
|
|
- A user is a “member” if `user->canAccessTenant($tenant)` is true.
|
|
|
|
### User
|
|
|
|
Authenticated tenant-plane actor.
|
|
|
|
**Key behaviors**
|
|
- Must support membership checks (`canAccessTenant($tenant)`).
|
|
- Capability checks are performed via Gates/Policies using `Capabilities::*` identifiers.
|
|
|
|
### TenantMembership
|
|
|
|
Joins a User to a Tenant with a role mapped to capabilities (Feature 065).
|
|
|
|
**Key behaviors**
|
|
- Role → capabilities mapping is centralized and deterministic.
|
|
- Requests should avoid repeated membership DB queries (request-scope cache).
|
|
|
|
### Capability (registry)
|
|
|
|
Canonical capability keys live in `app/Support/Auth/Capabilities.php` and must be referenced via constants (`Capabilities::*`).
|
|
|
|
## Entities (conceptual, not persisted)
|
|
|
|
### UiEnforcementContext
|
|
|
|
Context used to evaluate membership/capability for an action.
|
|
|
|
**Fields**
|
|
- `user`: current authenticated user (or null)
|
|
- `tenantResolver`: one of:
|
|
- `tenantFromFilament` (tenant-scoped)
|
|
- `tenantFromRecord` (record == tenant)
|
|
- `tenantFrom(callable)` (record → tenant mapping)
|
|
- `record`: optional record for table/record actions
|
|
- `capability`: required capability identifier (from `Capabilities::*`)
|
|
|
|
### UiEnforcementDecision
|
|
|
|
The derived UI behavior applied to a Filament action.
|
|
|
|
**Fields**
|
|
- `isVisible`: boolean (non-members must not be able to discover actions)
|
|
- `isEnabled`: boolean (members without capability see disabled action)
|
|
- `disabledTooltip`: string (standardized via `UiTooltips`)
|
|
- `requiresConfirmation`: boolean (destructive/high-impact actions)
|
|
|
|
### BulkSelectionAuthorization (preflight)
|
|
|
|
Derived authorization status for a bulk action selection.
|
|
|
|
**Fields**
|
|
- `selectedIds`: list of record IDs
|
|
- `resolvedTenants`: list of tenant IDs derived via tenant resolver (record == tenant or mapping)
|
|
- `unauthorizedCount`: count of records failing authorization (determines all-or-nothing disable)
|
|
- `ineligibleCount`: optional count of business-ineligible records (may be skipped with deterministic feedback; does not affect authorization disable by default)
|
|
|