glp-companion/docs/architecture.md

36 KiB

Architectural Specification: GLP-1 Companion Platform

Document Version: 1.0.0
Target Runtimes: iOS, Android, Web (Wasm/CanvasKit), macOS, Windows
Framework: Flutter 3.x (Dart 3.x)
Security & Compliance Level: HIPAA & GDPR-Ready Tier 1 Health Application


1. System Vision & Domain Boundaries

The GLP-1 Companion is designed to address the clinical and behavioral realities of GLP-1/GIP receptor agonist pharmacotherapy (Semaglutide, Tirzepatide, Liraglutide). The architecture is structured around five core pillars:

  1. Pharmacokinetics & Dose Logistics: Modeling dosage curves, biological half-lives, titrations, and physical injection site rotation.
  2. Lean Mass Preservation: Monitoring protein intake targets and hydration volumes to mitigate muscle atrophy and kidney/GI adverse events.
  3. Recipe Scraping & Pantry Ingestion: De-duplicating grocery overhead via automated microdata extraction and local inventory delta checks.
  4. Decoupled Biometric Ingestion: Unifying OS-native health ecosystems (HealthKit, Health Connect) with cloud APIs (MyFitnessPal, Withings) across mobile, desktop, and web.
  5. Zero-Knowledge / High-Privacy Local Persistence: End-to-end encrypted local databases (SQLCipher) paired with passwordless federated authentication.

2. Architectural Paradigm: Feature-First Clean Architecture

The platform rejects monolithic and layered-by-technical-type layouts in favor of Bounded Contexts (Feature-First Clean Architecture). Each business domain operates as an autonomous module.

lib/
├── app/                              # Top-level application bootstrap
│   ├── app.dart                      # Multiplatform root widget
│   ├── observers/                    # Routing & state lifecycle observers
│   └── router/                       # GoRouter route declarations & redirect guards
├── core/                             # Shared foundation & cross-cutting concerns
│   ├── error/                        # Failures, exceptions, and error boundary handlers
│   ├── network/                      # HTTP/REST clients, retry policies, TLS pinning
│   ├── platform/                     # Abstract hardware & OS platform wrappers
│   ├── security/                     # SQLCipher key generation, biometric locks, keychain
│   ├── theme/                        # Dynamic Material 3 & Apple Cupertino theme engines
│   └── utils/                        # DateTime calculations, pharmacokinetics math, formatters
└── features/                         # Modular business domains
    ├── auth/                         # Passwordless, OAuth SSO, passkey integration
    ├── medication/                   # Titration tracking, dose logging, injection rotation
    ├── nutrition/                    # Micro/macro logs, protein density, hydration
    ├── recipes/                      # Schema.org JSON-LD web scraper, recipe catalog
    ├── meal_planner/                 # Weekly calendar, portion scaler
    ├── pantry/                       # Food inventory, expiration date manager
    └── health_sync/                  # HealthKit, Health Connect, MFP abstraction

Clean Architecture Layers per Feature

Within each feature module in lib/features/<feature_name>/, separation of concerns is strictly enforced:

<feature_name>/
├── domain/                           # Pure Dart - ZERO external framework imports
│   ├── entities/                     # Immutable domain business objects
│   ├── value_objects/                # Validated value types (e.g., DosageMg, ProteinTarget)
│   ├── repositories/                 # Abstract repository interfaces
│   └── usecases/                     # Isolated business operations (single responsibility)
├── data/                             # Infrastructure & data persistence
│   ├── datasources/
│   │   ├── local/                    # Drift tables, secure key-value stores
│   │   └── remote/                   # Supabase REST, GraphQL, third-party APIs
│   ├── models/                       # Data Transfer Objects (DTOs), JSON serialization
│   └── repositories/                 # Concrete repository implementations
└── presentation/                     # UI & State management
    ├── controllers/                  # Riverpod AsyncNotifiers / StateNotifiers
    ├── screens/                      # Responsive top-level views
    └── widgets/                      # Reusable components (Adaptive Dialogs, Pickers, Cards)

