{ "output": "# Phase 3 — App wiring: AppGate + lifecycle hooks\n\n## Objective\nWire `BillingManager`, `DebugBillingOverride`, and `AppGate` into `ServiceBookApplication`. Add billing lifecycle hooks (`startConnection`, `refresh`, `endConnection`) to `MainActivity`. The app should remain functionally unchanged from a user's perspective; gate state propagates but no UI consumes it yet.\n\n## Key Files & Context\n- **New Files**:\n - `app/src/main/java/com/servicebook/domain/AppGate.kt`\n - `app/src/test/java/com/servicebook/domain/AppGateTest.kt`\n- **Modified Files**:\n - `app/src/main/java/com/servicebook/ServiceBookApplication.kt`\n - `app/src/main/java/com/servicebook/MainActivity.kt`\n - `app/src/test/java/com/servicebook/TestServiceBookApplication.kt`\n - `app/src/test/java/com/servicebook/MainActivityTest.kt`\n\n## Implementation Steps\n\n### 1. Centralize read-only state in `AppGate`\n- Create `domain/AppGate.kt`.\n- Inject `VehicleRepository`, `BillingManager`, and a `CoroutineScope`.\n- Expose `isPremium: StateFlow` delegated from `BillingManager`.\n- Expose `isReadOnly: StateFlow` which combines `vehicleRepository.observeVehicles()` and `isPremium`. The read-only rule is: `vehicles.size > 1 && !premium`.\n\n### 2. Register dependencies in `ServiceBookApplication`\n- Update `ServiceBookApplication.kt` to define open lateinit properties for `billingManager`, `debugBillingOverride`, and `appGate`.\n- In `initDependencies()`, initialize `debugBillingOverride`, `DefaultBillingClientProvider`, `BillingManagerImpl`, and `AppGate`. Use `BuildConfig.DEBUG` to conditionally pass the debug override to the `BillingManagerImpl`.\n\n### 3. Wire billing lifecycle in `MainActivity`\n- Update `MainActivity.kt` to cast `application` to `ServiceBookApplication`.\n- Call `application.billingManager.startConnection()` in `onCreate`.\n- Override `onResume` to call `application.billingManager.refresh()`.\n- Override `onDestroy` to call `application.billingManager.endConnection()`.\n\n### 4. Update Test Infrastructure\n- In `TestServiceBookApplication.kt`, initialize `billingManager` as a `FakeBillingManager`, initialize `debugBillingOverride` and `appGate`.\n- Update `MainActivityTest.kt` to use mockk/spies on `FakeBillingManager` to assert that `startConnection`, `refresh`, and `endConnection` are called at the correct lifecycle moments.\n\n### 5. Unit Tests for `AppGate`\n- Create `AppGateTest.kt`.\n- Test the derivation matrix for `isReadOnly`:\n - 0 vehicles, free -> false\n - 1 vehicle, free -> false\n - 2 vehicles, free -> true\n - 0 vehicles, premium -> false\n - 1 vehicle, premium -> false\n - 2 vehicles, premium -> false\n\n## Verification & Testing\n- Ensure `./gradlew test` passes.\n- Verify the app still runs end-to-end identically to before (no paywall UI should be visible yet).\n" }