high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

Valid context input produces a URI string with the correct base path and all expected query parameters present
Prefill values containing special characters (spaces, ampersands, Norwegian characters æøå) are correctly percent-encoded in the resulting URI
Cold-start navigation path (app not running) resolves to the correct go_router route string
Warm-start navigation path (app already running) triggers router.go() with the correct URI
When activityId does not exist in the repository, handler routes to the configured fallback URI
When contactId is inaccessible (insufficient permissions), handler routes to the configured fallback URI
All repository and router interactions use mocks — no real Supabase or go_router instances
URI structure matches the documented deep link schema (correct path segments and parameter names)
Tests are independent — each test sets up its own mock state without relying on prior test execution

Technical Requirements

frameworks
Flutter
flutter_test
go_router
Riverpod
mocktail
apis
go_router navigation API
data models
ScenarioDeepLinkContext
ScenarioDeepLinkHandler
PromptHistoryRepository
performance requirements
URI construction must be synchronous or resolve within one event loop tick
All tests complete in under 1.5 seconds
security requirements
Prefill values must be URL-encoded to prevent URI injection
contactId validation must enforce row-level security context in integration tests (not unit scope here, but mock should reflect that access can be denied)

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

go_router's GoRouter cannot be easily instantiated in unit tests — use a mock class that implements or wraps the router interface, or extract navigation logic behind a NavigationService interface that can be mocked. If go_router version does not support easy mocking, consider defining a thin RouterDelegate abstraction in ScenarioDeepLinkHandler that the tests can replace. URI building should use Dart's Uri class (Uri(path: ..., queryParameters: {...})) rather than string interpolation to guarantee correct encoding. For cold-start vs warm-start distinction, the handler likely checks whether GoRouter.of(context) is available or uses a platform channel callback — mock accordingly.

Testing Requirements

Unit tests only using flutter_test and mocktail. Create scenario_deep_link_handler_test.dart. Mock both the go_router GoRouter instance and PromptHistoryRepository. For URI correctness tests: parse the resulting URI string using Uri.parse() and assert scheme, path, and queryParameters individually — do not do string equality on the full URI (fragile).

For URL-encoding tests: include at least one Norwegian character (ø, æ, å) and one ampersand in prefill values and assert the encoded form. For cold/warm-start: mock the router state (null vs active) and assert the correct navigation method (push vs go) is called. For validation failures: stub the repository to return null or throw an access-denied exception and assert fallback URI is used.

Component
Scenario Deep Link Handler
service medium
Epic Risks (2)
high impact medium prob scope

The Rule Engine must support a flexible JSON rule schema that can express compound conditions (e.g., contact_type AND wellbeing_flag AND delay_days). Underestimating schema expressiveness may require breaking changes to the rule format after coordinators have already configured rules.

Mitigation & Contingency

Mitigation: Define and freeze the rule JSON schema (trigger_type enum, metadata_conditions structure, delay logic) before any implementation begins; validate schema against all known HLF scenarios documented in the feature spec.

Contingency: If schema changes are needed after deployment, implement a schema version field and a migration utility that upgrades stored rules to the new format without coordinator intervention.

medium impact medium prob technical

Deep-link navigation to the activity wizard with pre-filled arguments may fail if the user's session has expired or if the wizard route is not yet mounted in the navigator stack, causing unhandled navigation exceptions.

Mitigation & Contingency

Mitigation: Implement session state check before navigation; if session is expired, redirect to biometric/login screen and store the pending deep-link URI for post-auth redirect using go_router's redirect mechanism.

Contingency: If post-auth redirect proves unreliable, fall back to navigating to the home screen with a visible action banner that re-triggers the wizard with pre-filled arguments.