# Phase 1 Data Model: Provider Readiness Source-of-Truth Cleanup ## Overview This feature adds no table, no new enum, and no persisted readiness artifact. It reclassifies which already-stored fields are allowed to act as leading operator truth on tenant and provider connection surfaces. ## Persistent Source Truths ### Tenant **Purpose**: Tenant identity and lifecycle boundary for all tenant-facing operator surfaces. **Key fields**: - `id` - `workspace_id` - `external_id` - `name` - `status` - `app_status` (legacy tenant-level projection) - `rbac_status` **Relationships**: - `Tenant` has many `ProviderConnection` **Validation rules**: - `status` remains the authoritative tenant lifecycle input and maps through `TenantLifecycle`. - `app_status` remains persisted but is no longer allowed to act as leading operator truth on targeted tenant surfaces. - `rbac_status` remains a separate domain and must not substitute for provider readiness. ### ProviderConnection **Purpose**: Canonical stored provider-connection record for tenant-scoped provider integration state. **Key fields**: - `id` - `tenant_id` - `workspace_id` - `provider` - `display_name` - `is_default` - `connection_type` - `consent_status` - `verification_status` - `status` (legacy connection-state projection) - `health_status` (legacy health projection) - `last_health_check_at` - `last_error_reason_code` - `last_error_message` - `migration_review_required` **Relationships**: - `ProviderConnection` belongs to `Tenant` - `ProviderConnection` belongs to `Workspace` - `ProviderConnection` has one `ProviderCredential` **Validation rules**: - `consent_status` is the primary stored truth for consent progression. - `verification_status` is the primary stored truth for current provider verification outcome. - `status` and `health_status` may remain persisted and updated by existing projections, but targeted operator surfaces must treat them as secondary diagnostics only. - `is_default` remains the routing anchor for tenant-facing provider summaries where a single connection must be chosen. ### ProviderCredential **Purpose**: Encrypted credential storage associated with a provider connection. **Key fields**: - `provider_connection_id` - encrypted credential payload fields **Relationships**: - `ProviderCredential` belongs to `ProviderConnection` **Validation rules**: - This spec does not change credential persistence, mutation rules, or encryption handling. - Credential presence may continue to influence diagnostic projections, but it is not itself rendered as a leading readiness label on the targeted surfaces. ### OperationRun / Verification Report **Purpose**: Stored verification evidence used by tenant verification and provider check surfaces. **Key fields**: - `tenant_id` - `type` with `provider.connection.check` - `status` - `outcome` - `context` - stored verification report payload derived from the run **Relationships**: - `OperationRun` belongs to `Tenant` when tenant-bound **Validation rules**: - The latest stored verification report remains the deep-dive verification surface for tenant detail. - This spec does not change run lifecycle, queueing, or verification report persistence. ## Existing Domain State Families ### TenantLifecycle **Values**: - `draft` - `onboarding` - `active` - `archived` **Rule**: - Lifecycle answers whether the tenant is in the normal lifecycle. It does not answer provider consent, provider verification, or provider readiness. ### ProviderConsentStatus **Values**: - `unknown` - `required` - `granted` - `failed` - `revoked` **Rule**: - Consent answers whether the permission or consent step has been completed. It does not prove provider verification health. ### ProviderVerificationStatus **Values**: - `unknown` - `pending` - `healthy` - `degraded` - `blocked` - `error` **Rule**: - Verification is the primary current provider-state axis for whether a connection has been checked and what that check currently proves. ### Legacy Diagnostic Projections **Known provider projection values in current surfaces**: - `status`: commonly `connected`, `needs_consent`, `error`, `disabled` - `health_status`: commonly `ok`, `degraded`, `down`, `unknown` **Rule**: - These values remain diagnostics or projections. They must not compete with consent and verification as primary operator truth on targeted surfaces. ## Derived Surface Contracts ### Tenant List Row Truth (derived, non-persisted) **Purpose**: Minimal row-level truth for `/admin/tenants`. | Field | Type | Required | Description | |------|------|----------|-------------| | `tenantId` | integer | yes | Tenant identifier | | `tenantLabel` | string | yes | Tenant name | | `lifecycle` | string | yes | Lifecycle label derived from `TenantLifecycle` | | `providerSignal` | object nullable | no | Optional bounded provider summary derived from current truth; may be absent in this slice | | `legacyAppStatusVisible` | boolean | yes | Must be `false` on default-visible tenant list surfaces | | `primaryInspectUrl` | string | yes | Canonical tenant detail destination | **Validation rules**: - `providerSignal` may be omitted when a truthful single-row summary cannot be stated without inventing a readiness model. - `legacyAppStatusVisible` must be `false` for the default tenant list configuration. ### Tenant Detail Provider Summary (derived, non-persisted) **Purpose**: Compact provider-state summary rendered inside the tenant detail `Provider` section. | Field | Type | Required | Description | |------|------|----------|-------------| | `connectionPresence` | enum | yes | `missing`, `configured`, or `default_configured` | | `ctaUrl` | string | yes | Canonical provider-connections destination | | `displayName` | string nullable | no | Default or chosen connection display name | | `provider` | string nullable | no | Provider label | | `consentStatus` | string nullable | no | Current consent state from the chosen connection | | `verificationStatus` | string nullable | no | Current verification state from the chosen connection | | `lastCheckedAt` | string nullable | no | Stored last-check timestamp | | `lastErrorReasonCode` | string nullable | no | Diagnostic reason code when present | | `legacyStatus` | string nullable | no | Legacy diagnostic projection | | `legacyHealthStatus` | string nullable | no | Legacy health projection | **Validation rules**: - Consent and verification are the leading fields in this summary. - Legacy status and health may remain available only as diagnostics. - When no default Microsoft provider connection exists, the summary must explicitly say action is needed and must not invent a healthy or ready label. ### Provider Connection Surface Truth (derived, non-persisted) **Purpose**: Shared truth hierarchy for provider connection list, view, and edit surfaces. | Field | Type | Required | Description | |------|------|----------|-------------| | `connectionId` | integer | yes | Provider connection identifier | | `tenantLabel` | string nullable | no | Tenant label when rendered on tenantless canonical surfaces | | `displayName` | string | yes | Connection display name | | `provider` | string | yes | Provider key or label | | `connectionType` | string | yes | Platform or dedicated | | `isDefault` | boolean | yes | Default designation | | `consentStatus` | string | yes | Leading consent truth | | `verificationStatus` | string | yes | Leading verification truth | | `legacyStatus` | string nullable | no | Secondary diagnostic projection | | `legacyHealthStatus` | string nullable | no | Secondary diagnostic projection | | `migrationReviewRequired` | boolean | yes | Secondary diagnostic flag | | `lastCheckedAt` | string nullable | no | Last stored check timestamp | | `lastErrorReasonCode` | string nullable | no | Stored diagnostic reason code | **Validation rules**: - List, view, and edit surfaces must display `consentStatus` and `verificationStatus` before any legacy projection fields. - Legacy fields may remain filterable or visible only when clearly marked and positioned as diagnostics. - `connectionType` and `isDefault` remain supporting facts, not substitutes for readiness. ## Surface Truth Hierarchy Rules 1. Tenant lifecycle is the primary tenant-state axis. 2. Provider consent and provider verification are the primary provider-state axes. 3. RBAC remains a separate tenant-management domain. 4. Legacy tenant app status, provider status, and provider health are diagnostic-only on targeted surfaces. 5. No derived surface contract in this feature may collapse `active`, `connected`, or `consented` into a synthetic `ready` value. ## No New Persistence - No new table is introduced. - No new enum or reason family is introduced. - No new persisted readiness summary is introduced. - Existing persisted legacy fields remain for compatibility, but their surface role is reduced.