critical priority low complexity infrastructure pending infrastructure specialist Tier 0

Acceptance Criteria

A single `route_constants.dart` file exists under `lib/navigation/` exporting all named route constants as `static const String` values
Route constants cover all five tab roots: home, contacts, add, work, notifications — and all known sub-routes for each branch
A `RouteMetadata` immutable value class is defined with fields: `String semanticsLabel`, `bool suppressSwipeBack`, `String semanticsIdentifier`
`RouteMetadata` is annotated with `@immutable` and implements `==` and `hashCode` correctly
All route path strings follow a consistent pattern (e.g., `/home`, `/home/detail/:id`) with no trailing slashes
No route constant is duplicated — compile-time uniqueness is enforced or documented via a lint comment
File has no runtime dependencies — only plain Dart classes and string constants (no Flutter imports required)
All string constants and model fields include Dart doc comments explaining their purpose
A `routeNames` iterable (or equivalent list) exposes all declared route names for validation in tests
WCAG 2.2 AA: `semanticsLabel` values are human-readable, screen-reader-friendly strings (not slugs or IDs)

Technical Requirements

frameworks
Flutter
Dart
data models
RouteMetadata
performance requirements
File must be a compile-time constant file — zero runtime overhead
No heavy imports that increase cold-start time
security requirements
No sensitive data (user IDs, tokens) embedded in route path constants
Route paths must not expose internal role identifiers in the URL

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Keep this file purely declarative — no logic, no providers, no imports beyond `package:flutter/foundation.dart` for `@immutable`. Use a `const` constructor on `RouteMetadata`. Consider a `RouteMetadata.defaults({required String semanticsLabel, required String semanticsIdentifier})` factory that sets `suppressSwipeBack: true` by default, since the accessibility requirement states swipe-back must be suppressed on ALL routes. Group constants by tab branch using static nested classes or a clear comment section for readability (e.g., `// --- Home branch ---`).

The `semanticsIdentifier` values will be consumed by automated accessibility audit tooling, so they must be stable — never change them once assigned. Use reverse-DNS style identifiers such as `no.norskhandikapforbund.home.root` for forward compatibility.

Testing Requirements

Unit tests in `test/navigation/route_constants_test.dart`: (1) Verify all five tab root constants are non-empty and unique strings. (2) Verify `RouteMetadata` equality semantics — two instances with identical fields must be equal. (3) Verify `RouteMetadata.suppressSwipeBack` defaults to `true` if a convenience constructor is provided. (4) Verify `semanticsLabel` values do not contain underscores or camelCase (should be natural language).

(5) Verify `semanticsIdentifier` values match a defined naming convention (e.g., snake_case). Target: 100% branch coverage for the `RouteMetadata` class.

Component
Navigation Route Configuration
infrastructure medium
Epic Risks (2)
high impact medium prob technical

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.

medium impact medium prob technical

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.