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

1.7 KiB

Data Model — Remove Legacy Tenant Graph Options

Summary

This feature is a behavioral refactor only. It changes how Graph credentials/options are sourced (provider connection only) and adds a CI guardrail. No schema changes are included.

Entities (existing)

Tenant (app/Models/Tenant.php)

  • Relevant fields (legacy): app_client_id, app_client_secret, tenant_id, external_id
  • Relevant method (deprecated): graphOptions(): array
  • Planned behavior: graphOptions() remains but throws (kill-switch) to prevent legacy use.

ProviderConnection (app/Models/ProviderConnection.php)

  • Used by: ProviderConnectionResolver::resolveDefault($tenant, 'microsoft')
  • Key fields: tenant_id, provider, is_default, status, entra_tenant_id

ProviderCredential (app/Models/ProviderCredential.php)

  • Used by: CredentialManager::getClientCredentials($connection) via ProviderGateway::graphOptions()
  • Expected payload: ['client_id' => string, 'client_secret' => string]

Relationships (existing)

  • Tenant::providerConnections() → hasMany ProviderConnection
  • ProviderConnection::credential() → hasOne/hasMany ProviderCredential (via relationship method in model)

Validation / Constraints

  • Provider connection resolution must fail deterministically when:
    • No default connection exists for tenant/provider
    • Multiple defaults exist
    • Connection is disabled / needs consent
    • Missing entra_tenant_id
    • Missing/invalid credential payload

(These rules are currently enforced by ProviderConnectionResolver.)

State Transitions

  • None added by this feature.

Out of Scope

  • Dropping / migrating tenant credential columns.
  • Changing provider resolution semantics.