# 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)