high priority high complexity testing pending testing specialist Tier 9

Acceptance Criteria

All 7 lifecycle stages have at least one dedicated integration test asserting the correct outcome at that stage
Tests run deterministically against a local Supabase instance started via `supabase start` with a seeded test database
Seed data includes: 1 organisation, 1 coordinator (with FCM token), 1 driver (with FCM token), 1 declaration template
Stage 1 (template rendering): assert rendered PDF/HTML content contains correct driver name and org name
Stage 2 (encryption): assert uploaded storage object is not plaintext-readable without the correct key
Stage 3 (storage upload): assert declaration row exists in DB with status = SENT after upload
Stage 4 (notification dispatch): assert notification_dispatch_log row exists and FCM mock was called with correct driver token
Stage 5 (driver acknowledgement): assert scroll_to_bottom=false returns 422; assert scroll_to_bottom=true returns 200 and status = ACKNOWLEDGED
Stage 6 (audit event): assert declaration_audit_log row exists with action_type = DECLARATION_ACKNOWLEDGED and all required fields
Stage 7 (coordinator alert): assert notifications row exists for coordinator with correct body and deep_link
Test suite completes in under 60 seconds on CI
All tests are isolated: each test run seeds fresh data and tears down after completion
No real FCM calls are made — an HTTP mock intercepts FCM API calls and records payloads for assertion

Technical Requirements

frameworks
flutter_test (Dart integration test runner)
Supabase CLI (supabase start, supabase db reset)
Deno test runner for Edge Function unit coverage
msw or custom HTTP mock server for FCM interception
apis
Supabase REST API (called directly from test client)
Supabase Admin API (for seeding and verification)
Mock FCM endpoint (localhost HTTP server replacing fcm.googleapis.com in test environment)
data models
Declaration
DeclarationAcknowledgement
DeclarationAuditLog
ScheduledNotification
Notification
DriverProfile
CoordinatorProfile
Organisation
performance requirements
Full test suite runtime under 60 seconds
Individual test case timeout: 10 seconds
Supabase local instance must start within 30 seconds on CI
security requirements
Test credentials (JWT tokens, API keys) must be generated from the local Supabase instance only — never real credentials
FCM mock must run on localhost only and be disabled outside of test environment
Test database must be completely isolated from any shared/staging environment

Execution Context

Execution Tier
Tier 9

Tier 9 - 22 tasks

Can start after Tier 8 completes

Implementation Notes

Test infrastructure setup: create a `test/integration/declarations/` directory. Use a `setUpAll` that: (1) calls `supabase.auth.signUp` for driver and coordinator test users; (2) inserts org + template seed data via admin client; (3) starts a local HTTP mock on port 9099 to capture FCM calls. Use a `tearDown` that deletes all rows created in the test by declaration_id to keep tests isolated without full DB reset (faster). For the encryption test, assert the storage object bytes do NOT contain the driver name in plaintext — use a simple string search on the raw bytes.

For the concurrency test, fire two simultaneous Dart `Future.wait([acknowledge(), acknowledge()])` calls and assert exactly one returns 200 and one returns 409. Document the test setup in a `test/integration/README.md` so CI engineers can replicate the environment.

Testing Requirements

This task IS the testing task. Coverage targets: (1) 100% of the 7 lifecycle stages covered by at least one passing test; (2) at least 3 negative-path tests (scroll validation rejection, duplicate acknowledgement 409, missing FCM token skip); (3) at least 1 concurrency test — two simultaneous acknowledgement requests for the same declaration assert only one succeeds (idempotency/lock). Tests are written as Dart integration tests using the flutter_test framework invoking the Supabase REST/RPC API directly (no Flutter widget layer). Edge Function logic is additionally covered by Deno unit tests for each function in isolation.

Epic Risks (4)
high impact medium prob security

Org-scoped encryption key management is complex. If keys are not correctly isolated per organization, a breach in one org's key could expose another org's declarations. Additionally, key rotation is not specified but may be needed for compliance, and the current implementation may not support it.

Mitigation & Contingency

Mitigation: Use Supabase Vault or a dedicated secrets management approach for org-scoped key storage. Define the key derivation strategy (per-org master key) in a security design document reviewed before implementation begins. Include key isolation tests in the test suite.

Contingency: If a full per-org key management system cannot be safely implemented within the sprint, fall back to a single platform-level encryption key with strict RLS isolation as a temporary measure, flagging the key rotation gap as a security debt item with a defined resolution milestone.

medium impact medium prob integration

Push notification delivery to drivers depends on FCM token availability and device connectivity. If a driver has not granted notification permissions or has an expired FCM token, the declaration delivery notification will silently fail, leaving the coordinator unaware and the declaration unacknowledged.

Mitigation & Contingency

Mitigation: Implement delivery status tracking in declaration-notification-service. Fall back to in-app notification and SMS (if configured) when push delivery fails. Expose delivery failure status in the declaration status badge so coordinators can identify and manually follow up.

Contingency: If push delivery proves unreliable, implement a polling-based in-app notification fallback where drivers see pending declarations on next app open, ensuring the workflow can complete even without push notifications.

medium impact medium prob technical

The acknowledgement service is meant to validate that the driver has fully scrolled through the declaration before confirming. Implementing reliable scroll completion detection in Flutter across different screen sizes and font sizes is technically non-trivial and could be bypassed.

Mitigation & Contingency

Mitigation: Implement scroll position tracking using ScrollController with a threshold (e.g., 95% of content height reached) and record the validated state server-side before allowing acknowledgement submission. Document the approach in the legal sign-off checkpoint noted in the feature documentation.

Contingency: If reliable scroll detection cannot be implemented within the sprint, add a mandatory reading delay timer (e.g., estimated reading time based on word count) as an alternative validation mechanism, pending legal review of the approach.

medium impact low prob dependency

The driver assignment service must coordinate with the threshold-based expense approval workflow for fees above configured thresholds. If the expense approval workflow interface changes or is not yet stable, the integration point could break or produce incorrect routing behavior.

Mitigation & Contingency

Mitigation: Define a clear interface contract between driver-assignment-service and the expense approval workflow before implementation. Use dependency injection so the expense workflow client can be mocked in tests. Monitor the expense approval feature for interface changes.

Contingency: If the expense approval workflow interface is not stable, implement a direct database insert to the expense records table as a temporary bypass, with a flag indicating manual review is needed, until the stable interface is available.