## Summary - introduce the Provider Connection Filament resource (list/create/edit) with DB-only controls, grouped action dropdowns, and badge-driven status/health rendering - wire up the provider foundation stack (migrations, models, policies, providers, operations, badges, and audits) plus the required spec docs/checklists - standardize Inventory Sync notifications so the job no longer writes its own DB rows; terminal notifications now flow exclusively through OperationRunCompleted while the start surface still shows the queued toast ## Testing - ./vendor/bin/sail php ./vendor/bin/pint --dirty - ./vendor/bin/sail artisan test tests/Unit/Badges/ProviderConnectionBadgesTest.php - ./vendor/bin/sail artisan test tests/Feature/ProviderConnections tests/Feature/Filament/ProviderConnectionsDbOnlyTest.php - ./vendor/bin/sail artisan test tests/Feature/Inventory/RunInventorySyncJobTest.php tests/Feature/Inventory/InventorySyncStartSurfaceTest.php Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box> Reviewed-on: #73
3.5 KiB
3.5 KiB
Data Model: Provider Foundation v1
Branch: 061-provider-foundation
Date: 2026-01-24
Spec: /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/061-provider-foundation/spec.md
Entities
ProviderConnection
Represents a tenant-scoped connection to an external provider (v1: Microsoft).
Identity
- Scoped to a Suite Tenant (
tenant_id). - Canonical target scope identifier for Microsoft:
entra_tenant_id(GUID). - Uniqueness:
(tenant_id, provider, entra_tenant_id)must be unique.
Fields (suggested)
id(UUID)tenant_id(FK → tenants)provider(string; v1:microsoft)entra_tenant_id(string; GUID)display_name(string)is_default(boolean; exactly one default per(tenant_id, provider))status(string enum):connected | needs_consent | error | disabledhealth_status(string enum):ok | degraded | downscopes_granted(json/jsonb; optional; stores observed granted scopes/permissions metadata)last_health_check_at(timestamp nullable)last_error_reason_code(string nullable; stable reason code)last_error_message(string nullable; sanitized short message)metadata(json/jsonb nullable; optional non-sensitive provider metadata)- timestamps
Indexes (suggested)
- Unique index:
(tenant_id, provider, entra_tenant_id) - Partial unique index:
(tenant_id, provider)whereis_default = true - Indexes for filtering:
(tenant_id, provider, status),(tenant_id, provider, health_status)
State transitions (v1)
status: typicallyneeds_consent/error→connectedafter successful health check;disabledis an explicit admin action.health_status:okon successful check;degraded/downbased on categorized failures (throttling vs outage vs auth).
ProviderCredential
Represents securely stored credentials for exactly one provider connection.
Identity
- 1:1 with ProviderConnection (
provider_connection_idunique).
Fields (suggested)
id(UUID)provider_connection_id(FK → provider_connections, unique)type(string; v1:client_secret)payload(encrypted JSON/array)- required keys (v1):
client_id,client_secret - optional key:
tenant_id(should match ProviderConnectionentra_tenant_idif stored)
- required keys (v1):
- timestamps
Constraints (suggested)
payloadmust be encrypted at rest.payloadmust never be exposed via UI/API serialization.- If
payload.tenant_idis stored, validate it matchesprovider_connections.entra_tenant_id.
DefaultProviderConnection (concept)
Not a separate table by default; represented by provider_connections.is_default = true.
Rules:
- Multiple Microsoft connections per Suite Tenant are allowed.
- Exactly one default connection exists per
(tenant_id, provider)and is used when starting operations without an explicit connection selection.
OperationRun (existing)
Provider operations are tracked as operation_runs with provider context stored in the context JSON.
Provider context fields (suggested)
provider:microsoftprovider_connection_id: UUIDtarget_scope:{ "entra_tenant_id": "<guid>" }module:health_check | inventory | complianceselection: optional selectors/filters for the operation (DB-only)idempotency: fingerprint/hash inputs used for dedupe
Concurrency rules (from spec clarifications)
- Same operation type + same scope: dedupe → return the active run.
- Different operation type while any run is active for the same scope: block as “scope busy” and link to the active run.