high priority medium complexity backend pending backend specialist Tier 7

Acceptance Criteria

After a valid acknowledgement record is inserted, the declarations row status column transitions from 'SENT' to 'ACKNOWLEDGED' atomically within the same Supabase transaction
Status update is idempotent: if declaration is already ACKNOWLEDGED, re-submission returns 409 CONFLICT rather than duplicating the audit event
Audit event is written to the declaration_audit_log table with fields: actor_id (UUID), declaration_id (UUID), org_id (UUID), action_type = 'DECLARATION_ACKNOWLEDGED', occurred_at (ISO 8601 UTC)
If the status update succeeds but audit log insertion fails, the entire operation rolls back — no partial state is persisted
Audit log row is not editable or deletable by any app-level role (enforced via Supabase RLS: INSERT only, no UPDATE/DELETE)
The acknowledged_at timestamp stored on the declaration row equals the occurred_at timestamp in the audit log for the same event
API returns 200 with the updated declaration object including new status and acknowledged_at fields
Attempting to acknowledge a declaration with status != 'SENT' returns 409 with error code ALREADY_ACKNOWLEDGED or INVALID_STATUS_TRANSITION

Technical Requirements

frameworks
Supabase Edge Functions
Supabase Postgres (transactions via rpc or supabase-js withTransaction pattern)
BLoC (AcknowledgementBloc transitions to AcknowledgementSuccess state)
apis
POST /declarations/:id/acknowledge
Supabase RPC: rpc('acknowledge_declaration', { p_declaration_id, p_actor_id, p_org_id })
data models
Declaration (id, status, acknowledged_at, org_id)
DeclarationAcknowledgement (id, declaration_id, actor_id, created_at)
DeclarationAuditLog (id, declaration_id, actor_id, org_id, action_type, occurred_at)
performance requirements
Atomic status update + audit log write must complete within a single DB round trip via stored procedure
p95 latency for the full acknowledgement handler (including this step) must remain under 600 ms
security requirements
RLS on declarations table: only the driver who owns the declaration (auth.uid() = driver_id) may trigger the status update
RLS on declaration_audit_log: INSERT allowed for authenticated service role only; SELECT restricted to org admins and the actor themselves
org_id must be derived from the server-side JWT claims, never trusted from the client request body

Execution Context

Execution Tier
Tier 7

Tier 7 - 84 tasks

Can start after Tier 6 completes

Implementation Notes

Implement the core logic as a Postgres stored procedure `acknowledge_declaration(p_declaration_id uuid, p_actor_id uuid, p_org_id uuid)` that (1) checks current status with a FOR UPDATE lock, (2) raises exception if not SENT, (3) updates status, (4) inserts audit log row — all within one transaction. Call from Edge Function via `supabase.rpc('acknowledge_declaration', {...})`. This avoids multi-round-trip race conditions. The Edge Function remains thin: validate input, call RPC, map result to HTTP response.

Store action_type as a Postgres enum `declaration_action_type` with value 'DECLARATION_ACKNOWLEDGED' to enforce valid values at the DB level.

Testing Requirements

Unit tests: (1) acknowledgement of a SENT declaration transitions status to ACKNOWLEDGED; (2) acknowledgement of an already-ACKNOWLEDGED declaration returns 409; (3) audit event fields match expected values exactly (actor_id, declaration_id, org_id, action_type, timestamp). Integration tests against local Supabase instance: verify transaction atomicity by simulating a failure after status update and confirming rollback leaves declaration in SENT state and no orphaned audit log row. Test RLS: confirm a driver cannot acknowledge another driver's declaration.

Component
Declaration Acknowledgement Service
service medium
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.