critical priority medium complexity database pending database specialist Tier 0

Acceptance Criteria

Migration script creates driver_assignments table with columns: id (uuid PK), org_id (uuid FK organizations), driver_id (uuid FK auth.users), assignee_contact_id (uuid FK contacts), assignment_date (date, not null), status (text with CHECK constraint: 'pending', 'confirmed', 'pending_approval', 'rejected', 'completed'), fee_amount (numeric(10,2)), deleted_at (timestamptz nullable), created_at (timestamptz default now()), updated_at (timestamptz default now()), created_by (uuid FK auth.users)
Index on org_id exists
Index on driver_id exists
Index on (org_id, status) exists for filtered listing queries
RLS SELECT policy: authenticated users see only rows where org_id matches their JWT org claim
RLS INSERT policy: coordinators and admins can create assignments within their org
RLS UPDATE policy: coordinators and admins can update status and fee_amount for their org's rows only
RLS DELETE blocked — soft-delete via deleted_at only
status CHECK constraint rejects any value outside the defined enum list
Migration file is timestamped, committed to supabase/migrations, and idempotent

Technical Requirements

frameworks
Supabase
PostgreSQL
apis
Supabase Migrations CLI
Supabase RLS
data models
DriverAssignment
Organization
Contact
User
performance requirements
Query for all assignments by org_id and status executes using (org_id, status) composite index
Query for all assignments by driver_id uses driver_id index
security requirements
RLS enabled on table from creation
fee_amount must be numeric with precision to prevent floating-point inconsistencies in financial calculations
org_id always sourced from JWT claim in RLS policies, never from user input
Soft-delete preserves audit trail — no hard deletes permitted

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

The status CHECK constraint values must exactly match the constants used in the Dart DriverAssignment model and DriverAssignmentService — define them together and keep them in sync. Consider adding a database trigger to auto-update updated_at on every UPDATE. The fee_amount column uses numeric(10,2) to avoid float precision issues — this is important for financial fee routing logic downstream. The (org_id, status) composite index is more selective than individual indexes for the most common query pattern (list pending assignments for my org).

Add a partial index on (org_id, driver_id) WHERE deleted_at IS NULL for the common 'active assignments for driver' query pattern.

Testing Requirements

SQL or Supabase integration tests verifying: (1) INSERT by coordinator in correct org succeeds, (2) INSERT by coordinator in wrong org is rejected by RLS, (3) SELECT returns only own-org rows, (4) UPDATE status within org succeeds, (5) UPDATE status across orgs rejected, (6) DELETE attempt rejected, (7) Invalid status value rejected by CHECK constraint, (8) Migration runs cleanly on fresh Supabase project, (9) Migration is idempotent on second run.

Component
Driver Assignment Repository
data medium
Epic Risks (3)
high impact medium prob security

Row-level security policies for driver assignments and declarations must correctly scope data to the coordinator's chapter without leaking records across organizations. An incorrect RLS predicate could silently return empty result sets or, worse, expose cross-org data, both of which are difficult to detect in unit tests.

Mitigation & Contingency

Mitigation: Write dedicated RLS integration test scenarios with multiple org fixtures asserting both data isolation and correct data visibility. Use Supabase's built-in policy testing utilities and review policies with a second developer.

Contingency: If RLS policies prove too complex to get right quickly, implement application-layer org scoping as a temporary guard while RLS is fixed in a follow-up, with an explicit security review gate before production deployment.

high impact medium prob security

The declaration audit logger must produce tamper-evident records. If the database allows updates or deletes on audit rows, the compliance guarantee is broken. Supabase does not natively prevent row deletion by default.

Mitigation & Contingency

Mitigation: Implement an insert-only RLS policy on the audit table that denies UPDATE and DELETE for all roles including the service role. Add a database trigger that rejects mutation attempts and logs the attempt itself.

Contingency: If immutability cannot be enforced at the database level within the sprint, store audit entries in an append-only Supabase Edge Function log stream as a temporary alternative, with a migration plan to the proper table once constraints are implemented.

medium impact low prob technical

The org-feature-flag-service caches flag values to avoid repeated database reads. If the cache is not invalidated promptly after an admin toggles the flag, coordinators may see stale UI state — either seeing driver features when they should not, or not seeing them when they should.

Mitigation & Contingency

Mitigation: Use a Supabase Realtime subscription to listen for changes on the driver_feature_flag_config table and invalidate the in-memory cache immediately on change. Set a short TTL (60 seconds) as a safety net.

Contingency: If Realtime subscription proves unreliable, expose a manual cache-bust endpoint accessible from the admin toggle action, ensuring the cache is cleared synchronously on every flag change.