docs(31-02): complete Google OAuth PKCE plan summary and state updates
This commit is contained in:
parent
4068d3de08
commit
fe65166ecd
3 changed files with 113 additions and 8 deletions
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
- [x] **CLOUD-01**: User gets working AI via Puter.js with zero API keys and no sign-up required
|
||||
- [x] **CLOUD-02**: Puter.js integrated as server-proxied adapter (not browser-direct) with full cost tracking
|
||||
- [ ] **CLOUD-03**: User can sign in via Google OAuth to access Gemini free tier
|
||||
- [x] **CLOUD-03**: User can sign in via Google OAuth to access Gemini free tier
|
||||
- [ ] **CLOUD-04**: System auto-detects installed tools (Hermes, Claude Code, OpenClaw) and pre-fills configuration
|
||||
- [ ] **CLOUD-05**: User can enter API keys for subscription providers during onboarding
|
||||
- [x] **CLOUD-05**: User can enter API keys for subscription providers during onboarding
|
||||
|
||||
### Voice
|
||||
|
||||
|
|
@ -75,9 +75,9 @@
|
|||
| ONBD-07 | Phase 30 | Complete |
|
||||
| CLOUD-01 | Phase 31 | Complete |
|
||||
| CLOUD-02 | Phase 31 | Complete |
|
||||
| CLOUD-03 | Phase 31 | Pending |
|
||||
| CLOUD-03 | Phase 31 | Complete |
|
||||
| CLOUD-04 | Phase 31 | Pending |
|
||||
| CLOUD-05 | Phase 31 | Pending |
|
||||
| CLOUD-05 | Phase 31 | Complete |
|
||||
| ONBD-04 | Phase 32 | Pending |
|
||||
| ONBD-05 | Phase 32 | Pending |
|
||||
| ONBD-06 | Phase 32 | Pending |
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ gsd_state_version: 1.0
|
|||
milestone: v1.5
|
||||
milestone_name: Smart Onboarding + Personal AI Assistant
|
||||
status: executing
|
||||
stopped_at: Completed 31-puter.js-zero-config-cloud/31-01
|
||||
last_updated: "2026-04-03T00:37:39.937Z"
|
||||
stopped_at: Completed 31-puter.js-zero-config-cloud/31-02 (all 3 tasks, 11 tests pass)
|
||||
last_updated: "2026-04-03T00:37:50.371Z"
|
||||
last_activity: 2026-04-03
|
||||
progress:
|
||||
total_phases: 6
|
||||
|
|
@ -76,6 +76,8 @@ Key constraints for v1.5 (established at roadmap):
|
|||
- [Phase 30-hardware-detection-mode-selection]: Hardware probe is non-blocking — wizard step 1 always has an enabled Continue button regardless of probe outcome
|
||||
- [Phase 30-hardware-detection-mode-selection]: Mode save on wizard completion is non-blocking — wrapped in try/catch, defaults to 'both' on failure
|
||||
- [Phase 31-puter.js-zero-config-cloud]: agentId is optional in puterProxyService.chatStream — cost recording skipped when null/undefined to avoid FK violation in cost_events
|
||||
- [Phase 31-puter.js-zero-config-cloud]: pendingPkce stores only verifier (no companyId) — company does not exist at authorize time during onboarding
|
||||
- [Phase 31-puter.js-zero-config-cloud]: pendingTokens pattern: callback parks tokens by stateId, claim endpoint links to real companyId post-company-creation
|
||||
|
||||
### Pending Todos
|
||||
|
||||
|
|
@ -90,6 +92,6 @@ None yet.
|
|||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-04-03T00:37:30.288Z
|
||||
Stopped at: Completed 31-puter.js-zero-config-cloud/31-01
|
||||
Last session: 2026-04-03T00:37:50.368Z
|
||||
Stopped at: Completed 31-puter.js-zero-config-cloud/31-02 (all 3 tasks, 11 tests pass)
|
||||
Resume file: None
|
||||
|
|
|
|||
103
.planning/phases/31-puter.js-zero-config-cloud/31-02-SUMMARY.md
Normal file
103
.planning/phases/31-puter.js-zero-config-cloud/31-02-SUMMARY.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
phase: 31-puter.js-zero-config-cloud
|
||||
plan: "02"
|
||||
subsystem: server/google-oauth
|
||||
tags: [oauth, pkce, google, gemini, api-keys, secrets]
|
||||
dependency_graph:
|
||||
requires: []
|
||||
provides: [googleOAuthService, googleOAuthRoutes, google-oauth-routes]
|
||||
affects: [server/src/app.ts]
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns: [PKCE-S256, pendingTokens-claim-pattern, secretService-upsert]
|
||||
key_files:
|
||||
created:
|
||||
- server/src/services/google-oauth.ts
|
||||
- server/src/routes/google-oauth.ts
|
||||
- server/src/__tests__/31-google-oauth.test.ts
|
||||
modified:
|
||||
- server/src/app.ts
|
||||
decisions:
|
||||
- pendingPkce stores only verifier (no companyId) — company does not exist at authorize time
|
||||
- pendingTokens uses stateId as key — claim endpoint links tokens to companyId post-company-creation
|
||||
- Google token exchange uses fetch (Node built-in) not axios
|
||||
- secretService upsert pattern: getByName -> rotate if exists, create if not
|
||||
metrics:
|
||||
duration: "3 minutes 22 seconds"
|
||||
completed: "2026-04-03T00:36:57Z"
|
||||
tasks_completed: 3
|
||||
files_created: 3
|
||||
files_modified: 1
|
||||
requirements: [CLOUD-03, CLOUD-05]
|
||||
---
|
||||
|
||||
# Phase 31 Plan 02: Google OAuth PKCE Service and Routes Summary
|
||||
|
||||
**One-liner:** Google OAuth PKCE flow for Gemini free tier access — generateAuthUrl/exchangeCode/storeTokens service plus authorize/callback/claim/api-keys routes with in-memory pendingTokens pattern separating callback from company creation.
|
||||
|
||||
## Tasks Completed
|
||||
|
||||
| Task | Name | Commit | Files |
|
||||
|------|------|--------|-------|
|
||||
| 1 | googleOAuthService — PKCE generation, code exchange, token storage | 72045513 | server/src/services/google-oauth.ts |
|
||||
| 2 | googleOAuthRoutes (pendingTokens pattern) + API key route + mount in app.ts | c41ec162 | server/src/routes/google-oauth.ts, server/src/app.ts |
|
||||
| 3 | Unit tests for Google OAuth service and routes | d750d15f | server/src/__tests__/31-google-oauth.test.ts |
|
||||
|
||||
## What Was Built
|
||||
|
||||
### googleOAuthService (`server/src/services/google-oauth.ts`)
|
||||
|
||||
- `generatePkce()` — crypto.randomBytes(32).toString("base64url") verifier, SHA256 base64url challenge
|
||||
- `generateAuthUrl(redirectUri, state)` — builds Google OAuth URL with PKCE S256, Gemini scopes (openid + cloud-platform + generative-language.retriever), access_type=offline, prompt=consent
|
||||
- `exchangeCode(code, redirectUri, verifier)` — POSTs to https://oauth2.googleapis.com/token with authorization_code grant and code_verifier
|
||||
- `storeTokens(companyId, tokens)` — upserts JSON-stringified tokens under name "google_gemini_oauth_token" via secretService
|
||||
- `resolveTokens(companyId)` — retrieves and JSON.parses stored tokens
|
||||
|
||||
### googleOAuthRoutes (`server/src/routes/google-oauth.ts`)
|
||||
|
||||
- `POST /oauth/google/authorize` — assertBoard, generates UUID state, stores PKCE verifier in pendingPkce (NO companyId), returns `{ url, stateId }`
|
||||
- `GET /oauth/google/callback` — exchanges code via pendingPkce verifier, parks tokens in pendingTokens by stateId, redirects to `/?google_oauth=success&state=...`
|
||||
- `POST /oauth/google/claim` — assertBoard + assertCompanyAccess, moves tokens from pendingTokens to secretService under real companyId, returns `{ ok: true }`
|
||||
- `POST /api-keys/store` — assertBoard + assertCompanyAccess, upserts `${provider}_api_key` secret (openai/anthropic/groq), returns `{ ok: true }`
|
||||
- Cleanup of entries older than 10 minutes on each request
|
||||
|
||||
### Test Coverage (`server/src/__tests__/31-google-oauth.test.ts`)
|
||||
|
||||
All 11 tests pass:
|
||||
- Tests 1-2: PKCE generation format and auth URL contents
|
||||
- Test 3: token exchange HTTP call
|
||||
- Tests 4-5: storeTokens create and rotate paths
|
||||
- Test 6: authorize returns { url, stateId } with no companyId
|
||||
- Test 7: callback exchanges code and redirects with success
|
||||
- Test 8: callback with invalid state returns 400
|
||||
- Test 9: full authorize→callback→claim flow
|
||||
- Test 10: claim with missing stateId returns 404
|
||||
- Test 11: api-keys/store upsert
|
||||
|
||||
## Decisions Made
|
||||
|
||||
1. **pendingPkce stores only `{ verifier, createdAt }`** — no companyId stored at authorize time because the company has not been created yet during onboarding step 3. This was the key design requirement.
|
||||
|
||||
2. **pendingTokens pattern** — callback stores tokens in memory by stateId; claim endpoint later links them to a real companyId. This separates the OAuth callback timing from company creation.
|
||||
|
||||
3. **Client ID is public** — `812546505895-ag9nvbqvf8cpqk3mfem1glig0jtl5i31.apps.googleusercontent.com` is the publicly documented Gemini CLI installed-app client_id (per RESEARCH.md). PKCE flow is appropriate for public clients.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None — all functionality is fully wired.
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
Files created:
|
||||
- server/src/services/google-oauth.ts: EXISTS
|
||||
- server/src/routes/google-oauth.ts: EXISTS
|
||||
- server/src/__tests__/31-google-oauth.test.ts: EXISTS
|
||||
|
||||
Commits:
|
||||
- 72045513: feat(31-02): add googleOAuthService with PKCE generation and token management
|
||||
- c41ec162: feat(31-02): add googleOAuthRoutes with pendingTokens pattern and mount in app.ts
|
||||
- d750d15f: test(31-02): add 11 unit tests for Google OAuth service and routes
|
||||
Loading…
Add table
Reference in a new issue