Implement Organisation Field Config Loader
epic-structured-post-session-report-services-task-003 — Build the infrastructure component that fetches and parses organisation-specific field configuration from Supabase. Handle field visibility rules, required/optional flags, custom labels via the org-labels system, and dynamic field ordering. Expose a typed config model consumed by report-schema-service.
Acceptance Criteria
Technical Requirements
Implementation Notes
Design the Supabase query as a single join or RPC call that fetches both the field config rows and the org-specific label overrides in one round trip — avoid N+1 queries (one per field for label lookup). Model the deserialisation as a static factory method OrganisationFieldConfig.fromJson(Map
on role switch). Keep the loader stateless — it fetches and returns; caching is the responsibility of the upstream ReportSchemaCache layer.
Testing Requirements
Write unit tests using flutter_test with a mocked Supabase client. Cover: (1) successful fetch with custom labels overriding defaults, (2) successful fetch with no org-specific labels (all defaults used), (3) fetch returns null/empty config → fallback config returned, (4) Supabase error → typed OrgFieldConfigException thrown, (5) fields sorted correctly by display_order, (6) invisible fields excluded from output, (7) required flags correctly mapped. Write one integration test against a local Supabase instance that inserts a known config row and asserts the loader returns the expected OrganisationFieldConfig.
Flutter's speech_to_text package behaviour differs meaningfully between iOS and Android — microphone permission flows, locale availability, background audio session interference, and partial-result timing all vary. Inconsistent behaviour could make voice input unreliable for the primary audience (visually impaired peer mentors on iOS VoiceOver).
Mitigation & Contingency
Mitigation: Test speech-to-text-adapter on physical iOS and Android devices from the start, not just simulators. Write platform-specific test cases for permission flows and locale detection. Design the adapter's public interface to be platform-agnostic so that a native bridge could replace the package if needed.
Contingency: If speech_to_text proves unreliable on a platform, implement a native-speech-api-bridge (already identified in the component catalogue) as a drop-in replacement within the adapter, keeping the external interface unchanged so no UI code needs to change.
The coordinator task queue notification mechanism is not fully specified. If the queue system is owned by another team or uses an external service, way-forward-task-service may block on an undefined integration contract, delaying this epic.
Mitigation & Contingency
Mitigation: Define the task queue notification interface as an abstract Dart interface early in the epic. Implement a stub that writes a flag to the database so coordinator list queries can detect new tasks, deferring the real notification integration to a later epic.
Contingency: If the queue integration remains undefined at implementation time, ship way-forward-task-service with database persistence only and add a TODO-flagged notification hook. Coordinators will still see items on next page load; push notification delivery is deferred.