critical priority medium complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

Dashboard lists all integrations configured for the current organization in a responsive card grid
Each card displays: integration name, integration type label (e.g., 'Microsoft Dynamics', 'Xledger', 'Cornerstone'), status badge (active/error/pending), last successful sync timestamp (formatted as relative time, e.g., '2 hours ago'), and next scheduled sync time
Status badges use the unified entity color system: active = cyan (#22d3ee, data-accent='integration'), error = red, pending = amber
Each card has an 'Edit' action button that navigates to the integration detail/edit screen
Each card has a 'Sync Now' action button that triggers a manual sync; the button is disabled for integrations in 'error' state until credentials are re-validated
Tapping 'Sync Now' shows a loading spinner on that specific card and disables the button for that card only — other cards remain interactive
An empty state is shown when no integrations are configured, with a 'Add Integration' call-to-action button
A global 'Add Integration' FAB or button is present and navigates to the integration creation flow
The dashboard auto-refreshes integration statuses every 30 seconds via Supabase Realtime or polling
Dashboard is accessible: cards are announced correctly by screen reader, status badges have text alternatives, loading states are announced
Dashboard loads within 500ms; a skeleton loader is shown while data is fetching

Technical Requirements

frameworks
Flutter
BLoC
Riverpod
apis
Supabase REST API — integrations table (read, filter by organization_id)
Supabase Realtime — subscribe to integrations table for live status updates
Supabase Edge Function — trigger-manual-sync (called from Sync Now button)
data models
Integration
IntegrationStatus
IntegrationConfiguration
SyncResult
performance requirements
Initial dashboard load within 500ms with skeleton loader shown immediately
Status badge updates via Realtime must reflect within 2 seconds of backend status change
Card grid must render 20+ cards without frame drops (60 fps)
security requirements
Dashboard only shows integrations belonging to the current user's organization — enforce via RLS and client-side organization_id filter
Only admin/org_admin roles may see this screen — enforce via route guard
Manual sync trigger requires current user to have write permission on the integration
ui components
IntegrationConfigDashboard (screen widget)
IntegrationCard (status + actions)
IntegrationStatusBadge (active/error/pending)
SyncNowButton (with per-card loading state)
IntegrationDashboardEmptyState
IntegrationCardSkeletonLoader
AppCardGrid (design system card-grid-2 or card-grid-3 class)

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

Use a `ListView` with `GridView.builder` (crossAxisCount: 2 on tablets, 1 on phones) for the card layout. Each `IntegrationCard` should be a stateless widget receiving an `Integration` model; loading state for 'Sync Now' is managed in the parent BLoC/StateNotifier keyed by `integration_id` to ensure per-card isolation. Avoid storing loading state in the card widget itself. Subscribe to Supabase Realtime on the `integrations` channel filtered by `organization_id = ''` to receive live status updates.

On receiving a Realtime event, emit a `IntegrationStatusUpdated` BLoC event that updates only the affected integration in the list — avoid re-fetching the full list. For the last-sync timestamp, use a `timeago` or equivalent Dart package to format as relative time; refresh the display every minute. The skeleton loader should mirror the card layout to minimize layout shift when data arrives. Define `IntegrationStatus` as an enum: `active`, `error`, `pending`, `disabled` — map from the Supabase string value.

Color mapping: use design token semantic colors, not hardcoded hex values, to remain consistent with the design system.

Testing Requirements

Write flutter_test widget tests for: (1) cards render with correct name, type, status badge, and timestamps, (2) empty state renders when list is empty, (3) Sync Now button is disabled for error-status integrations, (4) Sync Now button shows per-card loading state without affecting other cards, (5) skeleton loader shows while data is loading, (6) Edit button navigates to the correct route. Mock Supabase repository with fixtures for: empty list, list with active/error/pending integrations, and Realtime status update events. Test Realtime update: emit a status change event from the mock stream and assert the card's badge updates. Test accessibility: card Semantics labels include integration name and status.

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.