# Data Model: Central Tenant Status Presentation ## 1. TenantLifecycleState - Purpose: The canonical tenant lifecycle domain value already defined by Spec 143 and implemented in `TenantLifecycle`. - Source: Existing tenant domain model. - Fields: - `value`: enum string - Allowed values: `draft`, `onboarding`, `active`, `archived` - `label`: string - Allowed values: `Draft`, `Onboarding`, `Active`, `Archived` - Relationships: - Derived from one `Tenant` - Referenced by one `TenantLifecyclePresentation` - Validation rules: - Must be one of the four canonical lifecycle values for normal presentation flow - Non-canonical values must bypass canonical rendering and enter invalid-data fallback only - State transitions: - Not defined here; owned by Spec 143 and the tenant domain ## 2. TenantLifecyclePresentation - Purpose: The authoritative UI presentation contract for a lifecycle state. - Ownership: Presentation layer only; no persistence required. - Fields: - `value`: canonical lifecycle value - `label`: canonical operator-facing label - `badge_color`: concise badge/chip color token - `badge_icon`: icon token for badge or chip rendering - `short_description`: concise explanatory text for detail or selector surfaces - `long_description`: longer helper text for infolists, banners, or canonical viewers - `is_invalid_fallback`: boolean flag reserved for corrupted or unexpected input - Relationships: - Belongs to one `TenantLifecycleState` when canonical - May be constructed from a referenced tenant in a canonical viewer - Validation rules: - Canonical values must always produce `is_invalid_fallback = false` - Invalid fallback must never be used for `draft`, `onboarding`, `active`, or `archived` - `label` must match the canonical lifecycle vocabulary for canonical values ## 3. TenantLifecyclePresentationVariant - Purpose: Surface-specific density derived from the same underlying lifecycle meaning. - Ownership: Presentation composition only. - Fields: - `surface`: enum-like string - Expected values: `table`, `detail`, `selector`, `canonical_viewer`, `banner` - `show_badge`: boolean - `show_short_description`: boolean - `show_long_description`: boolean - `show_context_note`: boolean - Relationships: - Belongs to one `TenantLifecyclePresentation` - Validation rules: - Must not alter `value` or `label` - May change density only, never meaning ## 4. ReferencedTenantLifecycleContext - Purpose: Captures how lifecycle is shown when a tenant appears as context on another record, such as an operation run. - Ownership: Canonical viewer presentation only. - Fields: - `tenant_id`: integer or null - `tenant_name`: string or null - `lifecycle_value`: canonical lifecycle value or invalid raw value - `viewer_context`: string - Expected examples: `operation_run`, `report`, `audit_reference` - `context_note`: optional explanatory text describing why the referenced tenant may be non-active - Relationships: - References one `Tenant` - Uses one `TenantLifecyclePresentation` - Validation rules: - Must only be constructed after existing viewer authorization succeeds - Must not imply the canonical record is invalid when the tenant lifecycle is `onboarding` or `archived` ## 5. Existing Domain Models in Scope ### Tenant - Existing model: `App\Models\Tenant` - Relevant existing fields: - `status` - `deleted_at` / soft-delete state - `workspace_id` - `name` - `domain` - `app_status` - `rbac_status` - Relevant derived methods: - `lifecycle()` - `isDraft()` - `isOnboarding()` - `isArchived()` ### OperationRun - Existing model: `App\Models\OperationRun` - Relevant existing fields: - `tenant_id` - `workspace_id` - `status` - `outcome` - `context` - Role in this feature: - Supplies referenced tenant context only - No lifecycle ownership changes - No `OperationRun` state machine changes ## 6. Invariants - Tenant lifecycle presentation must remain exhaustive for canonical states. - Lifecycle presentation must not redefine lifecycle transitions or authorization. - Lifecycle and health-like domains must remain separate in the rendered UI. - Surface-specific rendering may change density, but not label or semantic meaning. - Invalid fallback is reserved exclusively for non-canonical lifecycle data.