Write integration tests for RLS and vault policies
epic-external-system-integration-configuration-foundation-task-013 — Write integration tests against a local Supabase instance to verify RLS policy enforcement on organization_integrations. Tests must confirm: org A cannot read org B records, coordinator role has correct permissions, service role bypasses RLS for edge functions, vault functions reject unauthorized callers, and credential rotation invalidates old vault references.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 6 - 158 tasks
Can start after Tier 5 completes
Handles integration between different epics or system components. Requires coordination across multiple development streams.
Implementation Notes
The most reliable approach is a two-layer test strategy: (a) Dart flutter_test for the Dart repository/vault client layer using the local Supabase URL and anon/service keys from `.env.test`; (b) SQL-level policy tests using pgTAP functions run directly via `supabase db test` — pgTAP is ideal for RLS assertions and is natively supported by the Supabase CLI. Use `set_config('request.jwt.claims', ...)` in pgTAP to simulate different role JWTs without needing real Auth users. For Dart-level tests, call `supabase.auth.signInWithPassword()` against the local Auth instance with seeded test users, then perform repository operations. Always use `addTearDown()` in each test to delete rows created during that test, preventing state leakage between tests.
The local Supabase URL and keys are available from `supabase status` output — store them in a `.env.test` file loaded by the test runner. Document the exact `supabase start` command and seed script in a `README_testing.md` in the test directory.
Testing Requirements
Integration tests using flutter_test connecting to a locally running Supabase instance (started with `supabase start`). Test structure: (1) Isolation setup — create two distinct orgs, one coordinator user per org, one peer mentor user, and seed one organization_integrations row per org using the service role; (2) Cross-org isolation — authenticate as org A coordinator, query for org B's integration row by ID, assert empty result set; (3) Coordinator permissions — assert SELECT and UPDATE succeed for own org's rows, assert INSERT of new integration succeeds, assert DELETE is permitted or rejected per policy; (4) Peer mentor read-only — assert all write operations (INSERT, UPDATE, DELETE) return 42501 permission denied; (5) Service role bypass — assert service role client reads all rows regardless of org; (6) Vault authorization — assert vault RPC succeeds with service role, fails with coordinator JWT returning auth error; (7) Rotation invalidation — store a credential, rotate it, attempt retrieval with old reference ID, assert failure. Use `supabase_flutter` in headless mode for Dart integration tests, or write tests as a Node.js/Deno script calling the PostgREST HTTP API directly if flutter_test connectivity is complex in CI.
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.