Implements architecture section 4.7: IHealthGateway now exposes the Phase 3B contract (HealthProviderType, HealthConnectionStatus, HealthDataPayload, checkStatus/requestAuthorization/fetchLatestBiometrics/disconnect) with defaults derived from the existing primitives. Drivers and test fakes switch from implements to extends so Dart inherits the default bodies.
- Mobile driver: BLOOD_GLUCOSE added to iOS/Android read sets (mmol/L to mg/dL normalization); checkStatus probes hasPermissions plus Health Connect SDK readiness; samsungHealth aliases the Health Connect binding on Android (federated Samsung/Pixel feeds); disconnect clears the cached SDK probe.
- Fallback driver: safe dummy states on Windows/Web/macOS (manualFallback connected, enterpriseFhir notConfigured, native unsupportedPlatform); fetchLatestBiometrics serves the encrypted drift cache; zero platform-channel calls.
- Settings: IntegrationsController rewritten from toggles to status orchestration (refreshStatuses, connect/disconnect round-trips, denial to permissionDenied plus snackbar); SettingsScreen gains a Health Integrations card with Apple Health, Health Connect (Samsung & Pixel), and SMART on FHIR rows showing live status badges and Connect/Disconnect buttons with desktop-safe disabled states.
- Manifests: Android adds READ_BLOOD_GLUCOSE, healthdata package query, ACTION_SHOW_PERMISSIONS_RATIONALE intent, and ViewPermissionUsageActivity alias; iOS adds NSHealthShareUsageDescription and NSHealthUpdateUsageDescription.
- Tests: +13 (fallback dummy-state matrix, integrations controller transitions, Settings desktop disabled-states and mobile connect/disconnect round trip); existing fake switched to extends; navigation test updated for the renamed card title.
Verified: build_runner 191 outputs; flutter analyze clean; flutter test 148/148; flutter build windows debug succeeded.
Domain (pure Dart):
- Add 12-quadrant InjectionSite anatomical model with a least-recently-used
rotation policy, DoseEntry entity, and Glp1Compound value object
(Semaglutide 168h, Tirzepatide 120h, Liraglutide 13h)
- Add CalculateSerumLevel use case implementing
C(t) = sum(D_i * 0.5^((t - t_i) / t_half))
- Define IMedicationRepository contract; retire superseded MedicationDose
Data:
- Add injection-history CRUD to AppDatabase (watch/get/insert/update/delete/
latest-administered), ordered newest first
- Implement drift-backed MedicationRepository with record-to-entity mapping
Presentation and local alerts:
- Add MedicationController (StateNotifier) managing serum estimation, site
rotation suggestions, and best-effort reminder scheduling
- Rework MedicationScreen: serum card, suggested-site card, interactive log
dialog (compound, dosage, timestamp, quadrant), history with delete, and a
60s decay ticker
- Add INotificationService / PlatformNotificationService wrapping
flutter_local_notifications (one-shot scheduling on Android/iOS/macOS,
graceful no-op on Web/Windows/Linux), Android boot receivers for reminder
restoration, and the timezone dependency
Development tooling:
- Add debug-only "Continue Without Signing In" bypass on the login screen,
backed by an in-memory devAuthBypassProvider; the router guard honors the
flag and the shell shows a dev-mode banner while active
Fixes:
- Resolve the Supabase client lazily in SupabaseAuthService so widget tests
and pre-initialization builds no longer throw
Testing:
- 36 new tests covering PK decay math, rotation determinism, repository CRUD
on an in-memory drift database, controller behavior with fakes, and the
end-to-end dev bypass flow; full suite green (37/37)
- BUILD_STATE.md: mark Phase 2 complete and record all verification gates