TenantAtlas/specs/088-remove-tenant-graphoptions-legacy/research.md
ahmido 1acbf8cc54 feat(spec-088): remove tenant graphOptions legacy path (#105)
## Summary
- remove tenant-based Graph options access from runtime service paths and enforce provider-only resolution
- add `MicrosoftGraphOptionsResolver` and `ProviderConfigurationRequiredException` for centralized, actionable provider-config errors
- turn `Tenant::graphOptions()` into a fail-fast kill switch to prevent legacy runtime usage
- add and update tests (including guardrail) to enforce no reintroduction in `app/`
- update Spec 088 artifacts (`spec`, `plan`, `research`, `tasks`, checklist)

## Validation
- `vendor/bin/sail bin pint --dirty`
- `vendor/bin/sail artisan test --compact --filter=NoLegacyTenantGraphOptions`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament`
- `CI=1 vendor/bin/sail artisan test --compact`

## Notes
- Branch includes the guardrail test for legacy callsite detection in `app/`.
- Full suite currently green: 1227 passed, 5 skipped.

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #105
2026-02-12 10:14:44 +00:00

72 lines
3.6 KiB
Markdown

# Research — Remove Legacy Tenant Graph Options
## Goal
Remove usage of the deprecated tenant-based Graph options accessor (`$tenant->graphOptions()` / `Tenant::graphOptions()`) and make provider-based resolution (`ProviderConnectionResolver` + `ProviderGateway`) the single source of truth for Microsoft Graph configuration.
## Decisions
### Decision: Provider connection is canonical for Graph options
- **Chosen**: Resolve `ProviderConnection` via `App\Services\Providers\ProviderConnectionResolver::resolveDefault($tenant, 'microsoft')`, then derive options via `App\Services\Providers\ProviderGateway::graphOptions($connection, $overrides)`.
- **Rationale**: Existing services already follow this path (e.g. onboarding/health); it centralizes credential storage and validation.
- **Alternatives considered**:
- Keep reading tenant columns (`Tenant.app_client_id` / `Tenant.app_client_secret`) as fallback — rejected (explicitly forbidden; introduces mixed credential sources).
### Decision: Kill-switch behavior for `Tenant::graphOptions()`
- **Chosen**: Keep method for now, but make it throw a clear exception (fail-fast).
- **Rationale**: Ensures any missed call site fails deterministically in CI/runtime.
- **Alternatives considered**:
- Delete method outright — rejected (higher risk / more disruptive API break).
### Decision: Guardrail scope and matching rules
- **Chosen**: Add a CI guard test that scans **`app/` only** for these forbidden patterns:
- `\$tenant->graphOptions(`
- `Tenant::graphOptions(`
- **Rationale**: Matches the agreed scope and avoids false positives on unrelated `graphOptions(...)` methods (e.g. `ProviderGateway::graphOptions`).
- **Alternatives considered**:
- Scan for all `->graphOptions(` — rejected (would flag many legitimate methods).
- Scan `tests/` too — rejected (would create noisy failures during refactors).
## Current Code Findings (Call Sites)
### Deprecated tenant accessor call sites (must be removed)
These are current `app/` references to `$tenant->graphOptions()`:
- `app/Services/AssignmentRestoreService.php`
- `app/Services/AssignmentBackupService.php`
- `app/Services/Intune/RestoreRiskChecker.php`
- `app/Services/Intune/TenantPermissionService.php`
- `app/Services/Intune/VersionService.php`
- `app/Services/Intune/FoundationMappingService.php`
- `app/Services/Intune/PolicyCaptureOrchestrator.php`
- `app/Services/Intune/FoundationSnapshotService.php`
- `app/Services/Intune/TenantConfigService.php` (wraps + returns `$tenant->graphOptions()`)
- `app/Services/Intune/ConfigurationPolicyTemplateResolver.php`
- `app/Services/Directory/EntraGroupSyncService.php`
- `app/Services/Directory/RoleDefinitionsSyncService.php`
- `app/Services/Graph/AssignmentFilterResolver.php`
### Canonical provider-based examples to copy
- `app/Services/Intune/RbacOnboardingService.php`
- `app/Services/Intune/RbacHealthService.php`
- `app/Services/Intune/RestoreService.php`
- `app/Services/Intune/PolicySnapshotService.php`
### Source of legacy accessor
- `app/Models/Tenant.php` defines the deprecated `graphOptions()` method.
## Recommended Refactor Pattern
```php
$resolution = $this->providerConnections()->resolveDefault($tenant, 'microsoft');
if (! $resolution->resolved || ! $resolution->connection instanceof ProviderConnection) {
// Fail fast with actionable reason.
}
$connection = $resolution->connection;
$graphOptions = $this->providerGateway()->graphOptions($connection, $overrides);
```
## Notes / Non-goals
- No database schema changes (tenant credential columns stay for now).
- No changes to Graph contract registry (`config/graph_contracts.php`) are required for this feature; this work changes configuration sourcing only.