high priority medium complexity integration pending integration specialist Tier 1

Acceptance Criteria

On panel mount, existing schedule configuration (frequency, time-of-day, enabled state) is fetched from the scheduler API and rendered accurately
Frequency options (e.g., daily, weekly, monthly) are presented as selectable chips or a dropdown with at least 3 options
A time-of-day picker allows selection of the hour (and optionally minute) when the scheduled sync will run
An enable/disable toggle allows turning the schedule on or off without deleting the configuration
When the user taps Save, PATCH /organizations/{orgId}/integrations/{integrationId}/schedule is called with the new config
After a successful save, the 'Next Scheduled Sync' label updates to display the calculated next run time based on the saved configuration
If the schedule is disabled, the 'Next Scheduled Sync' label shows 'Scheduled sync disabled'
Save errors are shown inline on the panel without dismissing it
The panel clearly distinguishes between unsaved pending changes and the currently persisted schedule
All form controls are accessible with labels and correct semantics for screen readers

Technical Requirements

frameworks
Flutter
BLoC
Riverpod
apis
Sync Scheduler Service REST API — GET /organizations/{orgId}/integrations/{integrationId}/schedule
Sync Scheduler Service REST API — PATCH /organizations/{orgId}/integrations/{integrationId}/schedule
data models
activity
performance requirements
Schedule config load must complete within 1 second on standard connection
Next-sync-time calculation must be computed client-side after save to avoid additional round-trip
Save API call must not freeze UI — async dispatch with loading indicator
security requirements
Schedule configuration scoped by organization via JWT — cannot modify another org's schedule
Supabase RLS restricts schedule config rows to the owning organization
Schedule jobs executed server-side only via Edge Functions — mobile client never directly invokes sync logic
ui components
FrequencySelector widget (chips or DropdownButtonFormField)
TimeOfDayPicker widget (Flutter's built-in showTimePicker wrapped in custom widget)
ScheduleEnableToggle widget (Switch with label)
NextSyncTimeDisplay widget (computed label, updates after save)
SaveButton with loading state

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Integration Task

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

Implementation Notes

Compute the 'next scheduled sync' time client-side using a pure NextSyncTimeCalculator utility that takes frequency, time-of-day, and current DateTime and returns the next DateTime — this makes it unit-testable without mocks. Use Flutter's showTimePicker for time selection but wrap it in a custom widget that formats the picked time according to the organization's locale (24h vs 12h). Store draft form state locally in the cubit as a SyncScheduleDraft object; only commit to API on explicit Save tap. Show a subtle 'Unsaved changes' indicator (e.g., amber dot) when draft differs from last-saved state so users don't lose changes accidentally.

The enable/disable toggle should update the draft immediately for instant visual feedback but still require explicit Save to persist.

Testing Requirements

Write unit tests for SyncScheduleCubit covering: load success → state populated with fetched config, save success → state updated and next-sync time computed correctly, save failure → state reverts, enable/disable toggle → correct enabled field in save payload. Write widget tests verifying next-sync time label updates after mock save success and shows 'disabled' when toggle is off. Test next-sync-time computation logic as a pure function with cases: daily at 08:00 (current time before/after), weekly on Monday, monthly on the 1st. Write integration tests confirming the correct payload structure is sent to the mock scheduler API.

Component
Sync Schedule Configuration
ui low
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.