Implement Dart IntegrationCredentialVault client
epic-external-system-integration-configuration-foundation-task-009 — Create the Dart client that communicates with the Supabase Vault wrapper functions via RPC calls. Implement storeCredentials(), retrieveCredentials(), rotateCredentials(), and deleteCredentials() methods. The client must never log or expose plaintext values, handle vault RPC errors gracefully, and return typed CredentialReference objects containing only the vault secret ID.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Handles integration between different epics or system components. Requires coordination across multiple development streams.
Implementation Notes
Place in lib/infrastructure/integrations/credential_vault/. Create a CredentialMap class that wraps Map
The vault secret ID returned by the store RPC is what gets persisted in organization_integrations.credential_vault_id. Never persist the full credentials in the Supabase table. Register via Riverpod as Provider
Must only be called from background sync service, never from UI layer.'
Testing Requirements
Write unit tests using flutter_test with mocked Supabase RPC client. Test: (1) storeCredentials calls correct RPC function with serialized credentials and returns CredentialReference; (2) storeCredentials throws ArgumentError for empty credentials map; (3) retrieveCredentials calls correct RPC with vault secret ID; (4) rotateCredentials deletes old and stores new secret, returns new CredentialReference; (5) deleteCredentials calls delete RPC; (6) any RPC error (PostgrestException) is wrapped in CredentialVaultException with non-sensitive message; (7) CredentialReference.toString() does not contain any credential value; (8) CredentialMap.toString() returns '[REDACTED]'. Security-test: assert no credential value appears in any thrown exception message.
Supabase Vault API has limited documentation for Dart/Flutter clients; wrapping it correctly for credential rotation and secret reference management may require significant trial and error, delaying the vault component and blocking all downstream credential-dependent work.
Mitigation & Contingency
Mitigation: Spike the Vault integration in the first sprint using a minimal proof-of-concept (store, retrieve, rotate one secret). Document the API surface before building the full vault client. Identify any missing Dart SDK bindings early.
Contingency: If Supabase Vault is too complex, fall back to Supabase's encrypted column approach (pgcrypto) for credential storage as a temporary measure, with a planned migration path to Vault once the API is understood.
Incorrect RLS policy configuration on organization_integrations could allow org admins of one organization to read or modify another organization's integration credentials, creating a serious data breach and compliance violation.
Mitigation & Contingency
Mitigation: Write integration tests that explicitly attempt cross-org data access using different JWT tokens and assert 0 rows returned. Include RLS policy review in PR checklist. Use Supabase's local development stack for policy validation before deployment.
Contingency: If a breach is discovered post-deployment, immediately revoke all integration credentials, rotate vault secrets, notify affected organizations, and apply emergency RLS patches.
JSONB columns for field_mappings and sync_schedule lack database-level schema enforcement; AI-generated or malformed JSON could silently corrupt integration configurations, causing export failures that are hard to diagnose.
Mitigation & Contingency
Mitigation: Define TypeScript/Dart model classes with strict deserialization and validation. Add database check constraints or triggers that validate JSONB structure at write time. Version the JSONB schema to enable forward-compatible migrations.
Contingency: Build a repair script that scans organization_integrations for invalid JSONB and resets corrupted records to a safe default state, alerting the admin of the affected organization.