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

