medium priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

Each mapping row in the Field Mapping Editor has a 'Bufdir Override' toggle visible only when the target integration type is Bufdir
Enabling the override toggle on a row reveals an override value/expression input field and a live preview panel
The live preview shows the resolved output value using sample data, updating as the admin types the expression
Override expressions support at minimum: static string literals, date format tokens (YYYY, MM, DD), and numeric constants
Validation rejects override expressions that would produce a value outside the allowed value set for the target Bufdir column (per BufdirColumnSchema)
Validation error for invalid override expressions is displayed inline beneath the expression input
Multiple rows can independently have overrides enabled
Rows with active overrides are visually distinguished in the mapping table (e.g., accent color row background)
Override configuration is included in the wizard's final payload under a bufdir_overrides key
If the selected integration type is not Bufdir, the override toggle column is hidden entirely
Admin can remove an override by toggling off, which clears the expression and restores normal mapping behaviour

Technical Requirements

frameworks
Flutter
Riverpod
apis
Bufdir Column Schema endpoint (GET /bufdir/column-schema) or static schema from BufdirColumnSchema model
data models
bufdir_column_schema
bufdir_export_audit_log
performance requirements
Live preview must update within 200ms of keystroke in expression field
Schema validation for override values must run client-side without network calls
security requirements
Override expressions are string templates only — no eval() or dynamic code execution
Bufdir column schema (allowed values, bounds) fetched server-side and cached client-side — not editable by client
Override values containing PII patterns should trigger a warning (e.g., if expression matches personnummer regex)
ui components
BufdirOverrideToggle widget
OverrideExpressionInput (text field with tokenised hint text)
OverridePreviewPanel (shows resolved output sample)
OverrideRowHighlight (row background accent for active overrides)

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Integration Task

Handles integration between different epics or system components. Requires coordination across multiple development streams.

Implementation Notes

Load BufdirColumnSchema from the database model (or from a cached Supabase query on wizard init) to get the allowed values/bounds per Bufdir column. Store this schema in a Riverpod provider so OverrideExpressionInput can access it for validation without prop drilling. The expression resolver should be a pure Dart function: parseOverrideExpression(String expr, Map sampleRow) → String. Support only a whitelist of token patterns ({{YYYY}}, {{MM}}, {{DD}}, and literal strings) — reject anything else to prevent injection.

Show the preview using a fixed sample data row generated from BufdirColumnSchema field types. Store override state per row in the FieldMappingEditorState as a Map keyed by source field name. Only render the override toggle column when wizard state's selectedIntegrationType == IntegrationType.bufdir.

Testing Requirements

Unit tests: override expression resolver — static string, date token substitution, numeric constant; schema bounds validation with valid and out-of-range values. Widget tests: toggle override on/off, assert expression field appears/disappears; enter invalid expression, assert inline error; enter valid expression, assert preview updates. Integration test: complete field mapping step with one Bufdir override, confirm override key present in wizard payload on review screen. Coverage target: 85% on expression resolution and validation logic.

Component
Field Mapping Editor
ui high
Epic Risks (4)
medium impact high prob technical

The multi-step Integration Setup Wizard must render different credential fields, field mapping targets, and validation rules depending on the selected integration type. If the type-specific branching logic is implemented as conditional widget trees rather than driven by the Integration Type Registry, the wizard becomes unmaintainable and adding new integration types requires UI code changes.

Mitigation & Contingency

Mitigation: Design the wizard to be metadata-driven from the Integration Type Registry from day one. Credential form fields, required field validation, and mapping target lists are all fetched from the registry, not hardcoded in widgets. Implement one integration type end-to-end first (Xledger) to validate the pattern before building the others.

Contingency: If the metadata-driven approach proves too complex for the initial delivery, implement Xledger and Dynamics as hardcoded wizard variants and create a registry-driven refactor as a follow-up technical debt ticket with a fixed deadline.

medium impact medium prob dependency

The Excluded Features Configuration Panel must wire directly into the feature flag system to suppress HLF app features. If the feature flag system does not yet expose a writable admin interface, this panel cannot save its configuration, blocking the HLF-specific acceptance criteria.

Mitigation & Contingency

Mitigation: Verify that the Organization-scoped Feature Flags feature (a declared dependency) exposes a Dart API for programmatic flag writes before starting this panel. Coordinate with the feature flags team to ensure the write API is available. If needed, schedule this panel as the last item in the epic.

Contingency: If the feature flag write API is unavailable at implementation time, store excluded features in the integration's JSONB settings column and wire them into a local feature flag provider that merges database state with the standard flag system at app startup.

high impact medium prob scope

The Field Mapping Editor's usability for non-technical org admins is high-risk. If the visual mapping interface is confusing, admins will configure incorrect mappings that cause silent data corruption in accounting exports — a serious financial risk discovered only at month-end reconciliation.

Mitigation & Contingency

Mitigation: Conduct usability testing with at least one admin user from Blindeforbundet on the field mapping editor prototype before full implementation. Provide descriptive labels and sample data values for all fields. Add a 'test mapping' preview that shows a transformed sample record before saving.

Contingency: If usability testing reveals the visual editor is too complex, implement a simplified list-based mapping editor (select app field → select external field, one row at a time) as a fallback, deferring the drag-and-drop visual editor to a future iteration.

medium impact medium prob technical

The Credential Management Form's masked fields and connection-test flow may conflict with screen reader requirements — VoiceOver and JAWS must be able to navigate the form, understand which fields are already configured, and receive feedback on connection test results without exposing credential values in accessible text.

Mitigation & Contingency

Mitigation: Design accessible semantics labels for masked fields (e.g., 'API key: configured, last 4 characters: abcd') from the start. Use Flutter's Semantics widget to provide screen-reader-specific text that differs from visual display. Test with VoiceOver on iOS and TalkBack on Android during development, not only at QA.

Contingency: If accessibility conflicts with security requirements for the credential form, implement a separate 'accessibility mode' flow where credential configuration is done through a separate confirmation step that provides more explicit semantic feedback without risk of value exposure.