3. Technology Stack & Multiplatform Dependencies

Capability Selection Rationale
Core UI Framework Flutter 3.x (Dart 3.x) Native AOT compilation on iOS, Android, macOS, and Windows; CanvasKit/Wasm rendering on Web.
State Management Riverpod 2.x (riverpod_generator) Compile-time safe dependency injection, automatic provider disposal, testability without BuildContext.
Navigation & Deep Linking go_router 14.x Declarative routing, browser URL synchronizer, deep linking for dose alerts and magic links.
Encrypted Database drift + sqlcipher_flutter_libs Type-safe reactive SQLite interface with AES-256 transparent database encryption at rest.
Secure Vault flutter_secure_storage OS-native credential storage: Apple Keychain, Android EncryptedSharedPreferences, Windows Credential Manager, Linux Secret Service.
Backend & Identity Supabase (PostgreSQL + RLS + GoTrue) Built-in passwordless authentication, OAuth provider support, Row-Level Security, Edge Functions.
Recipe Scraping Dart html parser + Supabase Edge Node Client-side parsing of application/ld+json Schema.org/Recipe with cloud fallback for bot-protected sites.
Platform Health Sync health package (Mobile) + OAuth REST (Web/Desktop) Unified interface isolating native HealthKit/Health Connect from cross-platform desktop/web code.
Push Notifications flutter_local_notifications Cross-platform offline-scheduled alerts for injections and hydration checks.

4. Multiplatform UX/UI Adaptation Engine

The UI layer implements an Adaptive Design Strategy rather than a lowest common denominator approach:

                        ┌────────────────────────────────────┐
                        │      Platform Theme Director       │
                        └─────────────────┬──────────────────┘
                                          │
                  ┌───────────────────────┴───────────────────────┐
                  ▼                                               ▼
      [Apple: iOS & macOS]                            [Material: Android, Web, Win]
┌─────────────────────────────────┐               ┌─────────────────────────────────┐
│        Cupertino Engine         │               │        Material 3 Engine        │
│ • CupertinoNavigationBar        │               │ • NavigationRail / NavigationBar│
│ • CupertinoSliverRefreshControl │               │ • FloatingActionButtons         │
│ • SF Pro System Typography      │               │ • Roboto / Adaptive Font Scaler │
│ • Haptic Feedback & Swipe-Back  │               │ • Dynamic Color / ColorScheme   │
└─────────────────────────────────┘               └─────────────────────────────────┘

Breakpoint Matrix

  • Compact (< 600dp - Mobile): Bottom CupertinoTabBar or NavigationBar. Full-screen sheets for dose logging.
  • Medium (600dp - 1024dp - Foldables / Tablets): Persistent navigation rail, split-view list/detail pane for recipe browsing and pantry audits.
  • Expanded (> 1024dp - Desktop / Web): Multi-column dashboard, persistent sidebar navigation rail, keyboard shortcuts (e.g., Cmd/Ctrl + N for quick food logging), modal popovers rather than full-screen sheets.

4.7 Phase 3B: Platform Health Integrations & HealthGateway Architecture

4.7.1 System Overview

The HealthGateway subsystem provides an abstracted, platform-agnostic bridge between application domains (Nutrition, Biometrics, Exercise) and external health telemetry ecosystems. It decouples high-level clinical metric analysis from platform-specific APIs (Apple HealthKit, Google Health Connect, Samsung Health) and external enterprise standards (SMART on FHIR), ensuring full cross-platform stability across iOS, Android, macOS, Windows, and Web.

                                 ┌──────────────────────────────────┐
                                 │       IHealthGateway (Core)      │
                                 └─────────────────┬────────────────┘
                                                   │
         ┌─────────────────────────┬───────────────┴────────────────┬────────────────────────┐
         │ (iOS / macOS)           │ (Android)                      │ (Cloud / Enterprise)   │ (Windows / Web)
         ▼                         ▼                                ▼                        ▼
