high priority low complexity testing pending testing specialist Tier 5

Acceptance Criteria

Test: calling logCreated with a ProxyActivityRecord produces exactly one Supabase INSERT call with event_type='created'
Test: calling logBulkCreated with a list of N ProxyActivityRecords produces exactly one batch INSERT call with N rows, each with event_type='bulk_created'
Test: calling logUpdated produces exactly one INSERT with event_type='updated'
Test: the payload_snapshot in each audit row equals the full JSON serialization of the input ProxyActivityRecord at call time — not a partial copy
Test: RLS — attempting to UPDATE a row in proxy_audit_log returns a permission denied error (mocked or live DB)
Test: RLS — attempting to DELETE a row in proxy_audit_log returns a permission denied error (mocked or live DB)
Test: ProxyAuditLogger never calls .update() or .delete() on the Supabase client — verified via mock assertion that these methods are never invoked
Test: logCreated and logBulkCreated are distinguishable in the audit log via the event_type field value
All tests pass via flutter_test without real network calls

Technical Requirements

frameworks
Flutter
Dart
flutter_test
apis
Supabase PostgREST insert (mocked)
data models
ProxyActivityRecord
ProxyAuditLogEntry
proxy_audit_log
performance requirements
Test suite must complete in under 15 seconds
security requirements
Tests must assert that update() and delete() are never called on the mock Supabase client — this is the programmatic immutability guarantee
No real Supabase credentials in test files

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

The payload_snapshot correctness test is the most nuanced: create a ProxyActivityRecord, call logCreated, then mutate the original record object, and assert the captured snapshot still reflects the original state — this verifies that a deep copy/serialization happens at call time, not a reference. Use mocktail's verify(mockClient.from('proxy_audit_log').insert(captureAny)).called(1) pattern to assert call counts. For the 'never calls update/delete' assertion, use verifyNever(mockClient.from('proxy_audit_log').update(any)) after each logCreated/logBulkCreated call. These tests are complementary to task-009: task-009 tests the repository's behavior, task-010 tests the logger service itself in isolation.

Testing Requirements

Use flutter_test with mocktail to mock the Supabase client. Verify INSERT call payloads by capturing the argument passed to .from('proxy_audit_log').insert(). Assert that .update() and .delete() are never called on the mock. For RLS immutability tests, either mock the Supabase client to return a 403 error on update/delete, or note these as integration tests requiring a real Supabase project with RLS enabled.

Group tests: (1) event_type differentiation, (2) row count per method, (3) payload_snapshot correctness, (4) programmatic immutability (no update/delete calls), (5) RLS immutability.

Component
Proxy Audit Logger
infrastructure low
Epic Risks (3)
high impact medium prob security

Supabase RLS policies for org-scoped proxy access may be difficult to express correctly, especially for coordinators with multi-chapter access. An overly permissive policy could allow cross-org proxy registrations, corrupting Bufdir reporting; an overly restrictive policy could block legitimate coordinators from registering.

Mitigation & Contingency

Mitigation: Write integration tests covering all access boundary cases (same org, cross-org, multi-chapter coordinator) before merging any RLS migration. Use parameterised RLS test helpers already established by the auth feature.

Contingency: If RLS proves insufficient, add a server-side Edge Function validation layer that re-checks org membership before persisting any proxy record, providing defence in depth.

medium impact low prob technical

Adding new tables and foreign key constraints to an existing production Supabase database risks migration failures or locking issues if the database already contains active sessions during deployment.

Mitigation & Contingency

Mitigation: Use additive-only migrations (no DROP or ALTER on existing tables). Test full migration sequence in a staging Supabase project before production deployment. Schedule during low-traffic window.

Contingency: Maintain a rollback migration script. If the migration fails, the feature remains unreachable behind a feature flag while the schema issue is resolved.

high impact medium prob security

Audit log entries must be immutable for compliance, but Supabase RLS by default allows row owners to update their own rows. If audit records are accidentally mutable, dispute resolution and accountability guarantees are invalidated.

Mitigation & Contingency

Mitigation: Configure the proxy_audit_log table with an RLS policy that allows INSERT for coordinators but denies UPDATE and DELETE for all roles including service_role, enforced at the database level.

Contingency: If RLS cannot fully prevent updates, create a database trigger that reverts any UPDATE to the audit table and logs the attempt as a security event.