--- name: google-platform-integration description: Guide therefore Google account integration, OAuth authentication flows, vault-gated credential handling, Gmail or Calendar or Contacts API work, multi-account behavior, scope changes, and related Tauri command updates. Use when working in `src/features/google/`, Google-aware mail/calendar/contacts code, `components/modules/settings/providers/AccountProvider*`, or backend Google auth/domain files under `src-tauri/src/commands/` and `src-tauri/src/services/google_auth_service*`. --- # Google platform integration ## Mission Keep therefore's Google integration aligned across frontend auth orchestration, backend-owned Google API access, and vault-protected credential storage. Preserve these product contracts: - Raw Google access tokens do not cross the IPC boundary in production builds. Frontend code uses metadata snapshots only. - Desktop token reads and writes are vault-gated. - Feature modules import the Google auth facade, not the state machine or vault flow directly. - Tasks are local-only. There is no active Google Tasks API integration. ## Start here 1. Read the authoritative docs before editing: - `docs/architecture/google-platform-integration.md` - `docs/technical/capability-contracts.md` - `docs/testing/google-oauth-verification-plan.md` - `src/features/google/README.md` 2. Map the change to the owning layer before touching code. 3. Check current code paths, not just docs. If docs and code disagree, follow code for immediate correctness and update the docs in the same change. 4. Treat multi-account stability, vault behavior, and token ownership as high-risk invariants. ## Layer map ### Frontend auth layers 1. `src/features/google/unifiedAuthService.ts` Public facade for feature modules. Prefer `unifiedGoogleAuth`. 2. `src/features/google/unifiedAuthStateMachine.ts` Singleton that drives PKCE, browser launch, callback handling, code exchange, migration, and token snapshot access. 3. `src/features/google/unifiedAuthVaultFlow.ts` Vault unlock, create, lock, reset, password change, and recovery flow. Desktop-only branches must stay behind `isTauriRuntime()`. 4. `src/features/google/unifiedAuthPkceFlow.ts` and `src/features/google/unifiedAuthPkceSession.ts` PKCE session lifecycle, storage, timeout, and validation. 5. `src/features/google/unifiedAuthApi.ts` The only frontend IPC layer for Google auth and vault commands. Use `safeInvoke` for writes and `safeInvokeReadOnly` for reads. 6. `src/features/google/unifiedAuthTypes.ts` Canonical types, Google auth error classes, and Google scope constants. 7. `src/features/google/unifiedAuthVaultFlow.ts` and `src/features/google/unifiedAuthTypes.ts` Auto-unlocked saved-credentials compatibility shim plus auth/vault error types. ### Backend ownership - `src-tauri/src/services/google_auth_service.rs` Owns token refresh and auth lifecycle helpers. - `src-tauri/src/services/google_auth_service/account_lifecycle.rs` Reuses an existing refresh token when a re-auth response omits `refresh_token`. - `src-tauri/src/commands/unified_google.rs` OAuth start and exchange plus loopback plumbing. Redirects use `http://127.0.0.1:{port}`, not `localhost`. - `src-tauri/src/commands/google_calendar.rs` Calendar domain command surface on top of shared auth helpers. - `src-tauri/src/services/gmail/message_service_simple/` Central Gmail API ownership. Commands delegate here for refresh and rate-limit handling. - `src-tauri/src/services/encrypted_secrets_store/` AES-256-GCM + Argon2id encrypted vault with rolling backup support. ### Related feature modules - `src/features/mail/` Gmail UI and data helpers. Renderer code must not refresh tokens or use a direct HTTP Gmail transport for mutations. - `src/features/calendar/` Calendar sync, views, timeblocks, and tasks rail display. Task timeblocks are calendar projections, not Google Tasks API data. - `src/features/contacts/` Google People or Contacts fetch, SQLite cache, frequency tracking, and compose autocomplete. - `src/features/tasks/` Local-only SQLite tasks. Do not treat this as a Google integration surface. ## Hard boundaries - Never bypass `vaultFlow.withVault(...)` for desktop token operations. - Never import `unifiedAuthStateMachine.ts` or `unifiedAuthVaultFlow.ts` from mail, calendar, contacts, or other feature modules. - Never call Tauri commands directly from feature modules. Route them through `unifiedAuthApi.ts`. - Never move raw access tokens into renderer state, persisted stores, or feature-level caches. - Never add Google Tasks scopes or Tasks API calls to active auth flows. - Never reset the active Mail or Calendar account implicitly during re-auth or scope extension. ## Workflows ### Changing OAuth or vault flow 1. Start at the public boundary: - `unifiedAuthService.ts` - `unifiedAuthStateMachine.ts` - `unifiedAuthVaultFlow.ts` - `unifiedAuthApi.ts` 2. Preserve these invariants: - Validate PKCE session state before code exchange. - Log and ignore stale or duplicate callbacks instead of crashing the flow. - Keep loopback redirect handling on `127.0.0.1`. - Treat `VaultPasswordCancelledError` as a graceful exit, not a fatal crash. - Keep migration calls idempotent via `runMigration()` during initialize paths when storage shape changes. 3. Audit both frontend and backend when auth semantics change. Do not patch only one side of the boundary. ### Changing Gmail, Calendar, or Contacts behavior 1. Keep feature modules on the facade or existing bridge surfaces. 2. Put new Google API ownership in the backend service or command layer, not in the renderer. 3. For Gmail changes, prefer the existing message service under `src-tauri/src/services/gmail/message_service_simple/`. 4. For Calendar changes, keep task timeblock behavior framed as Calendar integration. 5. For Contacts changes, preserve SQLite cache and frequency-tracking behavior. ### Changing scopes or account-selection behavior 1. Add new scopes to `GOOGLE_SCOPES` in `unifiedAuthTypes.ts`. 2. Only add a scope to `getAllDefaultScopes()` when the feature truly requires it during first sign-in. 3. Keep incremental scope extension aligned with `components/modules/settings/providers/AccountProvider*` and `src/features/settings/googleScopes.ts`. 4. Preserve active account IDs for Mail and Calendar across permission extensions and re-auth. 5. Confirm new scopes are declared in both frontend descriptors and backend allowlists. ### Changing Tauri command surfaces 1. Add or adjust the command in `src-tauri/src/commands/`. 2. Add or adjust the frontend call in `src/features/google/unifiedAuthApi.ts`. 3. Keep the command thin and delegate Google API logic to the backend service layer. 4. Update typed errors or request or response shapes in `unifiedAuthTypes.ts` when the frontend contract changes. ## Current drift and open gaps to verify intentionally - `src/features/google/unifiedAuthTypes.ts` still defines `GOOGLE_SCOPES.TASKS` and `GOOGLE_SCOPES.TASKS_READONLY`, but `getAllDefaultScopes()` no longer includes `GOOGLE_SCOPES.TASKS`. Treat any future attempt to re-add Tasks to the default auth flow as intentional scope expansion that must be justified against the local-only Tasks architecture, not as restoring old behavior. - `forceConsent` is a convention, not a guarded invariant. New auth entry points can accidentally churn refresh tokens if they force consent by default. - Incremental auth exists in the Settings account flow, but the architecture backlog still calls out broader incremental-scope guidance as incomplete. - Playwright or E2E OAuth coverage is still incomplete. Do not claim full end-to-end auth coverage without adding it. - Vault-only security assertions and background refresh scheduler consolidation are still listed as open work in the architecture doc. ## Verification Use the narrowest commands that cover the touched Google surface. - Frontend auth flow: - `npx vitest run tests/unifiedAuthService.test.ts src/features/google/unifiedAuthPkceFlow.test.ts src/features/google/__tests__/unifiedAuthVaultFlow.test.ts` - Workspace persistence or account-selection behavior: - `npx vitest run tests/googleWorkspaceStorage.test.ts tests/googleWorkspacePersistence.test.ts src/features/settings/state/googleWorkspaceAccountMutations.test.ts src/features/settings/__tests__/googleWorkspacePreferences.test.ts` - AccountProvider or scope-selection changes: - `npx vitest run tests/unifiedAuthService.test.ts tests/googleWorkspaceStorage.test.ts` - Rust auth backend: - `cargo test google_auth --manifest-path src-tauri/Cargo.toml` - `cargo test GoogleAuthService --manifest-path src-tauri/Cargo.toml` - Contacts backend: - `cargo test contacts --manifest-path src-tauri/Cargo.toml` Run `npm run type-check` when the change touches TypeScript-facing contracts. Update the architecture doc or verification plan in the same slice when behavior or required checks change.