TenantAtlas/specs/188-provider-connection-state-cleanup/tasks.md
ahmido 1655cc481e Spec 188: canonical provider connection state cleanup (#219)
## Summary
- migrate provider connections to the canonical three-dimension state model: lifecycle via `is_enabled`, consent via `consent_status`, and verification via `verification_status`
- remove legacy provider status and health badge paths, update admin and system directory surfaces, and align onboarding, consent callback, verification, resolver, and mutation flows with the new model
- add the Spec 188 artifact set, schema migrations, guard coverage, and expanded provider-state tests across admin, system, onboarding, verification, and rendering paths

## Verification
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Auth/SystemPanelAuthTest.php tests/Feature/Filament/TenantGlobalSearchLifecycleScopeTest.php tests/Feature/ProviderConnections/ProviderConnectionEnableDisableTest.php tests/Feature/ProviderConnections/ProviderConnectionTruthCleanupSpec179Test.php`
- integrated browser smoke: validated admin provider list/detail/edit, tenant provider summary, system directory tenant detail, provider-connection search exclusion, and cleaned up the temporary smoke record afterward

## Filament / implementation notes
- Livewire v4.0+ compliance: preserved; this change targets Filament v5 on Livewire v4 and does not introduce older APIs
- Provider registration location: unchanged; Laravel 11+ panel providers remain registered in `bootstrap/providers.php`
- Globally searchable resources: `ProviderConnectionResource` remains intentionally excluded from global search; tenant global search remains enabled and continues to resolve to view pages
- Destructive actions: no new destructive action surface was introduced without confirmation or authorization; existing capability checks continue to gate provider mutations
- Asset strategy: unchanged; no new Filament assets were added, so deploy behavior for `php artisan filament:assets` remains unchanged
- Testing plan covered: system auth, tenant global search, provider lifecycle enable/disable behavior, and provider truth cleanup cutover behavior

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #219
2026-04-10 11:22:56 +00:00

208 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Tasks: Canonical Provider Connection State Cleanup
**Input**: Design documents from `/specs/188-provider-connection-state-cleanup/`
**Prerequisites**: `plan.md`, `spec.md`, `research.md`, `data-model.md`, `contracts/provider-connection-state-cleanup.openapi.yaml`, `quickstart.md`
**Tests**: Required. Write or update Pest coverage before each behavior change and keep Sail-first verification focused.
**Organization**: Tasks are grouped by user story so each story can be implemented and validated independently.
## Phase 1: Setup (Shared Regression Scaffolding)
**Purpose**: Create the focused regression entry points and residual guardrails for the hard-cut cleanup before changing runtime or schema behavior.
- [X] T001 [P] Create the residual legacy-state Pest guard in `apps/platform/tests/Feature/Guards/NoLegacyProviderConnectionStateFallbackTest.php`
- [X] T002 [P] Add Spec 188 canonical-state regression entry points in `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionEnableDisableTest.php`, `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionHealthCheckJobTest.php`, `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionTruthCleanupSpec179Test.php`, and `apps/platform/tests/Feature/System/Spec114/DirectoryTenantsTest.php`
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Add the narrow lifecycle truth and shared fixture support that every story depends on.
**⚠️ CRITICAL**: No user story work should begin until this phase is complete.
- [X] T003 Implement the lifecycle add-and-backfill migration in `apps/platform/database/migrations/2026_04_09_000001_add_is_enabled_to_provider_connections.php`
- [X] T004 [P] Add canonical lifecycle support to the core model and shared test fixtures in `apps/platform/app/Models/ProviderConnection.php`, `apps/platform/database/factories/ProviderConnectionFactory.php`, and `apps/platform/tests/Pest.php`
- [X] T005 [P] Preserve provider and system authorization semantics during the cutover in `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionListAuthorizationTest.php`, `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionAuthorizationTest.php`, `apps/platform/tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php`, `apps/platform/tests/Feature/Rbac/ProviderConnectionsCreateUiEnforcementTest.php`, `apps/platform/tests/Feature/Rbac/EditProviderConnectionUiEnforcementTest.php`, and `apps/platform/tests/Feature/System/Spec114/DirectoryTenantsTest.php`
**Checkpoint**: The schema, model, fixtures, and access invariants are ready; canonical surface and runtime work can now proceed.
---
## Phase 3: User Story 1 - Read one canonical provider state language (Priority: P1)
**Goal**: Implement the operator-surface portion of the canonical reader cutover so admin, tenant, and system surfaces show only lifecycle, consent, and verification as the authoritative provider-state language.
**Independent Test**: Seed provider connections with canonical contradiction scenarios such as disabled with granted consent, enabled with missing consent, and enabled with blocked verification, then render provider, tenant, and system surfaces to verify that operators see lifecycle, consent, and verification only.
### Tests for User Story 1
- [X] T006 [P] [US1] Add admin provider list, detail, edit, and DB-only canonical-state assertions in `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionTruthCleanupSpec179Test.php`, `apps/platform/tests/Feature/Filament/ProviderConnectionsDbOnlyTest.php`, and `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionViewsDbOnlyRenderingSpec081Test.php`
- [X] T007 [P] [US1] Add tenant and system canonical provider summary, provider-search exclusion, tenant-search safety, and DB-only assertions in `apps/platform/tests/Feature/Tenants/TenantProviderConnectionsCtaTest.php`, `apps/platform/tests/Feature/System/Spec114/DirectoryTenantsTest.php`, `apps/platform/tests/Feature/Filament/TenantGlobalSearchLifecycleScopeTest.php`, and `apps/platform/tests/Feature/Filament/TenantScopingTest.php`
### Implementation for User Story 1
- [X] T008 [US1] Replace legacy provider list, detail, and edit presentation with lifecycle, consent, and verification in `apps/platform/app/Filament/Resources/ProviderConnectionResource.php`
- [X] T009 [US1] Rework the tenant provider summary helper and shared infolist entry to emit canonical state only in `apps/platform/app/Filament/Resources/TenantResource.php` and `apps/platform/resources/views/filament/infolists/entries/provider-connection-state.blade.php`
- [X] T010 [US1] Rework system directory health rollups and provider rows to read canonical state in `apps/platform/app/Filament/System/Pages/Directory/Tenants.php`, `apps/platform/app/Filament/System/Pages/Directory/ViewTenant.php`, and `apps/platform/resources/views/filament/system/pages/directory/view-tenant.blade.php`, counting only default Microsoft connections in list rollups while keeping detail rows canonical
**Checkpoint**: Provider, tenant, and system surfaces now speak one canonical provider-state language without visible legacy status or health semantics. The full reader-cutover milestone is complete only after `T014` lands.
---
## Phase 4: User Story 2 - Trust runtime decisions again (Priority: P1)
**Goal**: Move runtime readers, writers, and transport contracts to lifecycle, consent, and verification so action visibility, onboarding, verification, and health checks stop depending on removed legacy fields.
**Independent Test**: Execute create, onboarding, consent, verification, health-check, and mutation flows while asserting that all reads, writes, and queries depend only on lifecycle, consent, and verification truth.
### Tests for User Story 2
- [X] T011 [P] [US2] Add canonical reader-gate regressions for lifecycle, consent, and verification in `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionEnableDisableTest.php`, `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionHealthCheckStartSurfaceTest.php`, and `apps/platform/tests/Feature/EntraAdminRoles/ScanEntraAdminRolesJobTest.php`
- [X] T012 [P] [US2] Add canonical create and writer-flow regressions for resource create, onboarding, consent bootstrap, verification start, and health checks in `apps/platform/tests/Feature/ProviderConnections/MvpProviderScopeTest.php`, `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionHealthCheckJobTest.php`, `apps/platform/tests/Feature/Verification/ProviderConnectionHealthCheckWritesReportTest.php`, `apps/platform/tests/Feature/Onboarding/OnboardingProviderConnectionTest.php`, `apps/platform/tests/Feature/Onboarding/OnboardingProviderConnectionPlatformDefaultTest.php`, and `apps/platform/tests/Feature/ManagedTenantOnboardingWizardTest.php`
- [X] T013 [P] [US2] Add audit and lifecycle-mutation regressions in `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionEnableDisableTest.php`, `apps/platform/tests/Feature/Audit/ProviderConnectionConsentAuditTest.php`, `apps/platform/tests/Feature/Audit/ProviderConnectionConsentRevocationAuditTest.php`, and `apps/platform/tests/Feature/Audit/ProviderConnectionVerificationAuditTest.php`
### Implementation for User Story 2
- [X] T014 [US2] Move resolver and background-job reads to `is_enabled`, `consent_status`, and `verification_status` in `apps/platform/app/Services/Providers/ProviderConnectionResolver.php` and `apps/platform/app/Jobs/ScanEntraAdminRolesJob.php`
- [X] T015 [US2] Remove legacy transport and projection outputs from provider health-check contracts in `apps/platform/app/Services/Providers/Contracts/HealthResult.php`, `apps/platform/app/Services/Providers/MicrosoftProviderHealthCheck.php`, and `apps/platform/app/Services/Providers/ProviderConnectionStateProjector.php`
- [X] T016 [US2] Update verification and health-check writers to persist canonical state only in `apps/platform/app/Jobs/ProviderConnectionHealthCheckJob.php` and `apps/platform/app/Services/Verification/StartVerification.php`
- [X] T017 [US2] Update onboarding, consent callback, and provider-mutation writers to persist lifecycle, consent, verification, and diagnostics only in `apps/platform/app/Http/Controllers/AdminConsentCallbackController.php`, `apps/platform/app/Http/Controllers/TenantOnboardingController.php`, `apps/platform/app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php`, and `apps/platform/app/Services/Providers/ProviderConnectionMutationService.php`
- [X] T018 [US2] Keep enable or disable actions confirmation-gated and switch lifecycle audit metadata off legacy status in `apps/platform/app/Filament/Resources/ProviderConnectionResource.php`
**Checkpoint**: Runtime decisions, verification flows, onboarding, and health checks all use canonical lifecycle, consent, and verification truth.
---
## Phase 5: User Story 3 - Finish the hard cut without residual tail (Priority: P2)
**Goal**: Remove the remaining compatibility surface so schema, badges, helpers, factories, and tests cannot recreate legacy provider state.
**Independent Test**: Apply the final schema, run focused regression coverage, and prove that no active badge, contract, filter, helper, factory, query, or test depends on legacy provider status or health.
### Tests for User Story 3
- [X] T019 [P] [US3] Add contradiction scenarios for disabled plus granted consent and disabled plus `verification_status = healthy` in `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionEnableDisableTest.php`, `apps/platform/tests/Feature/ProviderConnections/ProviderConnectionTruthCleanupSpec179Test.php`, and `apps/platform/tests/Feature/System/Spec114/DirectoryTenantsTest.php`
- [X] T020 [P] [US3] Add legacy-badge and residual-fallback regressions in `apps/platform/tests/Feature/Guards/NoLegacyProviderConnectionStateFallbackTest.php`, `apps/platform/tests/Unit/Badges/BooleanEnabledBadgesTest.php`, `apps/platform/tests/Unit/Badges/ProviderConnectionBadgesTest.php`, `apps/platform/tests/Unit/Providers/ProviderConnectionBadgeMappingTest.php`, and `apps/platform/tests/Unit/Badges/BadgeCatalogTest.php`
### Implementation for User Story 3
- [X] T021 [US3] Retire legacy provider badge domains and route lifecycle through shared badge mappings in `apps/platform/app/Support/Badges/BadgeDomain.php`, `apps/platform/app/Support/Badges/BadgeCatalog.php`, `apps/platform/app/Support/Badges/Domains/ProviderConnectionStatusBadge.php`, and `apps/platform/app/Support/Badges/Domains/ProviderConnectionHealthBadge.php`
- [X] T022 [US3] Remove remaining legacy provider-state helper keys, labels, and comments from `apps/platform/app/Models/ProviderConnection.php`, `apps/platform/app/Filament/Resources/ProviderConnectionResource.php`, `apps/platform/app/Filament/Resources/TenantResource.php`, `apps/platform/resources/views/filament/infolists/entries/provider-connection-state.blade.php`, and `apps/platform/resources/views/filament/system/pages/directory/view-tenant.blade.php`
- [X] T023 [US3] Remove any surviving legacy provider-state references from shared fixtures and targeted runtime paths in `apps/platform/database/factories/ProviderConnectionFactory.php`, `apps/platform/tests/Pest.php`, and files matched by `apps/platform/tests/Feature/Guards/NoLegacyProviderConnectionStateFallbackTest.php`
- [X] T024 [US3] Drop `status`, `health_status`, and their indexes from `provider_connections` in `apps/platform/database/migrations/2026_04_09_000002_drop_legacy_provider_state_columns_from_provider_connections.php`
**Checkpoint**: The hard cut is complete; no active runtime, UI, badge, helper, factory, or schema path can recreate legacy provider state.
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Format, verify, and confirm the hard cut with the focused Sail pack and manual smoke checks.
- [X] T025 Run `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` for touched files under `apps/platform/app/`, `apps/platform/database/`, `apps/platform/resources/views/`, and `apps/platform/tests/`
- [X] T026 Run the focused Spec 188 Sail verification pack from `specs/188-provider-connection-state-cleanup/quickstart.md`
- [X] T027 Execute the manual smoke checklist and residual legacy-state sweep from `specs/188-provider-connection-state-cleanup/quickstart.md` against `/admin/provider-connections`, `/admin/tenants/{tenant}`, `/system/directory/tenants`, and `/system/directory/tenants/{tenant}`
- [X] T028 Validate that the final diff contains no dual-read or dual-write shim, no new provider-state abstraction, and no undeclared persistence beyond `is_enabled` by reviewing `apps/platform/app/Services/Providers/`, `apps/platform/app/Support/Badges/`, `apps/platform/database/migrations/`, and `specs/188-provider-connection-state-cleanup/plan.md`
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)**: No dependencies; start immediately.
- **Foundational (Phase 2)**: Depends on Setup completion; blocks all user story work.
- **User Story 1 (Phase 3)**: Depends on Foundational completion.
- **User Story 2 (Phase 4)**: Depends on Foundational completion.
- **User Story 3 (Phase 5)**: Depends on User Story 1 and User Story 2 completion because it removes the remaining compatibility surface and drops the schema.
- **Polish (Phase 6)**: Depends on all desired user stories being complete.
### User Story Dependencies
- **US1**: Covers the operator-surface portion of the reader cutover after Phase 2 and is not a standalone implementation-complete slice until `T014` lands.
- **US2**: Independent as a review slice after Phase 2, but writer tasks `T015`-`T018` must follow the canonical reader cutover before the feature is release-ready.
- **US3**: Depends on the finished surface and runtime cutover from US1 and US2.
### Cross-Story Implementation Sequencing
- `T008`-`T010` and `T014` together form the canonical reader cutover across shared helpers, operator surfaces, and runtime gates.
- `T015`-`T018` complete the canonical writer and transport cutover and should land only after the reader cutover above is in place.
- `T021`-`T024` are final hard-cut cleanup tasks and depend on both P1 stories being functionally complete.
### Within Each User Story
- Write or update the story tests first and confirm they fail for the intended reason.
- Move shared readers before story-specific writers when both are touched by the same cutover.
- Finish story-specific assertions after the implementation lands.
- Keep authorization, confirmation, and audit regressions green before advancing to the next story.
### Parallel Opportunities
- `T001` and `T002` can run in parallel.
- `T004` and `T005` can run in parallel after `T003` lands.
- Phase 3 and Phase 4 regression authoring can run in parallel after Phase 2 completes, but implementation sequencing still follows reader cutover before writer cutover.
- `T019` and `T020` can run in parallel after both Phase 3 and Phase 4 are complete.
---
## Parallel Example: User Story 1
```bash
# Lock the admin and read-only surface expectations before changing provider-state UI:
Task: T006 Add admin provider list, detail, edit, and DB-only canonical-state assertions in apps/platform/tests/Feature/ProviderConnections/ProviderConnectionTruthCleanupSpec179Test.php, apps/platform/tests/Feature/Filament/ProviderConnectionsDbOnlyTest.php, and apps/platform/tests/Feature/ProviderConnections/ProviderConnectionViewsDbOnlyRenderingSpec081Test.php
Task: T007 Add tenant and system canonical provider summary, provider-search exclusion, tenant-search safety, and DB-only assertions in apps/platform/tests/Feature/Tenants/TenantProviderConnectionsCtaTest.php, apps/platform/tests/Feature/System/Spec114/DirectoryTenantsTest.php, apps/platform/tests/Feature/Filament/TenantGlobalSearchLifecycleScopeTest.php, and apps/platform/tests/Feature/Filament/TenantScopingTest.php
```
## Parallel Example: User Story 2
```bash
# Lock reader, writer, and audit behavior before changing runtime provider-state logic:
Task: T011 Add canonical reader-gate regressions in apps/platform/tests/Feature/ProviderConnections/ProviderConnectionEnableDisableTest.php, apps/platform/tests/Feature/ProviderConnections/ProviderConnectionHealthCheckStartSurfaceTest.php, and apps/platform/tests/Feature/EntraAdminRoles/ScanEntraAdminRolesJobTest.php
Task: T012 Add canonical writer-flow regressions in apps/platform/tests/Feature/ProviderConnections/ProviderConnectionHealthCheckJobTest.php, apps/platform/tests/Feature/Verification/ProviderConnectionHealthCheckWritesReportTest.php, apps/platform/tests/Feature/Onboarding/OnboardingProviderConnectionTest.php, apps/platform/tests/Feature/Onboarding/OnboardingProviderConnectionPlatformDefaultTest.php, and apps/platform/tests/Feature/ManagedTenantOnboardingWizardTest.php
Task: T013 Add audit regressions in apps/platform/tests/Feature/Audit/ProviderConnectionConsentAuditTest.php, apps/platform/tests/Feature/Audit/ProviderConnectionConsentRevocationAuditTest.php, and apps/platform/tests/Feature/Audit/ProviderConnectionVerificationAuditTest.php
```
## Parallel Example: User Story 3
```bash
# Lock contradiction coverage and final residual guards before dropping legacy provider columns:
Task: T019 Add contradiction scenarios in apps/platform/tests/Feature/ProviderConnections/ProviderConnectionEnableDisableTest.php, apps/platform/tests/Feature/ProviderConnections/ProviderConnectionTruthCleanupSpec179Test.php, and apps/platform/tests/Feature/System/Spec114/DirectoryTenantsTest.php
Task: T020 Add legacy-badge and residual-fallback regressions in apps/platform/tests/Feature/Guards/NoLegacyProviderConnectionStateFallbackTest.php, apps/platform/tests/Unit/Badges/BooleanEnabledBadgesTest.php, apps/platform/tests/Unit/Badges/ProviderConnectionBadgesTest.php, apps/platform/tests/Unit/Providers/ProviderConnectionBadgeMappingTest.php, and apps/platform/tests/Unit/Badges/BadgeCatalogTest.php
```
---
## Implementation Strategy
### First Demonstrable Milestone (Reader Cutover)
1. Complete Phase 1: Setup.
2. Complete Phase 2: Foundational.
3. Complete Phase 3 plus `T014` from Phase 4 to finish the canonical reader cutover.
4. Validate canonical provider surfaces and runtime reader gates across `/admin`, tenant summaries, and `/system` before moving into runtime writer cutover.
### Incremental Delivery
1. Finish Setup and Foundational work.
2. Deliver the full reader cutover across US1 plus `T014` and validate the canonical provider-state language across surfaces and runtime gates.
3. Deliver the remaining US2 writer work and validate runtime writes and transport cleanup.
4. Deliver US3 and validate the final hard cut and legacy removal.
5. Finish Phase 6 verification and smoke checks.
### Parallel Team Strategy
1. One developer completes Phase 1 and Phase 2.
2. After Phase 2, one developer takes US1 while another takes US2.
3. Rejoin on US3 once surfaces and runtime behavior are both canonical.
4. Finish with shared formatting, focused Sail tests, and the residual sweep.
---
## Notes
- Every task follows the required checklist format: checkbox, task ID, optional parallel marker, required story label for story phases, and exact file paths.
- The task list preserves the plans hard-cut order: lifecycle foundation first, surface and runtime cutover next, then residual cleanup and schema removal last.
- The recommended MVP review slice is US1, but the feature is not shippable until US2 and US3 are complete because the spec forbids compatibility tails.