--- description: "Task list for implementing Spec 088" --- # Tasks: Remove Legacy Tenant Graph Options **Input**: Design documents from `/specs/088-remove-tenant-graphoptions-legacy/` **Prerequisites**: plan.md (required), spec.md (required), research.md, data-model.md, contracts/, quickstart.md **Tests**: REQUIRED (Pest) — this feature changes runtime behavior and introduces a CI guardrail. ## Phase 1: Setup (Shared Infrastructure) - [x] T001 Verify test + format tooling paths (composer.json, phpunit.xml, specs/088-remove-tenant-graphoptions-legacy/quickstart.md) - [x] T002 [P] Add a focused test runner note to specs/088-remove-tenant-graphoptions-legacy/quickstart.md (include `--filter=NoLegacyTenantGraphOptions`) --- ## Phase 2: Foundational (Blocking Prerequisites) **⚠️ CRITICAL**: No user story work can begin until this phase is complete. - [x] T003 Create provider-only Graph options resolver in app/Services/Providers/MicrosoftGraphOptionsResolver.php - [x] T004 [P] Create exception for missing/invalid provider config in app/Services/Providers/ProviderConfigurationRequiredException.php - [x] T005 Wire resolver dependencies (ProviderConnectionResolver + ProviderGateway) in app/Providers/AppServiceProvider.php - [x] T006 Add tests for resolver failure/success paths in tests/Feature/Providers/MicrosoftGraphOptionsResolverTest.php - [x] T007 Implement kill-switch: make Tenant::graphOptions() throw in app/Models/Tenant.php - [x] T008 Add test asserting kill-switch behavior in tests/Feature/Models/TenantGraphOptionsKillSwitchTest.php **Checkpoint**: A single reusable provider-only resolver exists, with tests, and the legacy accessor fails fast. --- ## Phase 3: User Story 1 — Safe Refactors via Single Credential Source (Priority: P1) 🎯 MVP **Goal**: All Graph-enabled flows use provider connection-derived configuration only. **Independent Test**: `vendor/bin/sail artisan test --compact --filter=MicrosoftGraphOptionsResolverTest` + run a few refactored service tests (as applicable) and ensure no `app/` references remain. ### Implementation - [x] T009 [P] [US1] Refactor graph options usage in app/Services/AssignmentRestoreService.php (replace `$tenant->graphOptions()` with resolver) - [x] T010 [P] [US1] Refactor graph options usage in app/Services/AssignmentBackupService.php (replace `$tenant->graphOptions()` with resolver) - [x] T011 [P] [US1] Refactor graph options usage in app/Services/Intune/RestoreRiskChecker.php (replace `$tenant->graphOptions()` with resolver) - [x] T012 [P] [US1] Refactor graph options usage in app/Services/Intune/TenantPermissionService.php (derive `client_id` from provider-based options; no tenant fallback) - [x] T013 [P] [US1] Refactor graph options usage in app/Services/Intune/VersionService.php (replace `$tenant->graphOptions()` with resolver) - [x] T014 [P] [US1] Refactor graph options usage in app/Services/Intune/FoundationMappingService.php (replace array merge with provider-based options) - [x] T015 [P] [US1] Refactor graph options usage in app/Services/Intune/PolicyCaptureOrchestrator.php (replace `$tenant->graphOptions()` with resolver) - [x] T016 [P] [US1] Refactor graph options usage in app/Services/Intune/FoundationSnapshotService.php (replace `$tenant->graphOptions()` with resolver) - [x] T017 [P] [US1] Refactor/remove legacy wrapper in app/Services/Intune/TenantConfigService.php (must not return `$tenant->graphOptions()`; use resolver) - [x] T018 [P] [US1] Refactor context building in app/Services/Intune/ConfigurationPolicyTemplateResolver.php (replace `array_merge($tenant->graphOptions(), ...)` with provider-based context) - [x] T019 [P] [US1] Refactor graph options usage in app/Services/Directory/EntraGroupSyncService.php (replace `$tenant->graphOptions()` with resolver) - [x] T020 [P] [US1] Refactor graph options usage in app/Services/Directory/RoleDefinitionsSyncService.php (replace `$tenant->graphOptions()` with resolver) - [x] T021 [P] [US1] Refactor options merge in app/Services/Graph/AssignmentFilterResolver.php (replace `array_merge($options, $tenant->graphOptions())` with provider-based options) ### Verification - [x] T022 [US1] Run focused tests for this story: `vendor/bin/sail artisan test --compact --filter=MicrosoftGraphOptionsResolver` - [x] T023 [US1] Run a repo scan to ensure no `app/` usage remains (confirm via tests/Feature/Guards/NoLegacyTenantGraphOptionsTest.php once added) **Checkpoint**: `app/` contains zero tenant-based graph options usages, and runtime failures are provider-config actionable. --- ## Phase 4: User Story 2 — Prevent Reintroduction of Legacy Paths (Priority: P2) **Goal**: CI fails if `$tenant->graphOptions()` or `Tenant::graphOptions()` appears anywhere under `app/`. **Independent Test**: `vendor/bin/sail artisan test --compact --filter=NoLegacyTenantGraphOptions`. ### Tests (Guardrail) - [x] T024 [P] [US2] Create guard test scanning `app/` in tests/Feature/Guards/NoLegacyTenantGraphOptionsTest.php - [x] T025 [US2] Ensure guard failure message is actionable (points to ProviderConnectionResolver + ProviderGateway) in tests/Feature/Guards/NoLegacyTenantGraphOptionsTest.php ### Verification - [x] T026 [US2] Run guard test: `vendor/bin/sail artisan test --compact --filter=NoLegacyTenantGraphOptions` --- ## Phase 5: Polish & Cross-Cutting Concerns - [x] T027 [P] Run formatter: `vendor/bin/sail bin pint --dirty` (app/**, tests/**) - [x] T028 Run full affected test folders: `vendor/bin/sail artisan test --compact tests/Feature/Guards` - [x] T029 Run a broader suite if needed: `vendor/bin/sail artisan test --compact` --- ## Dependencies & Execution Order ### User Story Dependencies - **US1 (P1)** depends on Phase 2 foundational tasks (resolver + kill-switch). - **US2 (P2)** can be implemented after Phase 2, but should run after US1 refactor so the guard passes. ### Dependency Graph (high level) - Phase 2 (T003–T008) -→ US1 refactors (T009–T021) -→ US1 verification (T022–T023) -→ US2 guardrail (T024–T026) -→ Polish (T027–T029) ## Parallel Execution Examples ### After Phase 2 is complete These refactors are parallelizable because they touch different files: - T009–T016, T018–T021 can run in parallel ([P]). ### US2 guardrail - T024 can be done in parallel with late US1 refactors, but it will only pass once all US1 call sites are removed. ## Implementation Strategy ### MVP (US1) 1. Complete Phase 2 (resolver + kill-switch + tests). 2. Refactor all `app/` call sites (T009–T021). 3. Run focused tests (T022). ### Then lock it in (US2) 1. Add guardrail test (T024–T026). 2. Finish with formatting + regression checks (T027–T029).