TenantAtlas/specs/088-remove-tenant-graphoptions-legacy/plan.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

106 lines
4.4 KiB
Markdown

# Implementation Plan: Remove Legacy Tenant Graph Options
**Branch**: `088-remove-tenant-graphoptions-legacy` | **Date**: 2026-02-11 | **Spec**: [spec.md](spec.md)
**Input**: Feature specification in [spec.md](spec.md)
## Summary
Hard cut removal of the deprecated tenant-based Graph options accessor. All Microsoft Graph configuration must be derived exclusively from a resolved `ProviderConnection` via `ProviderConnectionResolver::resolveDefault()` and `ProviderGateway::graphOptions()`. Add a CI guardrail scanning `app/` for `$tenant->graphOptions()` / `Tenant::graphOptions()` and implement a kill-switch by making `Tenant::graphOptions()` throw.
## Technical Context
**Language/Version**: PHP 8.4.15 (Laravel 12)
**Primary Dependencies**: Filament v5, Livewire v4, Pest v4
**Storage**: PostgreSQL (Sail locally)
**Testing**: Pest via `vendor/bin/sail artisan test --compact`
**Target Platform**: Containerized Linux deployment (Sail local, Dokploy staging/prod)
**Project Type**: Laravel web application (monolith)
**Performance Goals**: N/A (internal refactor + CI guard)
**Constraints**:
- No fallback to tenant-stored credentials.
- Guardrail scans `app/` only (do not fail due to `tests/`).
- No new Graph endpoints; Graph calls remain routed through `GraphClientInterface`.
**Scale/Scope**: Repo-wide refactor of call sites in `app/Services/**`.
## Constitution Check
*GATE: Must pass before implementation. Re-check after design decisions.*
- Inventory-first / snapshots: **N/A** (no inventory/snapshot semantics change)
- Read/write separation: **PASS** (no new write surfaces; existing flows only refactored)
- Single contract path to Graph: **PASS** (Graph calls remain through `GraphClientInterface`; only options sourcing changes)
- Deterministic capabilities: **N/A** (no capability mapping changes)
- RBAC-UX / workspace isolation / tenant isolation: **N/A** (no routing or authorization semantic changes)
- Run observability: **N/A** (no new operations or run tracking changes)
- Data minimization / safe logging: **PASS** (no secrets introduced; provider credentials remain in credential store)
- Filament UI Action Surface Contract: **N/A** (no UI resources/pages are added or modified)
## Project Structure
### Documentation (this feature)
```text
specs/088-remove-tenant-graphoptions-legacy/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
└── tasks.md # created by /speckit.tasks (later)
```
### Source Code (repository root)
```text
app/
├── Models/
│ └── Tenant.php
├── Services/
│ ├── Providers/
│ │ ├── ProviderConnectionResolver.php
│ │ └── ProviderGateway.php
│ └── ... (multiple Graph-enabled services)
tests/
└── Feature/
└── Guards/
```
**Structure Decision**: Laravel monolith; refactor stays within existing services/models.
## Implementation Plan
### Phase 0 — Outline & Research (completed)
- Documented decisions and call sites in [research.md](research.md).
### Phase 1 — Design & Implementation (planned)
1. **Kill-switch the deprecated accessor**
- Update `Tenant::graphOptions()` in `app/Models/Tenant.php` to throw a clear exception explaining that provider connections are required.
2. **Refactor all `app/` call sites off `$tenant->graphOptions()`**
- For each call site, resolve the default Microsoft provider connection via `ProviderConnectionResolver::resolveDefault($tenant, 'microsoft')`.
- If resolution fails, fail fast with a clear, actionable error (include the effective reason code/message).
- Replace option building with `ProviderGateway::graphOptions($connection, $overrides)`.
- Update `app/Services/Intune/TenantConfigService.php` (currently returns `$tenant->graphOptions()`), so it no longer provides a tenant-based path.
3. **Add CI guardrail (Pest)**
- Add a new guard test under `tests/Feature/Guards/` that scans `app/` for forbidden patterns:
- `\$tenant->graphOptions(`
- `Tenant::graphOptions(`
- Ensure failure message explains how to fix (use provider connection resolution).
4. **Verification**
- Run the guard test and the most relevant subsets described in [quickstart.md](quickstart.md).
- Run `vendor/bin/sail bin pint --dirty`.
### Phase 2 — Tasks (next step)
- Completed: `tasks.md` has been generated and Phase 1 is broken into smaller, reviewable steps.
## Complexity Tracking
No constitution violations are required for this feature.