┌──────────────────┐     ┌──────────────────┐             ┌──────────────────┐     ┌──────────────────┐
│  Apple HealthKit │     │  Health Connect  │             │  SMART on FHIR   │     │  Local Fallback  │
│  - Weight (lbs)  │     │  & Samsung Health│             │  OAuth2 / REST   │     │  - Manual inputs │
│  - Active Energy │     │  - Weight (lbs)  │             │  - HbA1c panels  │     │  - Local SQLite  │
│  - Blood Glucose │     │  - Active Burn   │             │  - Lipid markers │     │    persistence   │
└──────────────────┘     └──────────────────┘             └──────────────────┘     └──────────────────┘

4.7.2 Core Gateway Contracts & Data Payloads

// lib/core/platform/health_gateway.dart

import 'dart:io';
import 'package:flutter/foundation.dart';

enum HealthProviderType {
  appleHealth,
  healthConnect,
  samsungHealth,
  enterpriseFhir,
  manualFallback,
}

enum HealthConnectionStatus {
  notConfigured,
  permissionDenied,
  connected,
  unsupportedPlatform,
}

class HealthDataPayload {
  final double? weightLbs;
  final double? activeCaloriesToday;
  final double? bloodGlucoseMgDl;
  final DateTime timestamp;
  final HealthProviderType source;

  const HealthDataPayload({
    this.weightLbs,
    this.activeCaloriesToday,
    this.bloodGlucoseMgDl,
    required this.timestamp,
    required this.source,
  });
}

abstract class IHealthGateway {
  /// Verifies current OS entitlement and read permissions.
  Future<HealthConnectionStatus> checkStatus(HealthProviderType provider);

  /// Triggers native OS permission request prompt.
  Future<bool> requestAuthorization(HealthProviderType provider);

  /// Queries biometrics aggregated across the current calendar day.
  Future<HealthDataPayload?> fetchLatestBiometrics();

  /// Revokes active session bindings or tears down local connections.
  Future<void> disconnect(HealthProviderType provider);
}

4.7.3 Platform Support & Fallback Strategy

