TenantAtlas/specs/179-provider-truth-cleanup/spec.md
ahmido dc46c4fa58 feat: complete provider truth cleanup (#207)
## Summary
- implement Spec 179 to make tenant lifecycle, provider consent, and provider verification the primary truth axes on the targeted Filament surfaces
- demote legacy tenant app status and legacy provider status and health to diagnostic-only roles, add centralized badge mappings for provider consent and verification, and keep provider connections excluded from global search
- add the full Spec 179 artifact set under `specs/179-provider-truth-cleanup/` plus focused Pest coverage for tenant truth cleanup, provider truth cleanup, RBAC, discovery safety, and badge semantics
- fix the numeric out-of-scope tenant route regression so inaccessible `/admin/tenants/{id}` paths return `404 Not Found` instead of `500`

## Testing
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantLifecycleStatusDomainSeparationTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantTruthCleanupSpec179Test.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/ProviderConnectionsDbOnlyTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections/ProviderConnectionTruthCleanupSpec179Test.php`
- `vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections/RequiredFiltersTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Tenants/TenantProviderConnectionsCtaTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Rbac/TenantResourceAuthorizationTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections/ProviderConnectionListAuthorizationTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections/ProviderConnectionAuthorizationTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Rbac/AdminGlobalSearchContextSafetyTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantGlobalSearchLifecycleScopeTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantScopingTest.php`
- `vendor/bin/sail artisan test --compact tests/Unit/Badges/TenantBadgesTest.php`
- `vendor/bin/sail artisan test --compact tests/Unit/Badges/ProviderConnectionBadgesTest.php`

## Manual validation
- integrated-browser smoke on `/admin/tenants`, tenant detail, `/admin/provider-connections`, provider detail, and provider edit
- verified out-of-scope tenant and provider URLs return `404 Not Found` with the current session

## Notes
- branch: `179-provider-truth-cleanup`
- commit: `e54c6632`
- target: `dev`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #207
2026-04-05 00:48:31 +00:00

227 lines
31 KiB
Markdown

# Feature Specification: Spec 179 - Provider Readiness Source-of-Truth Cleanup
**Feature Branch**: `179-provider-truth-cleanup`
**Created**: 2026-04-04
**Status**: Draft
**Input**: User description: "Spec 179 — Provider Readiness Source-of-Truth Cleanup"
## Spec Scope Fields *(mandatory)*
- **Scope**: workspace + tenant
- **Primary Routes**:
- `/admin/tenants`
- `/admin/tenants/{tenant}`
- `/admin/provider-connections`
- `/admin/provider-connections/{record}`
- `/admin/provider-connections/{record}/edit`
- **Data Ownership**:
- Tenant-owned truth already exists in tenant lifecycle state, provider connection consent state, provider connection verification state, provider connection metadata, and stored verification outputs tied to a tenant.
- Workspace-owned context remains the selected workspace and its membership filter, which determines which tenants and provider connections are visible in `/admin`.
- This feature introduces no new persisted truth. It only removes misleading prominence from existing legacy status fields and reorders presentation of already-stored truth.
- **RBAC**:
- Workspace membership remains required for the tenant and provider resources in `/admin`.
- Tenant membership remains the isolation boundary for tenant and provider records.
- Existing provider view and provider manage capability checks remain authoritative for view and mutation surfaces.
- No authorization broadening is allowed; non-members remain deny-as-not-found and members without capability remain forbidden for protected actions.
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
| Surface | Surface Type | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Tenant list | CRUD / List-first Resource | Full-row click into tenant view | required | Header `Add tenant`; non-inspect row actions stay in `More` | Existing archive, restore, and force-delete actions remain secondary in `More`; unchanged by this spec | `/admin/tenants` | `/admin/tenants/{tenant}` | Active workspace, tenant name, environment, and existing tenant scope | Tenants / Tenant | Tenant lifecycle, plus an optional bounded provider signal only when it is derived from current provider truth | none |
| Tenant view | Detail / view-first resource | Tenant view page itself | forbidden | Header `ActionGroup` remains the secondary action container | Existing destructive lifecycle actions stay grouped and confirmed; unchanged by this spec | `/admin/tenants` | `/admin/tenants/{tenant}` | Tenant identity, workspace context, and existing tenant-scoped widgets | Tenant | Tenant lifecycle first; provider consent and provider verification separate from lifecycle and RBAC | none |
| Provider connections list | CRUD / List-first Resource | Full-row click into provider connection view | required | Header `New connection`; operational and management actions stay in row `More` | Existing set-default, enable or disable, and credential mutations stay secondary and confirmed where already required | `/admin/provider-connections` | `/admin/provider-connections/{record}` | Active workspace plus tenant filter or tenant query context, tenant name, provider name, and default marker | Provider Connections / Provider Connection | Consent state and verification state, not legacy connection status or health | Tenantless canonical route with tenant-aware filtering |
| Provider connection view | Detail / view-first resource | Provider connection view page itself | forbidden | Header actions and grouped header mutations remain the secondary action area | Existing credential and connection-state mutations remain grouped, confirmed, and capability-gated | `/admin/provider-connections` | `/admin/provider-connections/{record}` | Tenant identity, provider identity, connection type, and default marker | Provider Connection | Consent state and verification state as the leading diagnosis | none |
| Provider connection edit | Edit form | Provider connection edit page itself | forbidden | Save and cancel remain the form actions; grouped header actions remain secondary | Existing credential and connection-state mutations remain grouped, confirmed, and capability-gated | `/admin/provider-connections` | `/admin/provider-connections/{record}/edit` | Tenant identity, provider identity, connection type, and default marker | Provider Connection | Current consent and verification context before any configuration mutation; legacy fields are not allowed to dominate the form | none |
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
| Surface | Primary Persona | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|
| Tenant list | Workspace or tenant operator | List | Which tenants are in a normal lifecycle state, and is there any trustworthy provider concern I should notice without assuming readiness? | Tenant name, lifecycle, environment, and either a bounded provider signal from current provider truth or no provider signal at all | Legacy app-status projections and frozen provider surrogates are not default-visible | lifecycle, optional provider consent or verification summary | none on the list itself; existing row actions remain unchanged | Open tenant, Add tenant | Existing archive, restore, and force-delete actions remain secondary and are not reinterpreted as provider readiness signals |
| Tenant view | Tenant operator | Detail | What is this tenant's lifecycle, and what does the current provider base actually prove? | Lifecycle summary, provider consent, provider verification, verification summary, and RBAC shown as a separate domain when present | Legacy app status, historical provider projections, and raw verification internals stay diagnostic-only if retained at all | lifecycle, provider consent, provider verification, RBAC status as a separate domain | Existing verification and tenant management actions remain unchanged | Provider connections, Verify configuration, Edit, Grant admin consent, Open in Entra | Existing archive, restore, and force-delete actions remain grouped, confirmed, and clearly separate from provider truth |
| Provider connections list | Tenant operator or tenant admin | List | Which connections are consented, which are verified, and which still need attention? | Tenant, provider, default marker, consent state, verification state, and connection type when useful | Legacy connection status, legacy health, migration-review metadata, and raw error text stay secondary | consent, verification, default designation | Existing provider operations and management actions remain unchanged | Open provider connection, New connection | Set as default, enable or disable connection, dedicated-credential actions, and provider-run actions remain secondary and capability-gated |
| Provider connection view | Tenant operator or tenant admin | Detail | Is this connection only configured, or has it actually been checked and verified? | Consent state, verification state, provider identity, default designation, and next-step links | Legacy status and health, raw identifiers, and low-level technical fields stay secondary | consent, verification, connection type | Existing connection-check and provider-management actions remain unchanged | Check connection, Grant admin consent, Edit, View last check run | Enable dedicated override, rotate or delete dedicated credential, revert to platform, enable or disable connection, and set default remain grouped, confirmed, and authorized |
| Provider connection edit | Tenant admin | Edit | What can I safely change, and what do the current consent and verification states tell me before I mutate this connection? | Editable configuration, consent state, verification state, save and cancel, and the same tenant scope cues as the view page | Legacy status and health, raw technical metadata, and historical projections stay diagnostic-only if retained | consent, verification, connection type | Existing provider configuration mutation scope remains unchanged | Save changes, Cancel, Check connection, View last check run | Existing dedicated-credential and enable or disable actions remain grouped, confirmed, and authorized |
## Proportionality Review *(mandatory when structural complexity is introduced)*
- **New source of truth?**: No.
- **New persisted entity/table/artifact?**: No.
- **New abstraction?**: No.
- **New enum/state/reason family?**: No.
- **New cross-domain UI framework/taxonomy?**: No.
- **Current operator problem**: A tenant or provider connection can currently look active, connected, or healthy on a leading surface even when the provider basis is unclear, stale, blocked, or semantically contradicted by newer status fields.
- **Existing structure is insufficient because**: The current model already has clearer truth axes for lifecycle, consent, and verification, but primary tenant and provider surfaces still elevate legacy fields such as tenant app status, provider connection status, and provider health as if they were current truth.
- **Narrowest correct implementation**: Rework only the existing tenant and provider presentation layers, default-visible fields, filters, and badge mappings so that lifecycle, consent, and verification become the primary operator-facing truth without inventing a new readiness model.
- **Ownership cost**: The repo takes on focused UI cleanup, badge or filter adjustments, and regression coverage for truth ordering, but no new persistence, taxonomy, or cross-cutting semantic framework.
- **Alternative intentionally rejected**: A new tenant readiness enum, a full readiness assessment, or a new persisted summary artifact is rejected for this slice because the immediate risk is conflicting surface truth, not the absence of another status model.
- **Release truth**: Current-release truth cleanup that also prepares the codebase for later readiness and gating work.
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Read truthful tenant surfaces (Priority: P1)
As an operator, I can open the tenant list and tenant view and understand tenant lifecycle separately from provider consent and provider verification, so an `active` tenant does not silently read as provider-ready.
**Why this priority**: The biggest current risk is false confidence on the main tenant-facing surfaces.
**Independent Test**: Can be fully tested by seeding tenants whose lifecycle, legacy app status, consent, and verification states disagree, then rendering the tenant list and tenant view to verify that lifecycle remains separate and legacy app status no longer drives the leading operator truth.
**Acceptance Scenarios**:
1. **Given** a tenant is `active` and its provider verification is `unknown`, **When** the operator opens the tenant list or tenant view, **Then** the surface shows lifecycle without implying the tenant is provider-ready.
2. **Given** a tenant is onboarding, consent is granted, and verification is blocked, **When** the operator opens the tenant view, **Then** onboarding remains the tenant lifecycle truth and the provider issue remains separately visible.
3. **Given** a tenant still has a populated legacy app-status value, **When** the operator opens a primary tenant surface, **Then** that legacy field is not presented as the current leading status.
---
### User Story 2 - Diagnose provider connections from current axes (Priority: P1)
As an operator, I can use provider connection list, view, and edit surfaces to see consent and verification as the leading provider state axes, even when legacy connection status fields still contain data.
**Why this priority**: Provider connection pages are the canonical diagnostic surfaces for this domain and must stop showing parallel state systems as peers.
**Independent Test**: Can be fully tested by seeding provider connections whose legacy `status` and `health_status` disagree with `consent_status` and `verification_status`, then verifying that list, view, and edit surfaces elevate consent and verification while demoting or hiding the legacy fields.
**Acceptance Scenarios**:
1. **Given** a provider connection has consent granted, verification degraded, legacy status `connected`, and legacy health `ok`, **When** the operator opens the provider connections list or detail pages, **Then** consent and degraded verification are the leading truths and the legacy fields do not appear at equal prominence.
2. **Given** a provider connection is configured but never verified, **When** the operator opens its view or edit page, **Then** the page makes clear that the connection is not yet proven healthy.
3. **Given** a provider connection is disabled, **When** the operator opens the list or detail page, **Then** connection-state actions remain secondary and do not override consent or verification semantics.
---
### User Story 3 - Avoid false readiness language across surfaces (Priority: P2)
As an operator, I can move between tenant and provider surfaces without seeing `active`, `connected`, `consented`, or similar labels treated as if they automatically mean `ready`.
**Why this priority**: This slice is a truth cleanup, not a final readiness model, so it must reduce semantic overreach before any follow-up readiness work starts.
**Independent Test**: Can be fully tested by rendering primary tenant and provider surfaces for records that look favorable in one status family but unfavorable in another and verifying that no default-visible wording or badge composition collapses them into one readiness conclusion.
**Acceptance Scenarios**:
1. **Given** a tenant is active and the default provider connection is consented but verification is error or blocked, **When** the operator inspects the tenant and provider surfaces, **Then** neither surface implies that the tenant is operationally ready.
2. **Given** the tenant list does not have enough trustworthy provider truth to summarize one tenant safely, **When** the list renders, **Then** it omits that provider readiness signal instead of inventing a legacy or optimistic substitute.
3. **Given** RBAC status is also shown on the tenant view, **When** the page renders, **Then** RBAC remains a separate domain and does not masquerade as provider readiness.
### Edge Cases
- Legacy app status or legacy provider status fields still contain optimistic values that contradict current verification truth.
- A tenant has no provider connection or has multiple provider connections, so the tenant list cannot safely compress provider truth into one scan-time signal.
- Consent is granted but verification has never been run, so the system must distinguish configured or consented from verified.
- Verification is stale, blocked, degraded, or error while the tenant lifecycle remains active.
- RBAC health is present on the tenant view at the same time as provider truth and must remain visibly separate.
- A non-member or cross-workspace actor attempts to reach tenant or provider surfaces and must continue to see deny-as-not-found behavior without new hints.
## Requirements *(mandatory)*
**Constitution alignment (required):** This feature introduces no new Microsoft Graph contract, no new long-running workflow, and no new write path. Existing verification and provider-run actions remain as they are today. The work is limited to truth cleanup on existing operator-facing surfaces.
**Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001):** This feature is intentionally narrow. It adds no new persistence, abstraction, state family, presenter framework, or readiness taxonomy. It cleans up leading surface truth using already-existing lifecycle, consent, verification, and verification-report data.
**Constitution alignment (OPS-UX):** No new `OperationRun` type, execution surface, or feedback path is introduced. Existing verification and provider-operation flows keep their current run semantics.
**Constitution alignment (RBAC-UX):** The work stays in the admin plane at `/admin` on existing tenant and provider resources. Non-members and out-of-scope users remain deny-as-not-found. In-scope members without capability remain forbidden for protected actions. Server-side authorization remains the source of truth. Tenant global search stays safe because the tenant resource already has view and edit pages; provider connections remain non-globally-searchable for this slice. Existing destructive-like actions keep their current confirmation requirements.
**Constitution alignment (OPS-EX-AUTH-001):** Not applicable. No auth handshake behavior is changed.
**Constitution alignment (BADGE-001):** Status badge semantics remain centralized. This feature updates leading badge usage so tenant lifecycle, provider consent, and provider verification are the primary operator-facing status hierarchy on targeted surfaces. If provider consent or provider verification require new mappings, they MUST be added through `BadgeCatalog` and `BadgeRenderer` inside the existing badge system rather than through page-local labels or a synthetic readiness framework.
**Constitution alignment (UI-FIL-001):** The feature reuses existing Filament tables, infolists, widgets, form sections, action groups, and centralized badge helpers. No local replacement markup or page-local status language is needed. No exception is expected.
**Constitution alignment (UI-NAMING-001):** Operator-facing copy must keep `Lifecycle`, `Consent`, and `Verification` as distinct questions. This slice must not introduce `Ready` as a new leading label. If any legacy field remains visible, it must be named as diagnostic or legacy rather than as primary status.
**Constitution alignment (UI-CONST-001 / UI-SURF-001 / UI-HARD-001 / UI-EX-001 / UI-REVIEW-001):** Each affected surface keeps one primary inspect or open model, and the surface tables above define collection routes, detail routes, action placement, scope signals, and the default-visible truth. The targeted surfaces must stop treating `app_status`, provider `status`, or provider `health_status` as peer signals to lifecycle, consent, or verification.
**Constitution alignment (OPSURF-001):** Default-visible content must stay operator-first. Tenant surfaces show lifecycle and, when warranted, provider truth. Provider surfaces show consent and verification first. Diagnostics such as legacy fields, raw identifiers, or historical projections must remain secondary. Existing mutation scope and safe-execution patterns remain unchanged.
**Constitution alignment (UI-SEM-001 / LAYER-001 / TEST-TRUTH-001):** Direct mapping from existing lifecycle, consent, and verification truth is sufficient once legacy prominence is removed. This feature must not add a new readiness interpreter or semantic wrapper. Tests must protect business truth by proving the absence of false readiness and the demotion of conflicting legacy signals.
**Constitution alignment (Filament Action Surfaces):** The Action Surface Contract remains satisfied. Affected surfaces keep one primary inspect model, redundant `View` actions remain absent, empty action groups are not introduced, and destructive actions keep their current placement and confirmation rules. UI-FIL-001 is satisfied with no approved exception.
**Constitution alignment (UX-001 — Layout & Information Architecture):** No new screen type is introduced. Tenant view continues to use a view page with widgets and infolist content. Provider connection view continues to use a view page. Provider connection edit remains a section-based edit form. List pages keep search, sort, and filters, but the default-visible status dimensions and core filters must align to leading truth rather than legacy projections.
### Functional Requirements
- **FR-179-001 (Lifecycle remains its own truth)**: Targeted tenant surfaces MUST present tenant lifecycle as a distinct domain and MUST NOT use lifecycle labels to imply provider readiness.
- **FR-179-002 (Tenant app status removed from leading truth)**: Targeted tenant surfaces MUST NOT present `app_status` as a default-visible primary badge, summary field, or equivalent current-status signal.
- **FR-179-003 (Tenant list uses only trustworthy provider signal)**: The tenant list MUST either show a bounded provider signal derived from current provider consent and verification truth or omit provider status for that row. It MUST NOT rely on `app_status` or another legacy projection as the scan-time provider indicator.
- **FR-179-004 (Tenant detail separates provider axes)**: When tenant detail surfaces provider state, they MUST show provider consent and provider verification as separate axes.
- **FR-179-005 (No false readiness on tenant detail)**: Tenant detail MUST NOT allow `active`, `connected`, `configured`, or `consented` signals to read as equivalent to verified, healthy, or ready when verification is unknown, blocked, degraded, error, or absent.
- **FR-179-006 (RBAC remains separate)**: If RBAC status appears on tenant detail, it MUST remain visibly separate from provider consent and provider verification and MUST NOT substitute for provider readiness.
- **FR-179-007 (Provider list leading axes)**: Provider connection list MUST use consent state and verification state as the primary default-visible connection-state axes.
- **FR-179-008 (Legacy provider status demoted)**: Provider connection list, view, and edit surfaces MUST NOT present legacy `status` or `health_status` as equal-priority peer truth next to consent and verification.
- **FR-179-009 (Legacy diagnostics handling)**: If legacy provider `status` or `health_status` remains visible anywhere on the targeted provider surfaces, it MUST be clearly labeled and positioned as secondary diagnostics, historical projection, or technical metadata.
- **FR-179-010 (Provider detail distinguishes configured from proven)**: Provider connection view and edit surfaces MUST make it clear whether a connection is merely configured or consented versus operationally checked and verified.
- **FR-179-011 (Badge truth alignment)**: Centralized badge and presentation mappings used by the targeted tenant and provider surfaces MUST elevate lifecycle, consent, and verification over tenant app status, provider connection status, and provider connection health.
- **FR-179-012 (No conflicting equal-prominence status mosaic)**: Targeted tenant and provider surfaces MUST NOT render multiple semantically overlapping status badges or fields at the same visual level when only one is authoritative for that operator question.
- **FR-179-013 (List filters follow leading truth)**: Default-visible list filters and core list columns on affected surfaces MUST align with the leading truth hierarchy. Legacy status filters may remain only if they are explicitly secondary and do not present themselves as the primary way to judge current provider readiness.
- **FR-179-014 (No new persisted truth)**: The feature MUST ship without a new table, without a new persisted readiness artifact, and without a new status family.
- **FR-179-015 (Authorization boundaries unchanged)**: Workspace scoping, tenant isolation, and capability checks on all touched surfaces MUST remain unchanged. This cleanup MUST NOT widen visibility or bypass existing server-side authorization.
- **FR-179-016 (Global search and discovery stay safe)**: Tenant search behavior may remain in place because the tenant resource already has view and edit pages. Provider connections remain non-globally-searchable in this slice, and no touched surface may introduce new search-based status leakage.
- **FR-179-017 (Regression coverage is mandatory)**: Regression coverage MUST verify tenant legacy-status suppression, provider primary-status promotion, contradictory multi-status demotion, badge truth alignment, and global-search safety. Final implementation validation MUST verify the absence of schema requirements and new persisted truth.
## UI Action Matrix *(mandatory when Filament is changed)*
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Tenant list | `app/Filament/Resources/TenantResource.php` and `app/Filament/Resources/TenantResource/Pages/ListTenants.php` | `Add tenant` | `recordUrl()` opens the tenant view; one row-primary action slot is preserved | Primary overflow includes `Resume onboarding` or `View related onboarding`; `More` contains `Open`, `Edit`, `Grant admin consent`, `Open in Entra`, `Sync`, `Verify configuration`, `Restore`, `Force delete`, `Archive`, and RBAC helper actions | `Sync selected` stays grouped under `More` | `Add tenant` | n/a | n/a | existing only | Action Surface Contract remains satisfied. This spec changes status truth, not the action inventory. |
| Tenant view | `app/Filament/Resources/TenantResource/Pages/ViewTenant.php` | `Provider connections`, `Edit`, `View related onboarding`, `Grant admin consent`, `Open in Entra`, `Verify configuration` inside the existing header `ActionGroup` | direct page | n/a | none | n/a | Existing grouped lifecycle and verification actions remain | n/a | existing only | No new header mutations are introduced. The change is in default-visible status semantics only. |
| Provider connections list | `app/Filament/Resources/ProviderConnectionResource.php` and `app/Filament/Resources/ProviderConnectionResource/Pages/ListProviderConnections.php` | `New connection` | `recordUrl()` opens the provider connection view | `More` contains `Edit`, `Check connection`, `Inventory sync`, `Compliance snapshot`, `Set as default`, `Enable dedicated override`, `Rotate dedicated credential`, `Delete dedicated credential`, `Revert to platform`, `Enable connection`, and `Disable connection` | none | `New connection` | n/a | n/a | existing only | Canonical tenantless route stays `/admin/provider-connections`; this spec changes which status fields are treated as primary truth. |
| Provider connection view | `app/Filament/Resources/ProviderConnectionResource/Pages/ViewProviderConnection.php` | `Grant admin consent`, `Edit`, plus grouped connection-management actions | direct page | n/a | none | n/a | `Check connection`, `View last check run`, and existing grouped dedicated-credential and connection-state actions remain | n/a | existing only | Existing confirmed and audited mutations remain unchanged. This spec only changes which state is read as primary. |
| Provider connection edit | `app/Filament/Resources/ProviderConnectionResource/Pages/EditProviderConnection.php` | Existing grouped connection-management actions remain | direct page | n/a | none | n/a | Existing grouped connection-management actions remain | Default save and cancel actions remain | existing only | UX-001 remains satisfied. The edit surface must show consent and verification as current context without letting legacy fields dominate. |
### Key Entities *(include if feature involves data)*
- **Tenant lifecycle**: The tenant's own lifecycle truth, such as onboarding, active, archived, or equivalent states that describe whether the tenant is in the normal lifecycle.
- **Provider consent state**: The stored state that answers whether the provider permission or consent step has been completed.
- **Provider verification state**: The stored state that answers whether the provider connection has been checked and what that check currently proves.
- **Legacy tenant app status**: An older projected tenant-level field that may still exist in storage but is no longer allowed to act as leading operator truth on targeted surfaces.
- **Legacy provider connection status and health**: Older connection-level projections that may remain in storage for internal compatibility but are no longer allowed to compete with consent and verification on targeted surfaces.
- **Bounded provider signal**: A tightly-scoped tenant-level summary derived from current provider truth that may appear on the tenant list only when it can be expressed without inventing a broader readiness model.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-179-001**: In regression coverage, 100% of targeted tenant surfaces stop showing legacy tenant app status as a default-visible primary operator truth.
- **SC-179-002**: In regression coverage, 100% of targeted provider surfaces show consent state and verification state before any legacy provider status or health field.
- **SC-179-003**: In seeded scenarios where a tenant is active but provider verification is unknown, blocked, degraded, or error, 100% of targeted surfaces avoid implying that the tenant is provider-ready by default.
- **SC-179-004**: In seeded scenarios where legacy fields contradict current consent or verification truth, 100% of targeted surfaces render the current truth hierarchy consistently.
- **SC-179-005**: The feature ships without a required schema migration, a new persisted readiness artifact, or a new cross-surface status family.
## Assumptions
- Existing consent and verification fields are sufficiently trustworthy to become the leading provider truth for this cleanup slice.
- Existing verification reports and provider next-step guidance remain the correct supporting diagnostics for provider truth.
- Existing RBAC status surfaces remain valid as their own domain and do not need redesign in this spec beyond clearer separation from provider truth.
- The tenant list may omit a provider signal for some tenants if no bounded, trustworthy summary can be expressed without inventing a readiness model.
## Non-Goals
- Introducing a full tenant readiness assessment
- Adding a new readiness enum or score
- Building cross-dashboard or needs-attention propagation for every provider problem
- Adding operation pre-flight gating or blocking rules beyond the current behavior
- Introducing verification freshness or scheduled re-verification lifecycle rules
- Removing legacy database columns or internal compatibility paths in this slice
## Dependencies
- Existing tenant lifecycle model and tenant operator surfaces
- Existing provider connection model, consent state, verification state, and verification-report semantics
- Existing centralized badge and presentation mappings used on tenant and provider surfaces
- Existing workspace and tenant scoping, capability enforcement, and deny-as-not-found boundaries
- Existing tenant and provider Filament resources, pages, and regression tests covering truth and authorization behavior
## Definition of Done
- Tenant app status no longer appears as leading operator truth on the targeted tenant surfaces.
- Provider legacy status and health no longer compete with consent and verification on the targeted provider surfaces.
- Tenant lifecycle, provider consent, provider verification, and RBAC remain visibly separate where they coexist.
- No targeted tenant or provider surface allows `active`, `connected`, or `consented` to read as equivalent to ready.
- Badge and presentation usage reflects the cleaned truth hierarchy without inventing a new readiness model.
- The change requires no new persistence structure and is covered by targeted regression tests.