# Data Model: Spec 136 Admin Panel Canonical Tenant Resolution Full Rollout

## Overview

This feature introduces no new database tables or persisted business objects. Its data model is request-time and behavioral: it formalizes how surface classification, panel mode, canonical admin tenant context, session-backed filter state, and sensitive actions combine into one deterministic tenant outcome.

## Entity: Surface Inventory Entry

**Purpose**: Represents one admin-visible or admin-reachable surface in the rollout manifest.

**Fields**:
- `surface_name`
- `class_name`
- `surface_kind` enum: `resource`, `page`, `widget`, `shared_helper`, `guarded_file`
- `classification` enum: `type_a`, `type_b`, `type_c`
- `visibility_mode` enum: `admin_visible`, `shared_code_path`, `tenant_panel_only_but_reviewed`
- `has_persisted_tenant_filters` boolean
- `has_global_search` boolean
- `has_sensitive_actions` boolean
- `guard_required` boolean

**Relationships**:
- may reference one resource, page, or widget class
- may depend on one or more support-layer resolver or filter-state helpers

**Validation rules**:
- Every rollout surface must have exactly one classification.
- Type A and Type B surfaces must be guard-covered unless explicitly documented as an exception.
- Type C surfaces must not acquire hidden tenant enforcement in read or write paths.

## Entity: Canonical Admin Tenant Context

**Purpose**: Represents the single tenant context used by workspace-admin tenant-sensitive flows.

**Source fields**:
- `workspace_id`
- `panel_id`
- `route_tenant_id` nullable
- `filament_tenant_id` nullable
- `remembered_tenant_id` nullable
- `resolved_tenant_id` nullable
- `resolution_source` enum: `route`, `filament`, `remembered`, `none`
- `is_entitled` boolean

**Relationships**:
- belongs to one current workspace
- may resolve to one entitled tenant
- drives header context, queries, filter defaults, widgets, links, and sensitive actions for Type A and Type B admin surfaces

**Validation rules**:
- `resolved_tenant_id` must be null when no entitled tenant exists.
- The same resolved tenant must drive every tenant-sensitive element of the same admin surface.
- When the panel is admin, raw panel-native tenant reads are not valid substitutes for this entity.

## Entity: Panel Resolver Contract

**Purpose**: Encodes which resolver is allowed in a given panel mode.

**Fields**:
- `panel_id`
- `allowed_source` enum: `operate_hub_shell`, `filament_tenant`, `none`
- `fallback_behavior` enum: `remembered_allowed`, `no_fallback`, `safe_none`
- `applies_to` enum: `admin`, `tenant`, `shared_surface`

**Validation rules**:
- Admin panel uses `operate_hub_shell`.
- Tenant panel uses `filament_tenant`.
- Shared surfaces must branch by current panel rather than blending both rules.

## Entity: Persisted Tenant Filter Session State

**Purpose**: Represents session-backed filter state whose validity depends on the current canonical admin tenant.

**Fields**:
- `filters_session_key`
- `tenant_sensitive_filters` array
- `previous_resolved_tenant_id` nullable
- `current_resolved_tenant_id` nullable
- `resolution_action` enum: `apply`, `reseed`, `clear`
- `has_invalid_values` boolean

**Relationships**:
- belongs to one table or page surface
- depends on one `Canonical Admin Tenant Context`

**Validation rules**:
- Tenant-sensitive filter values must be cleared or reseeded when resolved tenant changes.
- If `current_resolved_tenant_id` is null, tenant-specific filter state must not remain active.
- Workspace-wide Type B surfaces may preserve non-tenant filters while clearing or reseeding tenant-specific ones.

## Entity: Sensitive Action Scope Contract

**Purpose**: Represents the tenant parity requirement between visible surface context and a sensitive action target.

**Fields**:
- `surface_name`
- `action_name`
- `visible_tenant_id` nullable
- `query_tenant_id` nullable
- `action_tenant_id` nullable
- `authorization_outcome` enum: `ok`, `not_found`, `forbidden`
- `confirmation_required` boolean

**Relationships**:
- belongs to one rollout surface
- depends on one resolved tenant context and one authorization decision

**Validation rules**:
- `action_tenant_id` must equal `visible_tenant_id` for Type A surfaces.
- Out-of-scope or missing tenant access must remain `not_found` when membership is not established.
- Existing destructive-like actions must still require confirmation and server-side authorization.

## Entity: Search and Record Resolution Contract

**Purpose**: Represents list, detail, deep-link, and global-search parity for tenant-sensitive resources.

**Fields**:
- `surface_name`
- `access_path` enum: `list`, `detail`, `direct_url`, `deep_link`, `global_search`
- `panel_mode` enum: `admin`, `tenant`
- `resolved_tenant_id` nullable
- `record_tenant_id` nullable
- `parity_outcome` enum: `aligned`, `disabled`, `not_found`, `forbidden`

**Validation rules**:
- Detail and direct access must never be broader than list scope.
- Global search must either match list/detail parity or be disabled.
- Admin no-context behavior must be explicit and deterministic per surface class.

## Entity: Guard Coverage Entry

**Purpose**: Documents whether a file is enforced by the admin tenant resolver guard or allowed as an exception.

**Fields**:
- `relative_path`
- `surface_name`
- `guard_status` enum: `guarded`, `exception`
- `exception_reason` nullable
- `review_owner`

**Validation rules**:
- Exceptions must be explicit and stable.
- Admin-only files are not valid exceptions for raw `Filament::getTenant()` or `Tenant::current()` reads.
- Guard output must clearly distinguish true violations from approved tenant-panel-native usage.

## State Transitions

### Canonical admin tenant state

1. `none`
  - No entitled route, Filament, or remembered tenant is available.
  - Outcome: safe no-tenant-selected behavior by surface type.

2. `remembered`
  - Only remembered tenant is valid and entitled.
  - Outcome: remembered tenant becomes the canonical admin tenant for the full request.

3. `filament`
  - A Filament tenant is valid and entitled.
  - Outcome: Filament tenant becomes the canonical admin tenant for the full request.

4. `route`
  - A route tenant parameter is present and entitled for a tenant-panel or shared route.
  - Outcome: route tenant governs the request where panel-native semantics apply.

### Persisted filter synchronization state

1. `unchanged`
  - Previous and current resolved tenant IDs match.
  - Outcome: persisted tenant filter values may remain.

2. `tenant_switched`
  - Previous and current resolved tenant IDs differ.
  - Outcome: tenant-sensitive filter values are cleared or reseeded.

3. `tenant_removed`
  - Current resolved tenant ID becomes null.
  - Outcome: tenant-sensitive filter values are cleared.

## Invariants

- One workspace-admin surface uses one tenant source for every tenant-sensitive element.
- Shared resources must branch by panel mode instead of mixing admin and tenant rules inside one execution path.
- Persisted tenant filter state is never trusted without synchronization.
- Search, list, detail, and deep-link behavior cannot exceed the same tenant boundary.
- Existing destructive or governance-sensitive actions keep their confirmations and authorization while gaining tenant-target parity.