Target Platform Health Provider Bridge Mechanism / Fallback
iOS Apple HealthKit Native package:health querying HKQuantityTypeIdentifierBodyMass, HKQuantityTypeIdentifierActiveEnergyBurned, HKQuantityTypeIdentifierBloodGlucose.
Android Health Connect androidx.health.connect.client routing both Google Pixel and Samsung Health sensor feeds via Health Connect runtime.
Windows / macOS Local Mock / Manual DB Driver Native SDKs bypassed via `kIsWeb
Web Web Storage Fallback Direct Supabase cloud-synced biometrics and manual modal logging; SDK initialization omitted.
Enterprise Cloud SMART on FHIR Headless OAuth2 code grant returning standardized HL7 FHIR Observation bundles (HbA1c, metabolic panels, weight).

4.7.4 Native Entitlements & Manifest Configurations

Android (android/app/src/main/AndroidManifest.xml)
<!-- Declare Health Connect integration and permissions -->
<manifest xmlns:android="[http://schemas.android.com/apk/res/android](http://schemas.android.com/apk/res/android)">
    <queries>
        <package android:name="com.google.android.apps.healthdata" />
        <intent>
            <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
        </intent>
    </queries>

    <uses-permission android:name="android.permission.health.READ_WEIGHT"/>
    <uses-permission android:name="android.permission.health.READ_ACTIVE_CALORIES_BURNED"/>
    <uses-permission android:name="android.permission.health.READ_BLOOD_GLUCOSE"/>

    <application>
        <!-- Activity-alias for Health Connect permissions rationale -->
        <activity-alias
            android:name="ViewPermissionUsageActivity"
            android:targetActivity=".MainActivity"
            android:exported="true"
            android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
            <intent-filter>
                <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
                <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
            </intent-filter>
        </activity-alias>
    </application>
</manifest>
iOS (ios/Runner/Info.plist)
<key>NSHealthShareUsageDescription</key>
<string>GLP-1 Companion uses read-only HealthKit data to track lean body mass trends, active caloric expenditure, and glycemic markers alongside your dosing schedule.</string>
<key>NSHealthUpdateUsageDescription</key>
<string>GLP-1 Companion records weight and dose timings into Apple Health to keep clinical history synchronized.</string>

4.7.5 Security, Authorization & Key Management

  1. Zero Raw Token Exposure: Enterprise SMART on FHIR refresh and access tokens are held exclusively in hardware-backed storage (flutter_secure_storage utilizing Android Keystore and Apple Keychain).
  2. Read-Only Minimal Principle: Scopes requested from HealthKit and Health Connect are strictly restricted to read permissions for weight, blood glucose, and active burn to maximize user trust and prevent third-party telemetry leakage.
  3. Local Encryption at Rest: Any synced telemetry data cached locally is stored inside the SQLCipher-encrypted SQLite database (glp1_encrypted.db), keyed by the hardware-derived master key managed by CryptoManager.

4.8 Phase 3C: Nutritional Search Engine, Barcode Scanning & Dual-Source Food Cache

4.8.1 Subsystem Overview

The Food Ingestion subsystem bridges cloud product databases with encrypted local storage (FoodProductsTable in Drift SQLCipher). To defend against rate-limiting, missing products, and non-profit server downtime (e.g., Open Food Facts 503 limits), the ingestion engine implements a deterministic multi-tier resolution ladder:

  1. L1 Local Cache: Encrypted SQLite query by exact barcode or tokenized substring.
  2. L2 Packaged Foods Primary (Open Food Facts): REST API v3 queries identifying branded packaged items with a strict custom User-Agent and a 4-second timeout.
  3. L3 Whole & Unbranded Foods Fallback (USDA FoodData Central): Automated fallback querying Foundation, SR Legacy, and Survey databases for generic items, unbranded raw foods, or failed L2 lookups.
  4. L4 Manual Ingestion: Client-side fallback modal allowing user-defined product creation and instant SQLCipher persistence.
       ┌────────────────────────┐         ┌────────────────────────┐
       │   Text Query Search    │         │  Mobile Barcode Scan   │
       │ ("string cheesestick") │         │    (EAN-13, UPC-A)     │
       └───────────┬────────────┘         └───────────┬────────────┘
                   │                                  │
                   ▼                                  ▼
       ┌───────────────────────────────────────────────────────────┐
       │                 IFoodSearchRepository                     │
       └─────────────────────────────┬─────────────────────────────┘
                                     │
           ┌─────────────────────────┼─────────────────────────┐
           ▼ (1. Check Cache)        ▼ (2. Primary Query)      ▼ (3. Auto Fallback)
┌─────────────────────┐    ┌─────────────────────┐    ┌─────────────────────┐
│ Local Drift Cache   │    │ Open Food Facts API │    │ USDA FoodData API   │
│ (SQLCipher AES-256) │    │ (Branded / Barcode) │    │ (Whole/Raw/Fallback)│
└──────────┬──────────┘    └──────────┬──────────┘    └──────────┬──────────┘
           │ (Hit)                    │ (Success)                │ (Success)
           │                          └────────────┬─────────────┘
           │                                       │ (Write Through Cache)
           ▼                                       ▼
┌───────────────────────────────────────────────────────────────────────────┐
│                          Normalized FoodProduct                           │
│     (UPC, Name, Brand, Serving, Calories, Protein, Carbs, Fat, Fiber)     │
└─────────────────────────────────────┬─────────────────────────────────────┘
                                      │
           ┌──────────────────────────┴──────────────────────────┐
           ▼                                                     ▼
┌──────────────────────────────────────┐      ┌──────────────────────────────────────┐
│       Log to Daily Nutrition         │      │        Add to Pantry Inventory       │
│  (Inserts into FoodLogsTable)        │      │  (Inserts into PantryItemsTable)     │
└──────────────────────────────────────┘      └──────────────────────────────────────┘

4.8.2 Domain Model & Contracts

// lib/features/nutrition/domain/entities/food_product.dart

class FoodProduct {
  final String id;
  final String? barcode;
  final String productName;
  final String? brand;
  final double servingSizeGrams;
  final String servingSizeUnit;
  final double calories;
  final double proteinGrams;
  final double carbsGrams;
  final double fatGrams;
  final double? fiberGrams;
  final double? sodiumMg;
  final String? imageUrl;
  final DateTime lastUpdated;

  const FoodProduct({
    required this.id,
    this.barcode,
    required this.productName,
    this.brand,
    required this.servingSizeGrams,
    this.servingSizeUnit = 'g',
    required this.calories,
    required this.proteinGrams,
    required this.carbsGrams,
    required this.fatGrams,
    this.fiberGrams,
    this.sodiumMg,
    this.imageUrl,
    required this.lastUpdated,
  });
}

4.8.3 Persistence Schema (FoodProductsTable)

// lib/core/database/tables/food_products_table.dart

import 'package:drift/drift.dart';

class FoodProductsTable extends Table {
  TextColumn get id => text()(); // UPC barcode or prefixed UUID ('usda_12345')
  TextColumn get barcode => text().nullable()();
  TextColumn get productName => text()();
  TextColumn get brand => text().nullable()();
  RealColumn get servingSizeGrams => real().withDefault(const Constant(100.0))();
  TextColumn get servingSizeUnit => text().withDefault(const Constant('g'))();
  RealColumn get calories => real()();
  RealColumn get proteinGrams => real()();
  RealColumn get carbsGrams => real()();
  RealColumn get fatGrams => real()();
  RealColumn get fiberGrams => real().nullable()();
  RealColumn get sodiumMg => real().nullable()();
  TextColumn get imageUrl => text().nullable()();
  DateTimeColumn get lastUpdated => dateTime()();

  @override
  Set<Column> get primaryKey => {id};
}

4.8.4 Data Source Specifications & Nutrient Mapping

Nutrient Metric Open Food Facts Nutriments Key USDA FoodData Central Nutrient ID Normalization Rule
Energy (Calories) energy-kcal_serving / energy-kcal_100g 1008 (Energy) Expressed as kcal (double).
Protein proteins_serving / proteins_100g 1003 (Protein) Grams per serving (double).
Carbohydrates carbohydrates_serving / carbohydrates_100g 1005 (Carbohydrate, by difference) Grams per serving (double).
Total Fat fat_serving / fat_100g 1004 (Total lipid) Grams per serving (double).
Dietary Fiber fiber_serving / fiber_100g 1079 (Fiber, total dietary) Grams per serving; nullable.
Sodium sodium_serving / sodium_100g 1093 (Sodium, Na) Converted to mg (OFF returns grams; multiply by 1000).

4.8.5 Network & Resiliency Rules

  1. Mandatory User-Agent: All HTTP requests to Open Food Facts must include:
    User-Agent: GLP1Companion-App/1.0 (contact: mtkell@kellengineering.com; platform: Flutter)
    
    Anonymous or default CLI user-agents will trigger upstream proxy 503 throttling.
  2. Circuit Timeout: Remote calls to Open Food Facts enforce a 4-second timeout. Upon timeout or HTTP 5xx error, the client transparently routes the query to UsdaFdcClient.
  3. Write-Through Local Caching: Every successfully resolved remote payload from OFF or USDA FDC is written into FoodProductsTable with insertOnConflictUpdate. Subsequent lookups for identical barcodes or query tokens resolve locally with zero network I/O.

4.9 Phase 4B: Private Recipe Integration (Mealie REST API Client)

4.9.1 Subsystem Overview

The Private Recipe Provider subsystem allows connecting authenticated, self-hosted recipe platforms (initially Mealie v1.x) to ingest recipes into the encrypted local SQLite database.

 ┌────────────────────────────────────────────────────────┐
 │                   Settings Screen                      │
 │    - Base URL: [https://mealie.kellfamilyhome.com](https://mealie.kellfamilyhome.com)       │
 │    - API Token: Bearer <Encrypted Hardware Keystore>   │
 └───────────────────────────┬────────────────────────────┘
                             │
                             ▼
 ┌────────────────────────────────────────────────────────┐
 │                 MealieApiClient                        │
 │    - GET /api/recipes (Paginated summary & slug)       │
 │    - GET /api/recipes/{slug} (Full ingredients/macros) │
 └───────────────────────────┬────────────────────────────┘
                             │
                             ▼
 ┌────────────────────────────────────────────────────────┐
 │             Normalized Recipe Domain Entity            │
 │    - Nutrition: calories, protein, carbs, fat          │
 │    - Source tag: 'mealie'                              │
 └───────────────────────────┬────────────────────────────┘
                             │
                             ▼
 ┌────────────────────────────────────────────────────────┐
 │           RecipesTable (Drift SQLCipher)               │
 │           Appears natively in /recipes tab             │
 └────────────────────────────────────────────────────────┘

4.9.2 Data Contracts & Mealie Normalization

  • Endpoint Structure:
    • Listing: GET {baseUrl}/api/recipes?perPage=-1 returns all user recipes.
    • Details: GET {baseUrl}/api/recipes/{slug} returns full structured steps, ingredient notes, and nutrition object (calories, proteinContent, carbohydrateContent, fatContent).
    • Image Asset: {baseUrl}/api/media/recipes/{recipeId}/images/min-original.webp
  • Security:
    • Server Base URL is stored in Drift settings/preferences.
    • API Token is persisted exclusively in FlutterSecureStorage (Android Keystore / Apple Keychain / Windows DPAPI).

5. Security & Passwordless Authentication Architecture

Password-based login is explicitly deprecated to eliminate credential-stuffing vectors and streamline onboarding.

User Device                Supabase Auth Gateway               OAuth Identity Provider
    │                                │                                    │
    ├─── Selects Provider ───────────┼───────────────────────────────────>│ (Apple / Google / MS)
    │    (Apple/Google/Microsoft)    │                                    │
    │<── Returns Auth Token/Nonce ───┼────────────────────────────────────┤
    │                                │                                    │
    ├─── Exchange Nonce / Verify ───>│                                    │
    │<── Issue JWT + Refresh Token ──┤                                    │
    │                                │                                    │
    │─── Or Request Magic Link ─────>│                                    │
    │    (Email OTP / Deep Link)     ├───── Dispatches Secure Link ──────>│ (User Email Box)
    │<── Deep Link Activated ────────┤                                    │
    │                                │                                    │
    └─── Store Session in Keychain ──┴────────────────────────────────────┘

Zero-Knowledge Local Storage Scheme

Local encryption relies on a three-tier lifecycle:

  1. On initial app bootstrap, a cryptographic salt and 256-bit AES master key are generated via core/security/crypto_manager.dart.
  2. The master key is committed directly to the platform hardware vault.
  3. The SQLCipher SQLite instance initializes using this hardware-backed key.

Platform vault targets:

  • iOS / macOS: Apple Keychain Services (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)
  • Android: Android KeyStore backing EncryptedSharedPreferences (AES-256 GCM)
  • Windows: Windows Data Protection API (DPAPI / Credential Manager)
  • Web: Ephemeral in-memory key unlocked by biometric WebAuthn / session credentials

SQLCipher database initialization parameters:

PRAGMA key = 'x2C5D8F91B4E6A30C8D7E1F2A5B8C0D3E...';
PRAGMA cipher_page_size = 4096;
PRAGMA kdf_iter = 256000;
PRAGMA cipher_hmac_algorithm = HMAC_SHA512;

6. Pharmacokinetics & GLP-1 Tracking Engine

The medication feature models drug serum concentration to deliver realistic physiological insights rather than simple calendar alarms.

Half-Life Modeling Formulation

Active serum levels are calculated using standard single-compartment open pharmacokinetic decay curves:

C(t) = \sum_{i=1}^{n} D_i \cdot \left(\frac{1}{2}\right)^{\frac{t - t_i}{t_{1/2}}}

Where:

  • D_i = Dose administered at timestamp t_i (mg)
  • t_{1/2} = Elimination half-life of compound:
    • Semaglutide (Ozempic / Wegovy): \approx 168\text{ hours (7 days)}
    • Tirzepatide (Mounjaro / Zepbound): \approx 120\text{ hours (5 days)}
    • Liraglutide (Saxenda): \approx 13\text{ hours}
  • t = Current evaluation timestamp

Injection Site Rotation Matrix

To prevent lipohypertrophy, injection events map to a 12-quadrant anatomical topological matrix:

  • Abdomen: Right Upper, Right Lower, Left Upper, Left Lower
  • Thighs: Right Anterior/Lateral, Left Anterior/Lateral
  • Upper Arms: Right Tricep/Lateral, Left Tricep/Lateral

Rotation alerts automatically flag and suggest the least recently utilized site.


7. Recipe Parsing & Smart Pantry Delta Engine

               ┌────────────────────────────────────────────────────────┐
               │           Web Scraping Pipeline (Recipes)              │
               └───────────────────────────┬────────────────────────────┘
                                           │
             1. Fetch HTML Document ───────┴───────> 2. Query <script type="application/ld+json">
                                                                │
                                                    Found Valid Schema.org/Recipe?
                                                     ├── YES ──> Parse Ingredients & Macros
                                                     └── NO  ──> Trigger Edge LLM Regex Fallback
                                                                │
                                                                ▼
                                                   [Parsed Recipe Entity]
                                                   - Title & Yield
                                                   - Ingredient List & Units
                                                   - Protein / Carb / Fat Counts
                                                                │
                                                                ▼
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                Smart Pantry Delta Generator                                    │
│                                                                                                │
│   [Weekly Meal Plan]                    [Active Pantry Inventory]      [Shopping List Engine]  │
│   • 800g Chicken Breast  ─── Compare ──> • 300g Chicken Breast  ──────> • Add 500g Chicken     │
│   • 4 Avocados           ─── Compare ──> • 4 Avocados           ──────> • Item Satisfied (0)   │
│   • 100g Greek Yogurt    ─── Compare ──> • Empty                ──────> • Add 100g Greek Yog.  │
└────────────────────────────────────────────────────────────────────────────────────────────────┘

8. Cross-Platform Health Data Integration (HealthGateway)

Cross-platform parity requires an abstract interface with decoupled implementations:

// lib/core/platform/health_gateway.dart
abstract class IHealthGateway {
  Future<bool> requestPermissions();
  Future<List<BiometricEntry>> fetchWeightHistory({required DateTime start, required DateTime end});
  Future<List<ExerciseEntry>> fetchWorkouts({required DateTime start, required DateTime end});
  Future<void> pushNutritionalIntake({required NutritionalRecord record});
  Stream<BiometricEntry> get realTimeWeightStream;
}

Implementation Matrix

  1. iOS (health_gateway_apple.dart): Wraps HealthKit (HKQuantityTypeIdentifierBodyMass, HKQuantityTypeIdentifierActiveEnergyBurned).
  2. Android (health_gateway_android.dart): Wraps Health Connect API (WeightRecord, ExerciseSessionRecord).
  3. Desktop / Web (health_gateway_cloud.dart): Communicates with cloud partner REST endpoints (MyFitnessPal API, Withings API, Google Fit REST) via OAuth token grants, falling back to manual entry dialogs.

9. Error Handling, Telemetry & Extensibility Architecture

Functional Error Handling

The codebase bans throwing unhandled raw exceptions across layer boundaries. All use-cases return a functional Result<T, Failure> union pattern (fpdart / freezed):

typedef AsyncResult<T> = Future<Either<Failure, T>>;

Modular Plugin Registration (Open-Closed Principle)

To support post-launch capabilities (e.g., continuous glucose monitor [CGM] Bluetooth LE integration, Telehealth lab panels), the app exposes a modular plugin registry:

abstract class ICompanionPlugin {
  String get pluginId;
  String get displayName;
  Future<void> initialize(ProviderContainer container);
  List<RouteBase> get pluginRoutes;
  Widget buildDashboardWidget(BuildContext context);
}

Plugins declare isolated database tables, register their own routes into GoRouter, and inject dashboard summary tiles without altering the core application codebase.