Implements Spec 081 provider-connection cutover. Highlights: - Adds provider connection resolution + gating for operations/verification. - Adds provider credential observer wiring. - Updates Filament tenant verify flow to block with next-steps when provider connection isn’t ready. - Adds spec docs under specs/081-provider-connection-cutover/ and extensive Spec081 test coverage. Tests: - vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantSetupTest.php - Focused suites for ProviderConnections/Verification ran during implementation (see local logs). Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box> Reviewed-on: #98
4.0 KiB
Data Model: Provider Connection Full Cutover
Feature: specs/081-provider-connection-cutover/spec.md
Date: 2026-02-07
This document describes the entities involved in Spec 081 using the repo’s current schema.
Entities
Tenant
Represents: A managed tenant target (Entra/Intune tenant) within a workspace.
Relevant attributes (existing)
id(PK)workspace_id(FK)nametenant_id(GUID-ish, used as Entra tenant ID)external_id(alternate tenant identifier)- Legacy (deprecated by this spec):
app_client_idapp_client_secret(encrypted)app_certificate_thumbprintapp_notes
Derived helpers (existing)
graphTenantId(): ?stringreturnstenant_idorexternal_id.graphOptions(): array{tenant:?string,client_id:?string,client_secret:?string}(to be deprecated/unused at runtime).
Relationships (existing)
providerConnections(): HasMany→ ProviderConnectionproviderCredentials(): HasManyThrough→ ProviderCredential (via ProviderConnection)operationRuns(): HasMany(implicit via OperationRun.tenant_id)
ProviderConnection
Represents: A workspace-owned integration connection for a tenant + provider (e.g., Microsoft).
Table: provider_connections
Fields (existing)
id(PK)workspace_id(FK, NOT NULL after migration)tenant_id(FK)provider(string, e.g.microsoft)entra_tenant_id(string; expected to match the tenant’s Entra GUID)display_name(string)is_default(bool)status(string; defaultneeds_consent)health_status(string; defaultunknown)scopes_granted(jsonb array)last_health_check_at(timestamp)last_error_reason_code(string, nullable)last_error_message(string, nullable; must be sanitized)metadata(jsonb)created_at,updated_at
Relationships (existing)
tenant(): BelongsToworkspace(): BelongsTocredential(): HasOne→ ProviderCredential
Invariants (existing + required)
- Uniqueness:
unique (tenant_id, provider, entra_tenant_id) - Exactly one default per (tenant_id, provider): enforced by partial unique index
provider_connections_default_unique.
Behaviors (existing)
makeDefault()clears other defaults and sets this record default in a DB transaction.
ProviderCredential
Represents: Encrypted credential material for a provider connection.
Table: provider_credentials
Fields (existing)
id(PK)provider_connection_id(FK, unique)type(string; defaultclient_secret)payload(encrypted array; hidden from serialization)created_at,updated_at
Payload contract (current)
- For
type=client_secret:client_id(string)client_secret(string)- optional
tenant_id(string) validated againstProviderConnection.entra_tenant_id
OperationRun
Represents: A canonical record for a long-running or operationally relevant action.
Table: operation_runs
Key fields (existing)
id(PK)workspace_id(FK)tenant_id(FK nullable in some cases)type(string)status(queued|running|completed)outcome(pending|succeeded|partially_succeeded|failed+ reservedcancelled)context(json)failure_summary(json)summary_counts(json)started_at,completed_at
Context contract (provider-backed runs)
provider(string)provider_connection_id(int)target_scope.entra_tenant_id(string)module(string; from ProviderOperationRegistry definition)
Spec 081 extension (planned)
- Introduce
outcome=blockedand storereason_code+ link-onlynext_stepsin safe context/failure summary.
State Transitions
ProviderConnection default selection
is_default: false -> trueviamakeDefault().- Invariant: only one default per (tenant_id, provider).
Provider-backed operation starts
- Start surface enqueues work and creates/dedupes
OperationRun. - If blocked (missing default connection/credential), an
OperationRunis still created and finalized as blocked.