Implement TerminologyRepository with Supabase fetch
epic-dynamic-terminology-and-labels-foundation-task-006 — Build TerminologyRepository that queries the labels JSONB column from Supabase's organization_configs table for a given orgId. On successful fetch, delegate to TerminologyCacheAdapter to persist the result. On network failure, delegate to TerminologyCacheAdapter for offline read. Return a typed Result or Either type. The repository must never throw — all errors are returned as typed failure values to support offline-first resilience.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Use a sealed class or freezed union for TerminologyFailure (e.g. networkError, cacheEmpty, parseError, authError) so callers are forced to handle all cases via exhaustive switch. Prefer fpdart's Either
Wrap the entire method body in a try-catch that catches Object (not just Exception) to guarantee no leakage. Do not use `maybeSingle()` unless the schema guarantees at most one row — use `.single()` and map the empty-result exception to an empty map. Inject dependencies via constructor so the class is testable without a live Supabase instance.
Testing Requirements
Unit tests must mock both SupabaseClient and TerminologyCacheAdapter. Cover: (1) successful fetch → cache write → returns Right(labelMap); (2) network exception → cache hit → returns Right(cachedMap); (3) network exception → cache miss → returns Left(networkAndCacheEmpty); (4) Supabase returns null labels → treated as empty map, cached, returned as Right({}); (5) Supabase returns malformed JSON → mapped to Left(TerminologyFailure.parseError). Use flutter_test with mockito or mocktail. Minimum 90% branch coverage on the repository class.
The labels JSONB column in organization_configs may lack a consistent schema across organizations, causing deserialization failures or silent missing keys when a new organization is onboarded with a differently structured map.
Mitigation & Contingency
Mitigation: Define and enforce a canonical JSONB schema via a Supabase check constraint and a migration script. Validate the schema in TerminologyRepository at parse time and emit structured errors for any key-type mismatches.
Contingency: If schema drift is discovered post-deployment, LabelKeyResolver's fallback logic ensures the app continues to function with English defaults while a data migration is prepared to normalize the offending organization's config.
Device local storage corruption or platform-specific SharedPreferences serialization bugs could render a cached terminology map unreadable, causing the app to fall back to English defaults unexpectedly for an organization with custom terminology.
Mitigation & Contingency
Mitigation: Wrap all cache reads in try/catch, validate the deserialized map against a minimum-required-keys check, and evict corrupted entries automatically before re-fetching from Supabase.
Contingency: Surface a non-blocking in-app warning to the coordinator that terminology may be in default English until the next sync completes; trigger an immediate background sync.