Add Hive storage backend to TerminologyCacheAdapter
epic-dynamic-terminology-and-labels-foundation-task-003 — Extend TerminologyCacheAdapter to support Hive as an alternative storage backend via a strategy pattern or constructor parameter. Define a TerminologyCacheBackend interface with SharedPreferences and Hive implementations. Both backends must implement the same write/read/clear contract. Hive is preferred for larger label maps due to faster reads on low-end devices.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
The strategy pattern here is constructor injection — `TerminologyCacheAdapter(TerminologyCacheBackend backend)`. A factory constructor or static factories can provide `TerminologyCacheAdapter.withSharedPreferences()` and `TerminologyCacheAdapter.withHive()` as convenience constructors. Hive stores `Map
The decision of which backend to use at runtime should be made at the DI layer (Riverpod provider), not inside the adapter itself. Document in a comment that Hive is recommended when the label map exceeds ~50 entries per organization, as this is the threshold where Hive's binary format outperforms SharedPreferences JSON.
Testing Requirements
Write tests for both backends separately. Use `MockSharedPreferences` for SharedPreferencesBackend. For HiveBackend, use `hive_test` package which provides an in-memory Hive implementation — call `Hive.init(Directory.systemTemp.path)` in setUp and `Hive.deleteBoxFromDisk('terminology_cache')` in tearDown. Test cases (run for both backends): (1) write then read returns same map, (2) read on empty returns null, (3) multi-org isolation, (4) clear removes only target.
Additionally test HiveBackend-specific: (5) lazy box open succeeds on first read without pre-initialization, (6) concurrent writes to the same orgId do not corrupt data.
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.