high priority medium complexity testing pending testing specialist Tier 3

Acceptance Criteria

Integration test suite exists for SecureStorageAdapter with tests that run on real iOS simulator and Android emulator (not just mocked)
Test verifies that a written token value is correctly retrieved in a subsequent read (round-trip encryption)
Test verifies that writing a token with a past expiry timestamp causes getTokens to return null or an expired indicator
Test verifies that clearTokens removes all stored keys and subsequent getTokens returns null
Test verifies that storing tokens for user A and switching to user B (different user ID scope) does not return user A's tokens
Test verifies concurrent read and write operations do not corrupt token data (using Dart isolate or async interleaving patterns)
Test verifies that writing new tokens overwrites existing tokens atomically (no partial state)
All tests are tagged with @Tags(['integration']) for selective CI execution
Tests pass on both iOS 16+ simulator and Android API 29+ emulator in CI pipeline
Test file is located in integration_test/ directory following Flutter integration test conventions
Test coverage report shows SecureStorageAdapter and AuthTokenStore at ≥ 85% line coverage
No flaky test retries required — all tests are deterministic

Technical Requirements

frameworks
Flutter
flutter_test
apis
flutter_secure_storage (platform plugin)
Dart async/isolate APIs
data models
AuthToken
AuthTokenStore
SecureStorageAdapter
performance requirements
Each individual test must complete in under 3 seconds on CI hardware
Full test suite must complete in under 60 seconds
Concurrent write test must not deadlock within 5 seconds
security requirements
Integration tests must not write real JWTs or PII — use fake token strings prefixed with 'TEST_'
All test keys must be scoped under a test namespace (e.g., 'test_auth_') to avoid polluting production keychain slots on shared CI runners
Ensure clearTokens is called in tearDown to clean up after every test to prevent cross-test contamination

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

The primary risk in these tests is platform-specific keychain/keystore behavior that only manifests on real devices. Focus the integration tests on scenarios that cannot be adequately mocked: actual AES encryption round-trips, keychain access group isolation, and platform errors (e.g., keychain locked on device restart). For the concurrent test, use a List.generate(10, ...) with Future.wait to simulate 10 simultaneous writes and then verify only the last write's value (or an ordered write with known result) is stored — this tests atomic update semantics. For user isolation, store tokens with user-scoped key prefixes (e.g., 'auth_tokens_{userId}') and verify reading with a different userId returns null.

Be aware that flutter_secure_storage on Android requires minSdkVersion 18+ and uses EncryptedSharedPreferences — ensure the test project's build.gradle reflects this. On iOS, the test will require a valid provisioning profile for keychain access in CI, or use the accessibleWhenUnlockedThisDeviceOnly option for simulator runs.

Testing Requirements

Implement two layers: (1) Unit tests in test/ using mocktail to mock the platform channel so they run on any host machine without a simulator — cover token expiry logic, null handling, and serialization. (2) Integration tests in integration_test/ that run on a real device/simulator to validate actual platform encryption behavior. For concurrent safety, use Future.wait with multiple simultaneous storeTokens calls and verify no corruption. Structure tests with setUp/tearDown calling clearTokens.

Use IntegrationTestWidgetsFlutterBinding.ensureInitialized() for the integration test entry point. Document CI commands for both platforms: flutter test integration_test/ -d and flutter test integration_test/ -d .

Component
Auth Token Store
data low
Epic Risks (3)
high impact medium prob technical

Flutter Secure Storage behavior differs between iOS Keychain and Android Keystore — key accessibility attributes (kSecAttrAccessibleWhenUnlocked vs. WhenUnlockedThisDeviceOnly) may cause tokens to become inaccessible after device restart or OS upgrade, breaking session restoration for returning users.

Mitigation & Contingency

Mitigation: Define explicit Keychain accessibility attributes during implementation and write integration tests on both platforms. Follow flutter_secure_storage documentation for cross-platform accessibility configuration.

Contingency: Implement a recovery flow that detects secure storage read failures and falls back to full re-authentication rather than crashing. Add a migration utility to re-write tokens with corrected attributes if a misconfiguration is discovered post-release.

high impact medium prob security

Personnummer is a legally sensitive national identifier under Norwegian GDPR implementation. If encryption-at-rest or data minimization requirements are not met before launch, the feature could be blocked by legal/compliance review from any of the four partner organizations.

Mitigation & Contingency

Mitigation: Ensure personnummer is only persisted after explicit user consent via the personnummer confirmation widget. Use Supabase column-level encryption for the personnummer field. Document the data processing basis and retention policy before the first TestFlight release.

Contingency: If legal review blocks the personnummer write-back, implement the feature as opt-in only with a deferred sync model, allowing BankID/Vipps login to proceed without storing the personnummer until compliance is confirmed.

medium impact high prob dependency

If the VippsOrgCostConfig data is not populated in Supabase for all four partner organizations before the feature ships, users from unconfigured organizations will see no Vipps login option and may report it as broken, creating confusion and support load.

Mitigation & Contingency

Mitigation: Create a seed migration script for Vipps org configuration and include it in the deployment checklist. Implement a clear admin UI warning when an organization is missing Vipps configuration.

Contingency: Add a feature flag in VippsOrgCostConfig so individual organizations can be enabled/disabled without a code deploy, allowing rapid remediation.