Write integration tests for foundation layer
epic-bufdir-reporting-export-foundation-task-010 — Write integration tests covering the three repository and storage classes against a Supabase test instance. Test cases must verify: append-only behaviour of audit log (UPDATE and DELETE must fail), org isolation (user from org A cannot read org B records), signed URL expiry, schema version uniqueness constraint, and correct file path construction in the storage adapter.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Create a test/integration/ directory separate from test/unit/. Add a custom test tag by placing a dart_test.yaml at the project root: tags: { integration: { timeout: '2m' } }. Run with: flutter test --tags integration --dart-define=SUPABASE_URL=... --dart-define=SUPABASE_SERVICE_ROLE_KEY=...
The IntegrationTestFixtures helper should use the service_role SupabaseClient to call supabase.auth.admin.createUser() for each test persona with custom app_metadata: { 'org_id': orgAId, 'role': 'coordinator' }. After creation, sign in with email/password to get a real user JWT. For the signed URL expiry test, use http package's http.get() on the URL immediately (expect 200), then await Future.delayed(Duration(seconds: 3)) and call again (expect 400 or non-200). Ensure CI pipeline sets the required environment variables as secrets — document this in the test file header comment.
Avoid test interdependencies: each test must be independently runnable.
Testing Requirements
These tests ARE the deliverable. Structure each test file around one repository/adapter class: export_audit_repository_integration_test.dart, bufdir_schema_config_repository_integration_test.dart, bufdir_export_file_storage_integration_test.dart. Use a shared IntegrationTestFixtures class in test/integration/helpers/integration_fixtures.dart for org/user setup and teardown. Each test file must have a setUpAll that creates test orgs and users via service_role client, and a tearDownAll that removes them.
Individual tests use setUp/tearDown for per-test data. Use expect(..., throwsA(isA
RLS policies for the audit log and schema config tables must correctly handle multi-chapter membership hierarchies (up to 1,400 local chapters for NHF). Incorrect policies could either over-expose data across organisations or prevent legitimate coordinator access, both of which are serious compliance failures.
Mitigation & Contingency
Mitigation: Design RLS policies using the existing org hierarchy resolver pattern. Write integration tests that verify cross-organisation isolation with representative fixture data covering NHF's multi-level hierarchy before merging.
Contingency: If RLS policies prove too complex to express safely in Postgres, implement a Supabase Edge Function as a data access proxy that enforces isolation in application code, with RLS serving as a secondary defence layer.
Bufdir's column schema is expected to evolve as Norse Digital Products negotiates a simplified digital reporting format. If the schema config versioning model is too rigid, applying Bufdir schema updates without a code deployment could fail, forcing emergency releases.
Mitigation & Contingency
Mitigation: Design the schema config table to store the full JSON column mapping as a JSONB field with a version number. Provide an admin API to upsert new versions without any schema migration required.
Contingency: If the versioning model is insufficient for a Bufdir schema change, fall back to a code deployment with the updated default schema, using the database config only for org-specific overrides.