high priority medium complexity integration pending frontend specialist Tier 2

Acceptance Criteria

WizardDraftRepository concrete implementation reads and writes drafts using flutter_secure_storage (not SharedPreferences, to protect field values)
Draft is serialized to JSON and stored under a key scoped to the user ID and wizard type (e.g., 'wizard_draft_{userId}_{wizardId}')
On pause: draft JSON written to secure storage with pausedAt timestamp in ISO 8601 UTC
On resume: draft JSON read from secure storage, deserialized, and expiry check applied before use
Expiry check: if DateTime.now().toUtc().difference(draft.pausedAt).inDays >= 7, treat as expired — delete the entry and start wizard from step 0
If no draft entry exists in storage on resume, WizardStateManager starts from step 0 with empty fieldValues — no error thrown
If JSON deserialization fails (corrupt data), treat as no draft and start from step 0 — log warning via dart:developer log(), do not crash
Draft is deleted from storage when WizardComplete state is reached (after successful submit)
WizardDraftRepository exposes: saveDraft(WizardDraft), loadDraft(userId, wizardId) → Future<WizardDraft?>, deleteDraft(userId, wizardId)
Integration test: pause wizard, cold-restart app session (recreate BLoC), resume — assert correct step and fields are restored from storage

Technical Requirements

frameworks
Flutter
BLoC
performance requirements
flutter_secure_storage read/write must not block UI — all calls are async and awaited off the main isolate
Draft JSON payload must not exceed 64KB — enforce a field value size limit if wizard fields are large
security requirements
Use flutter_secure_storage (iOS Keychain, Android Keystore) — never plain SharedPreferences for draft data
Storage key includes user ID to prevent cross-user data leakage on shared devices
On logout or account switch, call deleteDraft for all wizard types to clear stale user data

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Use the flutter_secure_storage package (add to pubspec.yaml if not already present). Define WizardDraftRepositoryImpl in lib/features/wizard/data/wizard_draft_repository_impl.dart implementing the WizardDraftRepository abstract class. Use jsonEncode/jsonDecode for serialization. The WizardDraft.fromJson factory should wrap parsing in try/catch returning null on failure.

For the expiry check, encapsulate the logic in a private method _isExpired(WizardDraft) on the repository to keep it testable. Register WizardDraftRepositoryImpl in the dependency injection layer (Riverpod provider or BLoC provider tree) so WizardStateManager receives it via constructor injection. When the wizard is completed, call deleteDraft from the BLoC's on handler — do not rely on UI to clean up.

Testing Requirements

Two levels of testing required. (1) Unit tests: mock flutter_secure_storage using a fake in-memory map; test saveDraft writes correct JSON; test loadDraft returns null for missing key; test expiry logic with a draft timestamped 8 days ago; test corrupt JSON returns null gracefully. (2) Integration test (flutter_test with real secure storage on device/emulator or using flutter_secure_storage fake): write a draft, recreate the repository instance, load the draft, assert fields match. Minimum 8 test cases total.

Component
Wizard State Manager
service medium
Epic Risks (4)
high impact medium prob technical

The WizardStateManager BLoC must guarantee that step transitions only occur on explicit user action, never automatically. Subtle reactive patterns in Bloc (e.g. stream listeners triggering add() calls) could inadvertently auto-advance the wizard, violating the core cognitive accessibility rule and creating a regression that is difficult to detect without dedicated tests.

Mitigation & Contingency

Mitigation: Write a dedicated unit test that subscribes to the BLoC stream and asserts no StepChanged event is emitted for 5 seconds after a state update, without an explicit user-sourced event being dispatched. Make this test part of the CI gate for the WizardStateManager.

Contingency: If an auto-advance regression is discovered post-integration, introduce a mandatory UserActionToken parameter on all step-transition events so the BLoC can structurally refuse transitions that do not originate from a user gesture handler.

medium impact medium prob integration

The ConfirmBeforeSubmitScreen requires deep-linking back to specific wizard steps for corrections. Implementing bidirectional navigation within a multi-step wizard while preserving all previously entered state is architecturally non-trivial and may conflict with the existing StatefulShellRoute navigation setup described in the app architecture.

Mitigation & Contingency

Mitigation: Design the ConfirmBeforeSubmitScreen's back-navigation links to dispatch a GoToStep event on the WizardStateManager rather than using GoRouter's pop() chain. This keeps navigation state entirely in the BLoC and avoids coupling to the router's stack semantics.

Contingency: If BLoC-driven step navigation proves incompatible with the router, implement the correction flow as a dedicated sub-route that pre-populates its form from the WizardStateManager's current draft, then merges the edited field back into the draft on completion before returning to the confirm screen.

medium impact medium prob technical

The CognitiveAccessibilityAudit utility must inspect live widget trees for violations such as icon-only buttons. Flutter's widget tree inspection APIs are available in test mode but have limitations in identifying semantic intent (e.g. distinguishing a decorative icon from a navigation button). False negatives could give a false sense of compliance.

Mitigation & Contingency

Mitigation: Augment the audit with a convention-based approach: require all navigation buttons to use a named wrapper widget (e.g. LabelledNavigationButton) that the audit can detect by type, rather than relying solely on widget-tree semantics analysis.

Contingency: If widget-tree detection proves insufficiently reliable, scope the CognitiveAccessibilityAudit to route-configuration analysis (verifying back navigation availability per route) and static analysis of wizard step count definitions via the CognitiveLoadRuleEngine, which provides deterministic results.

low impact high prob scope

The InlineContextualHelpWidget sources content from a bundled JSON asset via the HelpContentRegistry. If help texts are missing for newly added screens or fields (a likely scenario as the 61-feature app grows), the widget silently shows nothing, degrading the accessibility experience without any visible failure.

Mitigation & Contingency

Mitigation: Integrate a CognitiveAccessibilityAudit check that verifies every registered (screenId, fieldId) pair that requests help has a corresponding entry in the HelpContentRegistry bundle. Run this check in CI as part of the audit report.

Contingency: Add a debug-mode overlay that highlights fields with missing help entries using a visible warning indicator, making coverage gaps immediately obvious to developers during local development before they reach CI.