Implement GoRouter StatefulShellRoute configuration
epic-navigation-and-gesture-accessibility-foundation-task-005 — Implement the central NavigationRouteConfig using GoRouter with StatefulShellRoute for the five tab branches (Home, Contacts, Add, Work, Notifications). Each branch must declare its sub-routes with the RouteMetadata defined in task-004. Wrap every shell branch with PopScope to suppress swipe-back as the sole dismissal mechanism, per the accessibility requirement for users who rely on explicit back buttons rather than gesture navigation.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Use `StatefulShellRoute.indexedStack` — not `StatefulShellRoute` with a custom navigator — to avoid state loss on tab switch. Each `StatefulShellBranch` should set `navigatorKey` to a branch-specific `GlobalKey
Implement a `redirect` callback on sensitive routes to check Riverpod auth state; use `ref.read` inside the redirect since the router exists outside the widget tree. Avoid nesting `GoRouter` instances — one router for the whole app. Register the router as `@riverpod GoRouter router(RouterRef ref)` so it can observe auth changes and trigger redirects.
Testing Requirements
Integration tests using `flutter_test` and `GoRouter`'s test utilities: (1) Confirm all five branches are navigable by name using `router.go(RouteConstants.homePath)` etc. (2) Confirm `PopScope` blocks swipe-back — simulate `Navigator.maybePop` and assert it returns `false`. (3) Confirm tab switching preserves sub-route: push a detail screen on Home tab, switch to Contacts, return to Home — detail screen must still be visible. (4) Confirm deep-link `/work/task/42` activates Work tab and pushes the task detail screen.
(5) Widget test: render the shell and verify five `BottomNavigationBar` items are present. Target: all five branches covered, swipe suppression verified on both platforms.
StatefulShellRoute branch navigator state can interact unexpectedly with GoRouter's imperative navigation (go, push, replace), causing state snapshots to desync from actual route stacks. This could manifest as a user returning to a tab and seeing a different screen than expected, breaking the core motor-fatigue promise.
Mitigation & Contingency
Mitigation: Write integration tests that simulate cross-tab navigation with nested pushes before any UI layer is built. Pin go_router to a tested minor version and review the StatefulShellRoute changelog before upgrading.
Contingency: If branch navigator state consistently desyncs, fall back to a manual stack snapshot strategy using a custom NavigatorObserver that records and replays navigation events independently of StatefulShellRoute internals.
Persisted navigation stacks in shared_preferences can become stale or corrupt if route paths are renamed during development, causing app crashes or infinite redirect loops on cold start for users who have an old snapshot.
Mitigation & Contingency
Mitigation: Version the persisted schema with a format key. On app start, validate that all stored route paths exist in the current route config before restoring; silently discard invalid entries rather than crashing.
Contingency: Implement a safe-mode cold start that skips state restoration after a detected crash (via a dirty-launch flag written at startup and cleared on successful first frame), falling back to the default root tab.