# Phase 0 Research: Provider Readiness Source-of-Truth Cleanup ## Decision: Remove legacy `app_status` from tenant list primary truth and do not replace it with a new row-level readiness badge in this slice **Rationale**: The current tenant list exposes `app_status` as a default-visible badge and filter even though the feature goal is to stop projecting frozen or semantically stale provider truth from tenant-level legacy fields. A new per-row provider readiness badge would require choosing one provider connection, compressing multi-connection state, and implicitly inventing a readiness model. The narrowest safe move is to let the tenant list remain lifecycle-led and to consciously omit provider readiness from the row when it cannot be stated without semantic overreach. **Alternatives considered**: - Introduce a new tenant readiness badge on the list: rejected because it would create a new semantic layer before the later readiness spec. - Keep `app_status` but toggle it off by default: rejected because the spec explicitly warns that hidden-by-default legacy truth still leaks back into operator interpretation. ## Decision: Reuse the existing tenant Provider section, but repoint it from legacy `status` and `health_status` to consent and verification **Rationale**: Tenant detail already has a dedicated `Provider` section backed by `TenantResource::providerConnectionState()` and the shared Blade entry `provider-connection-state.blade.php`. That section is the narrowest place to present current provider truth without inventing a new widget or presenter. The helper should continue to resolve the default Microsoft provider connection or a missing-connection state, but its leading fields should become `consent_status` and `verification_status`, with legacy status and health demoted to optional diagnostics. **Alternatives considered**: - Build a new tenant provider summary widget: rejected because the current section already exists and the spec does not justify another surface layer. - Remove the Provider section entirely and rely only on the verification widget: rejected because the spec requires clear consent and verification semantics, and the verification widget is a deep-dive report, not the only summary contract. ## Decision: Keep `TenantVerificationReport` as the verification deep-dive and do not turn `TenantOperability` into provider truth **Rationale**: `TenantVerificationReport` already gives tenant detail a DB-only verification deep-dive using the latest `provider.connection.check` run. `TenantOperabilityService` and `verificationReadinessOutcome()` answer whether a verification action may be started in a given lifecycle and capability context, not whether the provider is operationally healthy. The cleanup should continue to use the verification report for stored verification detail and must not promote operability gating into readiness truth. **Alternatives considered**: - Use `TenantOperabilityDecision` as a tenant provider readiness signal: rejected because it mixes lifecycle and permission gating with provider-state truth. - Collapse verification detail into the Provider section and remove the verification widget: rejected because the widget already provides the deeper stored-report surface and no new readiness model is needed. ## Decision: Promote `consent_status` and `verification_status` to the default-visible provider connection list axes **Rationale**: The provider connections list currently defaults to `status` and `health_status`, even though the model already stores `consent_status` and `verification_status` and the resource already has label helpers for them. Surfacing consent and verification in the table is the clearest way to answer whether a connection is consented and whether it has been checked. Legacy `status` and `health_status` may remain available as hidden diagnostics for compatibility, but they should stop being the primary scan path. **Alternatives considered**: - Keep `status` and `health_status` visible because they are shorter to scan: rejected because that preserves the competing-truth problem the spec exists to remove. - Remove legacy columns completely from the list: rejected because the fields may still help diagnostics and internal compatibility during the transition. ## Decision: Split provider connection detail and edit surfaces into current state versus diagnostics instead of one equal-weight Status section **Rationale**: The current provider connection infolist and form both render consent, verification, legacy status, and health at the same hierarchy level in one `Status` section. The cleanup should create a primary current-state section for consent and verification, and a separate diagnostics section for legacy status, health, migration review, and last-error metadata. This keeps the existing resource and existing fields while making the leading truth explicit. **Alternatives considered**: - Keep one Status section and merely reorder the fields: rejected because equal visual grouping would still overstate the legacy fields. - Delete legacy fields from detail and edit immediately: rejected because the spec allows the fields to remain as long as they stop acting like leading truth. ## Decision: Extend the existing badge catalog with narrow provider consent and provider verification mappings while keeping legacy badge domains diagnostic-only **Rationale**: BADGE-001 requires status-like values to render through `BadgeCatalog` and `BadgeRenderer`. `BadgeCatalog` already centralizes legacy `TenantAppStatus`, `ProviderConnectionStatus`, and `ProviderConnectionHealth` mappings, so the narrowest compliant move is to add centralized provider consent and provider verification mappings inside the existing badge system. This keeps lifecycle, consent, verification, and legacy diagnostics on one central semantic path without creating a synthetic `Ready` or `ProviderReadiness` domain. **Alternatives considered**: - Continue using plain labels or local helper output for consent and verification: rejected because BADGE-001 requires centralized status-like badge semantics. - Add a new `ProviderReadiness` badge domain: rejected because it would front-run the later readiness spec and violate proportionality. - Remove legacy badge mappers entirely: rejected because diagnostic surfaces and internal compatibility still reference them. ## Decision: Keep legacy persisted fields and current projection writers intact in this slice **Rationale**: `ProviderConnection` still projects `status` and `health_status` during classification and enable or disable flows, and tenant records still persist `app_status`. The spec explicitly forbids a schema change or aggressive technical removal. The correct scope is presentation cleanup first, not domain-field deletion. **Alternatives considered**: - Drop legacy columns now: rejected because existing jobs, projections, audit metadata, and compatibility paths still write or reference them. - Stop writing the fields immediately as part of this spec: rejected because it would turn a surface-truth cleanup into a broader behavioral change. ## Decision: Update provider list filters to follow the leading truth hierarchy **Rationale**: The current provider list filter set centers `status` and `health_status`. If the table’s leading truth becomes consent and verification, the list’s core filters should follow the same hierarchy. Legacy filters may remain only as explicitly diagnostic filters, not as the primary filter language for current provider state. **Alternatives considered**: - Leave legacy filters untouched while changing only columns: rejected because that keeps the old semantics in the main operator interaction path. - Remove all legacy filters outright: rejected because diagnostic filtering may still be useful while the fields remain persisted. ## Decision: Extend existing truth-separation tests and add one focused provider-surface truth test instead of inventing a large new test harness **Rationale**: The repo already has `TenantLifecycleStatusDomainSeparationTest`, `ProviderConnectionsDbOnlyTest`, `RequiredFiltersTest`, and badge tests. The spec’s main risk is business-truth regression on a few surfaces. Focused feature tests that assert default-visible fields, section hierarchy, and filter names are enough to protect this contract without creating a broad new testing abstraction. **Alternatives considered**: - Rely on manual browser inspection only: rejected because truth regressions on default-visible surfaces are easy to reintroduce. - Create a large generic presenter test framework first: rejected because the cleanup intentionally avoids adding a new presenter layer.