6.6 KiB
Phase 1 Data Model: Central Tenant Operability Policy
Overview
This feature does not require a new database table in its first implementation slice. The primary data-model work is the formalization of existing persistent records plus new derived domain objects that express tenant operability consistently across lanes.
Persistent Domain Entities
Tenant
Purpose: Durable workspace-owned record whose lifecycle influences operability.
Key fields:
idworkspace_idexternal_idstatuswith canonical valuesdraft,onboarding,active,archiveddeleted_atfor archive persistence behavior
Relationships:
- Belongs to one workspace
- Has many onboarding sessions, audit logs, provider connections, and tenant-owned operational records
- May be referenced by canonical workspace records such as
OperationRun
Validation rules:
workspace_idmust match the active workspace scope for all in-scope route or action decisionsstatusmust resolve through the canonicalTenantLifecyclemodel- Soft-delete state is an implementation input, never the only semantic rule
State transitions relevant to this feature:
draft→onboardingonboarding→activeactive→archivedarchived→active
TenantOnboardingSession
Purpose: Separate workspace-scoped workflow record used to evaluate onboarding-lane actions.
Key fields:
idworkspace_idtenant_idnullable until linked- workflow state and lifecycle fields already used by onboarding services
Relationships:
- Belongs to one workspace
- Optionally belongs to one tenant
Validation rules:
- Must be in the same workspace as any linked tenant
- Onboarding-specific operability decisions must validate both tenant lifecycle and workflow resumability
OperationRun
Purpose: Canonical workspace-owned record that may reference a tenant without becoming subordinate to selected tenant context.
Key fields:
idworkspace_idtenant_idnullabletypestatusoutcome
Relationships:
- Belongs to one workspace
- May belong to one tenant reference
Validation rules:
- Canonical route legitimacy is based on the run and workspace first
- Tenant-linked follow-up actions must still respect tenant entitlement and operability outcomes
UserTenantPreference and WorkspaceContext Session State
Purpose: Stores remembered tenant context for the active operating lane.
Key fields:
user_idtenant_idlast_used_at- session-scoped workspace and remembered-tenant identifiers
Validation rules:
- Remembered tenant is valid only when workspace match, tenant existence, entitlement, and selector-lane operability all still hold
New Derived Domain Objects
TenantInteractionLane
Purpose: Explicitly identifies the lane in which the tenant is being evaluated.
Canonical values:
standard_active_operatingonboarding_workflowadministrative_managementcanonical_workspace_record
Why it exists:
- The same tenant can be selector-ineligible yet still administratively viewable or canonically referenceable
TenantOperabilityContext
Purpose: Normalized evaluation input for the central policy layer.
Fields:
tenantactorworkspaceIdlanepageCategorylinkedRecordTypenullablelinkedRecordIdnullableonboardingDraftnullablerequiredCapabilitynullableselectedTenantnullable
Context ownership:
- Consumers normalize and pass route, record, workflow, and selected-tenant inputs into the context.
- The central service resolves workspace membership, tenant entitlement, capability truth, lifecycle, and archived persistence state through canonical workspace, tenant, and RBAC helpers at evaluation time.
- Consumers may request a capability-aware question, but they do not authoritatively decide membership or entitlement before evaluation.
Validation rules:
tenant.workspace_idmust equalworkspaceId- linked records must belong to the same workspace when tenant-linked
selectedTenantmay be informative but never authoritative
TenantOperabilityQuestion
Purpose: Declares the exact semantic question the consumer is asking.
Canonical values:
selector_eligibilityremembered_context_validitytenant_bound_viewabilitycanonical_linked_record_viewabilityarchive_eligibilityrestore_eligibilityresume_onboarding_eligibilityonboarding_completion_eligibilityverification_readiness_eligibilityadministrative_discoverability
TenantOperabilityOutcome
Purpose: Structured result returned by the central operability policy.
Fields:
questionallowedlifecyclelanereasonCodenullablerequiredCapabilitynullablediscoverablebooleaninformationalMessageKeynullablemetadatakey-value bag for consumer-safe hints
Behavior:
- Must be stable enough for unit assertions and UI mapping
- May expose helper methods for common adapters, but raw outcome data remains canonical
TenantOperabilityReasonCode
Purpose: Stable denial or ineligibility reason catalog.
Initial values:
workspace_mismatchtenant_not_entitledmissing_capabilitywrong_laneselector_ineligible_lifecycletenant_not_archivedtenant_already_archivedonboarding_not_resumablecanonical_view_followup_onlyremembered_context_stale
Consumer Mapping
| Consumer | Primary question(s) |
|---|---|
| Choose-tenant page | selector_eligibility |
| Select-tenant controller | selector_eligibility, remembered_context_validity |
| WorkspaceContext | remembered_context_validity |
| OperateHubShell | tenant_bound_viewability, canonical_linked_record_viewability, administrative_discoverability |
| TenantActionPolicySurface | archive_eligibility, restore_eligibility, resume_onboarding_eligibility, verification_readiness_eligibility |
| ManagedTenantOnboardingWizard | resume_onboarding_eligibility, onboarding_completion_eligibility, verification_readiness_eligibility |
| TenantResource global search and admin listing | administrative_discoverability |
| TenantlessOperationRunViewer | canonical_linked_record_viewability and follow-up action questions |
Migration Notes
- No persistence migration is required for the first slice.
- Existing boolean accessors on
TenantOperabilityServicemay remain as compatibility adapters while consumers migrate to structured outcomes. - Any new enums or value objects should live under
app/Support/Tenantsto stay aligned with existing lifecycle, page-category, and action-surface support code.