high priority medium complexity integration pending integration specialist Tier 3

Acceptance Criteria

A 'Sync Now' button is visible on each integration card in the dashboard and on the wizard's final confirmation step
Tapping 'Sync Now' triggers a POST to the sync scheduler API with the correct organization ID and integration ID
While sync is in progress, the button is disabled and replaced with a CircularProgressIndicator on the card
On successful sync completion, the last-sync timestamp label updates immediately to the current time without requiring page reload
On successful sync, the integration status badge transitions to 'Synced' or equivalent success state
On sync API error (4xx/5xx), the status badge updates to 'Error' and an inline error message is displayed on the card
Error state shows a human-readable message and a retry option
If the integration is already syncing (concurrent trigger prevention), the button remains disabled until the in-flight sync completes
Sync trigger from the wizard's final step navigates to dashboard after initiating sync and shows in-progress state on the newly created card
Manual sync does not affect the configured automatic sync schedule
All interactive elements meet WCAG 2.2 AA touch target size (minimum 44x44 dp) and have semantic labels for screen readers

Technical Requirements

frameworks
Flutter
BLoC
Riverpod
apis
Sync Scheduler Service REST API — POST /organizations/{orgId}/integrations/{integrationId}/sync
Sync status polling or Supabase Realtime subscription for sync completion events
data models
activity
assignment
performance requirements
Sync trigger API call must complete request dispatch within 500ms UI feedback
Status polling interval must not exceed 5 seconds to keep UI responsive
Optimistic UI update for in-progress state must occur before API response
security requirements
Sync trigger must include JWT from Supabase Auth — service role key never used client-side
Organization ID scoped from JWT claims — never passed as unverified client param
Rate-limit sync trigger: disable button for minimum 30 seconds after trigger to prevent abuse
ui components
SyncTriggerButton widget (stateful, handles loading/idle/error states)
SyncStatusBadge widget (displays last-sync timestamp + status enum)
CircularProgressIndicator overlay on card during sync
SnackBar or Toast for transient success/error feedback

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Integration Task

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

Implementation Notes

Model sync state as a sealed class (SyncIdle, SyncInProgress, SyncSuccess, SyncError) managed by a BLoC/Cubit scoped to the integration card widget. Use Supabase Realtime subscription on the relevant integration row to receive status updates server-push rather than polling where possible — fall back to polling every 5s if Realtime is unavailable. The dashboard card should subscribe to its own integration's sync state independently so multiple cards can sync in parallel. Avoid global loading state — each card owns its own BLoC instance.

On the wizard final step, initiate sync and immediately navigate to dashboard; the dashboard card's Realtime subscription will pick up the in-progress state automatically. Store last-sync timestamp in the integration config record and read it on card mount.

Testing Requirements

Write unit tests for the SyncCubit/Bloc covering: idle → loading → success state transition, idle → loading → error state transition, and concurrent trigger prevention. Write widget tests for SyncTriggerButton verifying button disablement during loading and correct badge update on state change. Write integration tests using a mock Supabase Realtime channel to verify real-time status update flow end-to-end. Test error handling for network timeout (no response after 30s).

Minimum 80% branch coverage on sync state management logic.

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.