Integration test Supabase mileage adapter with RLS
epic-mileage-reimbursement-entry-infrastructure-task-010 — Write integration tests for SupabaseMileageAdapter that execute against a real Supabase test project. Tests must verify: peer mentor can insert and read own claims, peer mentor cannot read other claims (RLS rejection), coordinator can read all chapter-scoped claims, org_configuration is readable by all roles but writable only by admin.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Create three Supabase clients in the test file: serviceRoleClient (for setup/teardown only), peerMentorClient (authenticated as test peer mentor), coordinatorClient (authenticated as test coordinator). Use supabase_flutter's SupabaseClient directly — do not use SupabaseMileageAdapter for setup to avoid circular dependency. Seed test data in setUpAll or individual setUp methods with unique IDs (use Uuid.v4()) to prevent cross-test contamination. The integration test file should live at integration_test/features/mileage/supabase_mileage_adapter_test.dart.
Add a README note in the test directory explaining how to configure environment variables for the test Supabase project. Ensure CI pipeline has a separate job for integration tests with the required env vars injected as secrets.
Testing Requirements
Integration tests using flutter_test with @Tags(['integration']) annotation. Each test signs in as a specific role using Supabase Auth signInWithPassword() with dedicated test accounts created in the test Supabase project. Use setUpAll() to sign in and tearDownAll() to sign out. Use setUp/tearDown for row-level cleanup via service-role client.
Tests must NOT rely on pre-existing data — all required rows are inserted as part of the test. RLS rejection assertions check for either an empty result set (select) or a caught PostgrestException with code '42501' (write). Document each test with a comment citing the specific RLS policy name it validates.
Supabase Row Level Security policies for mileage_claims may require complex join conditions to distinguish peer mentor (own claims only) from coordinator (chapter-scoped claims) access. If the RLS policy is misconfigured, coordinators could see claims outside their chapter scope or peer mentors could read other users' data, causing a data privacy incident.
Mitigation & Contingency
Mitigation: Write RLS policy SQL as part of this epic with explicit test cases for each role. Use Supabase's built-in policy testing tools and add integration tests that assert cross-user data isolation before merging.
Contingency: If RLS configuration proves too complex to test reliably within the epic, add an application-layer guard in the adapter that filters query results by authenticated user ID as a defence-in-depth measure while the policy is corrected.
Norwegian tax authority reimbursement rounding rules may change or may not be publicly documented in machine-readable form. Using the wrong rounding convention could cause systematic over- or under-payment, leading to compliance issues for the organisation.
Mitigation & Contingency
Mitigation: Source the exact rounding specification from HLF's finance team before implementing MileageCalculationService. Document the rule as a comment in the source code and link to the authoritative reference.
Contingency: If the rule is ambiguous, implement both truncation and half-up rounding behind a configuration flag so the organisation can switch without a code release.
SharedPreferences reads and writes are asynchronous. If the distance prefill service (built in the next epic) calls LocalDistanceCache concurrently with a post-submission write, a race condition could result in the cache returning a stale or partially written value, causing the next form load to show an incorrect default.
Mitigation & Contingency
Mitigation: Wrap all SharedPreferences access in LocalDistanceCache with sequential async operations and document the non-concurrent usage contract in the class API.
Contingency: If race conditions are observed in testing, introduce a simple mutex pattern using a Completer to serialise cache operations.