Architecture
The integration engine is designed to be provider-agnostic. Each provider follows the same lifecycle: connect, sync entities, detect findings, materialize evidence.Provider Registry
integration_providers and integration_provider_display define available providersConnections
integration_connections stores OAuth tokens per tenant per providerSync Engine
Edge Functions pull data and upsert entities/findings
Evidence
rpc_materialize_integration_evidence converts findings to evidenceProvider Registry
OAuth Connect Flow
User initiates connection
The Integration Hub UI redirects the user to the provider’s OAuth consent screen with the appropriate scopes.
Callback processes token
The redirect URI receives the authorization code, exchanges it for tokens, and stores them securely.
Tokens stored in Vault
OAuth tokens are encrypted using Supabase Vault via
rpc_integration_set_secret(). The integration_connections table stores a vault reference, not raw tokens.Sync Edge Functions
trigger-sync (Dispatcher)
Thetrigger-sync function is the orchestrator. It:
- Looks up the connection and provider
- Retrieves decrypted OAuth tokens from Vault
- Dispatches to the appropriate provider-specific function
- Creates an
integration_sync_jobsrecord to track progress
Provider Functions
- sync-azure-ad
- sync-google-workspace
- sync-aws
Syncs from Microsoft Entra ID (Azure AD):
- Users and group memberships
- Conditional Access policies
- MFA registration status
- Security defaults configuration
Entity Upsert Pattern
All providers follow the same upsert pattern for storing synced data:Always use upsert with the unique constraint on
(connection_id, entity_type, external_id) to avoid duplicate records on reconnect or re-sync.Finding Detection
After entity sync, each provider runs finding detection logic:Evidence Materialization
After sync completes, evidence is materialized:integration_evidence_items and links them to relevant controls via control_evidence_links.
Adding a New Provider
For step-by-step instructions on adding a new integration provider, see the internal guide atdocs/adding-new-integration.md in the repository. The high-level steps are:
- Insert a row in
integration_providersandintegration_provider_display - Create a new Edge Function
sync-{provider-slug} - Implement the entity sync and finding detection logic
- Add OAuth configuration (client ID, scopes, redirect URI)
- Register the provider in the
trigger-syncdispatcher - Add finding-to-control mappings for evidence materialization
Job Queue
Sync operations are tracked inintegration_sync_jobs: