Integration test: repository and storage adapter end-to-end
epic-document-attachments-foundation-task-008 — Write integration tests that exercise the complete data layer together: upload a file via SupabaseStorageAdapter, insert the corresponding record via ActivityAttachmentRepository, query active attachments to verify the record appears, generate a signed URL and assert it is non-empty, soft-delete the record and confirm it no longer appears in active queries, and assert that a second org cannot access the first org's records (RLS cross-org isolation). Use flutter_test with a test Supabase project or local emulator.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Create a test helper file `test/helpers/supabase_test_client.dart` that initialises a SupabaseClient from environment variables for integration tests. Use `flutter_dotenv` or direct `Platform.environment` reads so CI can inject secrets via env vars without committing them. Each test should call `setUp` to create fresh UUIDs (`const Uuid().v4()`) for orgId and activityId so tests are fully isolated. For the RLS cross-org test: sign in as org B user (use Supabase Auth `signInWithPassword`), then attempt `getAttachmentsForActivity` with org A's activityId — expect an empty list (RLS filters rows) or a PostgREST 403.
For tearDown: call `storage.from('activity-attachments').remove([storagePath])` and `supabase.from('activity_attachments').delete().eq('id', insertedId)`. Document the local emulator setup in a `TESTING.md` note or in the test file header for future contributors.
Testing Requirements
Integration tests using flutter_test targeting a real Supabase test project or local Supabase emulator (supabase start). Structure: setUp creates two test users (org A, org B) via Supabase Auth, generates unique UUIDs for orgId/activityId, tears down by deleting storage objects and database rows. Test groups: (1) 'upload → insert → query' happy path; (2) 'signed URL generation' verifying non-empty HTTPS URL; (3) 'soft-delete exclusion' confirming deleted record disappears from active queries; (4) 'RLS cross-org isolation' confirming org B cannot access org A records. Tag tests with @Tags(['integration']) and document in README how to run them (SUPABASE_TEST_URL and SUPABASE_TEST_ANON_KEY env vars required).
Supabase RLS policies may not cover all query paths (e.g., service-role key usage in edge functions), potentially exposing attachment metadata or objects from another organisation to an unauthorised actor, breaching GDPR requirements.
Mitigation & Contingency
Mitigation: Add org_id scoping as an explicit WHERE clause at the Dart repository level as a second line of defence. Document which queries use the anon key versus service-role key, and audit all edge function calls that touch the storage bucket.
Contingency: If a bypass is discovered post-deployment, immediately revoke the affected signed URLs, rotate the service-role key, add the missing org_id filter, and deploy a patch. Notify affected organisations per GDPR breach protocol.
Supabase free/pro tier storage quotas may be exceeded earlier than expected if organisations upload large PDFs frequently, causing upload failures with no graceful degradation for users.
Mitigation & Contingency
Mitigation: Configure a 10 MB per-file cap enforced in the upload service (Epic 2), and add a storage usage monitoring alert at 80% of the allocated quota. Document the upgrade path in runbooks.
Contingency: If the quota is hit, temporarily disable new uploads via the org-level feature flag (attachments_enabled) and upgrade the Supabase plan. Communicate clearly to affected coordinators with an estimated restoration time.
The feature documentation specifies a migration order dependency: the activity_attachments table must be created after the activities table and before the Bufdir export join query is updated. Running migrations out of order will cause foreign-key or join failures.
Mitigation & Contingency
Mitigation: Add the migration to the numbered Supabase migration sequence immediately after the activities table migration. Add a CI check that runs migrations in order against a clean schema.
Contingency: If a deployment runs migrations out of order, roll back via the Supabase migration rollback script, reorder, and redeploy. No data loss occurs as attachments do not exist yet at that point.