Commit Graph

7 Commits

Author SHA1 Message Date
Mike Kell a40589cc89 ci(release): add alpha release pipeline, signing config, and publish tooling
- .forgejo/workflows/release.yaml: tag-triggered (v*) pipeline that builds a
  split-per-abi Android arm64 APK (signed via ANDROID_KEYSTORE_BASE64 /
  ANDROID_KEY_PROPERTIES secrets), a Windows MSIX plus portable zip, and
  attaches every asset to a Forgejo prerelease through the releases API;
  Flutter pinned to 3.47.x because pubspec.lock requires flutter >=3.44.0
- scripts/publish_alpha.ps1: local one-shot build+publish equivalent
  (codegen, APK, portable zip, MSIX, release + asset upload under dist/v*)
- android: release signing wired to key.properties with minify, resource
  shrinking, and new proguard-rules.pro (Flutter embedding, SQLCipher, and
  JSON keep rules)
- pubspec: msix ^3.16.7 dev dependency and msix_config publisher identity
- scripts/test.ps1: Forgejo asset-upload probe reading the token from env;
  the hardcoded token was removed and its rotation is tracked as a
  BUILD_STATE.md verification gate
- gitignore: /dist/, **/android/build/, and android/key.properties
2026-10-18 08:11:23 -04:00
Mike Kell e43603be1b feat(nutrition,pantry): add Phase 3C nutritional search engine, barcode scanning, and dual-source food cache
Implements the architecture 4.8 resolution ladder: local SQLCipher cache ->
Open Food Facts (4s timeout) -> USDA FoodData Central fallback, with every
remote hit written through to the new FoodProductsTable (schema v5).

- domain: FoodProduct entity + IFoodSearchRepository contract (pure Dart)
- data: UsdaFdcClient (FDC nutrient-ID mapper 1008/1003/1004/1005/1079/1093,
  api_key sent as query parameter - FDC ignores body keys and 403s otherwise),
  OpenFoodFactsClient (userAgent with app identity, SearchTerms search,
  getProductV3 barcode lookup), shared RemoteFoodDataSource interface
- presentation: FoodSearchController (400ms debounce, request-token
  supersession), FoodSearchScreen (MobileScanner sheet on mobile, manual UPC
  dialog + notification on desktop/web, macro action sheet with serving
  multipliers, Log to Diary / Add to Pantry actions)
- integration: /food-search route with ?preset=pantry, Nutrition screen entry
  button, Pantry screen Scan Item action
- hardening: FoodSearchUnavailableException distinguishes total source outage
  from a healthy empty result; GoogleHealthConnector dotenv reads now guarded
  with isInitialized (fixes NotInitializedError crashing app_navigation_test)
- tests: +16 (fallback sequence cache->OFF->USDA for text and barcode,
  USDA request shape via MockClient); full suite 170/170, analyze clean
2026-10-17 19:37:06 -04:00
Mike Kell 5b5e7e2f57 feat(platform,settings,nutrition): add Google Health cloud sync for desktop
Cloud connector framework: ICloudHealthConnector contract, supportsCloudSync / isCloudSyncReady on IHealthGateway, and a HealthProviderType.googleHealth slot; a conditional-import shim (io implementation / web stub) keeps platform channels out of web builds.

Google Health connector (successor to the retired Fitbit Web API, shutdown 2026-10-30): OAuth2 authorization-code + PKCE through the system browser with a loopback redirect; read-only activity-and-fitness + health-metrics scopes; tokens in flutter_secure_storage with transparent refresh; paginated weight and active-energy-burned dataPoints reads with kg-to-lb normalization from the per-point unit field; pure unit-tested parsers.

Gateway wiring: both drivers store injected connectors (desktop runs MobileHealthGateway through the io conditional import; the fallback driver is web-only); cloud status/authorize/disconnect route first and reads merge native + cloud non-fatally; syncFromHealth accepts cloud-only sources and imports persist as BiometricSource.cloudSync.

UI: Google Health row in Settings with Connect/Disconnect and auto-import on connect; explanatory desktop copy on the Apple Health and Health Connect rows; the Nutrition weight card syncs through a connected cloud partner and surfaces the outcome as a snackbar, degrading to the manual dialog when no source is connected.

Field fixes recorded in BUILD_STATE: io-driver connector wiring, duplicate-implementation merge correction, weight-card sync gate. Tests: google_health_parser_test suite; settings_screen_test updated for the fourth integration row. The legacy Fitbit connector was fully removed before shipping.
2026-10-17 18:06:36 -04:00
Mike Kell 298cadef32 feat(platform,auth,app): align identity to companionglp.com and harden OAuth deep-link handoff
Identity: rename the application identity to com.companionglp.glpcompanion on every platform (Android applicationId/namespace + MainActivity package, iOS/macOS bundle IDs incl. RunnerTests, Windows CompanyName/copyright, web manifest id, Supabase OAuth redirect scheme).

Deep links: register the custom scheme com.companionglp.glpcompanion:// in iOS/macOS Info.plist (CFBundleURLTypes), the Android VIEW/BROWSABLE intent-filter, and Windows per-user HKCU protocol registration. Server-side steps (Supabase uri_allow-list, Entra optional email claim) are recorded in BUILD_STATE.md.

Windows runner: single-instance mutex (Local\GLPCompanionSingleInstance) so login callbacks are delivered deterministically; SendAppLinkToInstance forwarding with foreground/taskbar-flash fallback so protocol activation can never look like a hang; protocol diagnostics appended to TEMP glpcompanion-protocol.log.

macOS: add the missing com.apple.security.network.client entitlement so the sandboxed runner can reach Supabase at all.

Auth UX: surface deferred OAuth/magic-link handshake failures as snackbars on the login screen; make isAuthenticatedProvider reactive (watches authStateProvider) with a microtask-deferred router refresh so live sign-in and sign-out redirect correctly; add a debug package:logging listener so supabase_flutter diagnostics are visible under flutter run.

Field-verified on Windows: Google, Microsoft (Entra ID), and email magic-link sign-in round trips plus sign-out redirect to /login.
2026-10-17 15:28:22 -04:00
Mike Kell 7682d8317a feat(medication): complete Phase 2 GLP-1 tracking, reminders, and dev bypass
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
2026-10-16 06:20:23 -04:00
Mike Kell 7b6b646d2c feat(auth): complete Phase 1 passwordless identity and encrypted DB foundation 2026-10-16 05:01:54 -04:00
Mike Kell 98e0d318f3 feat(init): baseline multiplatform architecture with clean arch shell, clinerules, and docs 2026-10-15 21:01:52 -04:00