critical priority medium complexity backend pending backend specialist Tier 1

Acceptance Criteria

`mapCategoryToField(String categoryId)` is a pure function — no side effects, deterministic output, no external calls
The function returns the correct BufdirFieldDefinition for every active internal activity category ID used by NHF, Blindeforbundet, and HLF
For an unknown/unmapped category ID, the function returns `null` and calls `log.warning('Unmapped Bufdir category: $categoryId')` — it does NOT throw
The mapping table is backed by the constants defined in task-005 — BufdirFieldDefinition instances are references to kBufdirSections entries, not new objects
Adding a new category ID to the mapping table requires editing exactly one file and one data structure
The function is covered by unit tests for: all known category IDs return non-null; an unknown ID returns null without throwing; the returned definition matches the expected section and field key

Technical Requirements

frameworks
Dart
Flutter
apis
Supabase — activity_categories table (read, to obtain authoritative list of category IDs)
data models
BufdirFieldDefinition
BufdirFormSection
performance requirements
Mapping lookup must be O(1) — use a `const Map<String, BufdirFieldDefinition>` not a linear search

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Declare the mapping as `const Map _categoryMapping = { 'nhf-individual-support': kFieldIndividualSupport, ... }` inside BufdirReportStructureMapper. Fetch the authoritative list of category IDs from the Supabase `activity_categories` table during development to ensure completeness. Use Dart's `debugPrint` or a structured logger for the unknown-ID warning — avoid `print()` in production code.

Consider a script or test that reads category IDs from Supabase and asserts 100% mapping coverage to prevent future regressions when new categories are added.

Testing Requirements

Unit tests: parametrised test covering every known category ID → assert non-null result with correct fieldKey and section. Test one unknown ID → assert null return and no exception. Test that the mapping Map contains no duplicate keys. Integration check: query Supabase activity_categories in a test environment and assert every active category_id has a mapping entry (catches drift between DB and code).

Component
Bufdir Report Structure Mapper
service medium
Epic Risks (2)
high impact medium prob integration

The preview repository depends on aggregated data produced by the Bufdir Data Aggregation feature. If the aggregation RPC schema or Supabase view columns change during parallel development, the repository's typed Dart models will break, causing compile errors or runtime null-dereference failures.

Mitigation & Contingency

Mitigation: Define a shared Dart interface (abstract class) for the aggregated data contract early and have both features code against it. Use Supabase typed generated clients so schema mismatches surface at code generation time rather than runtime.

Contingency: If the aggregation schema changes after the repository is complete, run `supabase gen types dart` immediately, update the repository model, and run repository unit tests before unblocking UI development. Keep a mock data fixture so UI work can continue during the fix.

high impact medium prob scope

The BufdirReportStructureMapper must map internal activity category IDs to the exact label strings used on the official Bufdir reporting form. If the mapping is incomplete or uses outdated labels, coordinators will see mismatches when cross-referencing the preview with the paper form, potentially leading to incorrect submissions.

Mitigation & Contingency

Mitigation: Obtain the current Bufdir reporting form PDF directly from Bufdir (Norse Digital Products has an existing Bufdir dialogue). Extract all field labels and section names into a static constants file reviewed by at least one coordinator from NHF or HLF before implementation begins.

Contingency: If incorrect labels are discovered during UAT on TestFlight, update the static constants file and redeploy. Because the mapper is a pure Dart class with no database storage, corrections require no migration — only a new build.