critical priority low complexity backend pending backend specialist Tier 1

Acceptance Criteria

AssignmentStatus enum defines all valid states matching Supabase CHECK constraint values (e.g., pending, active, completed, paused, cancelled) with no magic strings anywhere in the codebase
AssignmentRecord Dart model includes all database columns with correct Dart types and fromJson/toJson serialization
createAssignment() inserts a new record and returns the created AssignmentRecord with server-generated id and created_at timestamp
updateAssignmentStatus() performs a conditional UPDATE using the current status as an optimistic lock predicate; returns a typed conflict error if the row has been modified by another session
softDeleteAssignment() sets a deleted_at timestamp rather than physically removing the row; subsequent read queries filter out deleted records by default
All write methods propagate Supabase PostgrestException as domain-specific typed exceptions (AssignmentConflictException, AssignmentNotFoundException, AssignmentPermissionException)
Invalid status transitions (e.g., completed → active) are rejected at the repository layer with a typed AssignmentInvalidTransitionException before any network call is made
All write operations respect the authenticated user's RLS policy — attempts to write assignments outside the user's organisation scope are rejected by the database and surface as AssignmentPermissionException
Repository is injectable via Riverpod provider and mockable for unit tests

Technical Requirements

frameworks
Flutter
Riverpod
BLoC
apis
Supabase PostgREST REST API
Supabase Realtime (optional, for conflict detection)
data models
AssignmentRecord
AssignmentStatus (enum)
AssignmentConflictException
AssignmentInvalidTransitionException
AssignmentNotFoundException
AssignmentPermissionException
performance requirements
Write operations must complete within 2 seconds on a standard mobile network
Optimistic lock predicate must not require a separate SELECT round-trip — embed the condition in the UPDATE WHERE clause
security requirements
All operations must execute under the authenticated Supabase session token — never use service-role key on the client
RLS policies on the assignments table enforce organisation scoping; no client-side filtering is a substitute for server-side enforcement
Soft-deleted records must be excluded from all queries by RLS or view-level filter, not only by client code

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Model the status state machine explicitly as a Set allowedTransitions map so transition rules are data-driven, not scattered if/else logic. For optimistic locking use Supabase's .eq('status', currentStatus) inside the .update() call and check the returned count — if count == 0, treat it as a conflict. Soft-delete: add a deletedAt nullable DateTime field to AssignmentRecord and configure all read queries built in task-001 to chain .isFilter('deleted_at', null). Register the repository as a Riverpod Provider so BLoC cubits can depend on it via ref.watch without a global singleton.

Testing Requirements

Unit tests using flutter_test and a mocked Supabase client: (1) createAssignment returns a correctly populated AssignmentRecord; (2) updateAssignmentStatus with stale status triggers AssignmentConflictException; (3) softDeleteAssignment sets deleted_at and subsequent reads exclude the record; (4) invalid status transition is rejected before any network call. Integration test against a local Supabase instance (or a dedicated test schema) verifies RLS blocks cross-organisation writes. Aim for 90%+ line coverage on the repository class.

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

Blindeforbundet's encryption key retrieval mechanism may not be finalised at implementation time, or session key availability via Supabase RLS may be inconsistent, causing decryption failures that expose masked placeholders to users and degrade the experience.

Mitigation & Contingency

Mitigation: Agree with Blindeforbundet on key storage and retrieval contract before implementation starts. Prototype key retrieval in a spike against the staging Supabase instance and validate the full decrypt/verify cycle with real test data before committing to the implementation.

Contingency: Implement a fallback that shows a 'field temporarily unavailable' state with a retry affordance. Log decryption failures server-side for audit. Escalate to Blindeforbundet stakeholders to unblock key management before the service tier epic begins.

medium impact medium prob technical

NHF contacts may belong to up to 5 chapters, each governed by separate RLS policies. A coordinator's chapter scope may not cover all affiliations, causing partial profile reads or silent data omissions that are difficult to detect in tests.

Mitigation & Contingency

Mitigation: Map all RLS policy combinations for multi-chapter contacts early. Write integration tests that create contacts with 5 affiliations and query them from coordinators with varying chapter scopes. Use Supabase's RLS test utilities to verify row visibility per role.

Contingency: Add an explicit 'affiliation partially visible' state in the repository response model so the UI can communicate scope limitations to the coordinator rather than silently showing incomplete data.

low impact medium prob scope

Organisation-specific validation rules (e.g., NHF chapter limit, Blindeforbundet encrypted field edit flow) may expand in scope during implementation as edge cases are discovered, causing the validator to grow beyond the planned complexity.

Mitigation & Contingency

Mitigation: Define the complete validation rule set with product and org stakeholders before coding begins. Document each rule with its source organisation and acceptance test. Use a rule registry pattern so new rules can be added without modifying core validator logic.

Contingency: Timebox validator enhancements to 2 hours per additional rule. Defer non-blocking rules to a follow-on maintenance task rather than blocking the epic delivery.