Skip to content

feat: S1 — Live API ephemeral token endpoint - #30

Merged
anchildress1 merged 4 commits into
mainfrom
feat/s1-voice-token-endpoint
Jun 11, 2026
Merged

anchildress1 merged 4 commits into
mainfrom
feat/s1-voice-token-endpoint

Conversation

@anchildress1

Copy link
Copy Markdown
Owner

What 🎫

Implements S1 from docs/v2-implementation-checklist.md (R2 in docs/v2-voice-requirements.md): the existing Cloud Run server mints short-lived Gemini Live API ephemeral tokens so the browser can open the Oracle's voice session without ever seeing the long-lived key.

How

  • POST /api/voice/token → authTokens.create on v1alpha (@google/genai 2.8.0)
  • Token policy: single-use, 60s connect window, 30min session cap, locked to the Live model via liveConnectConstraints
  • LIVE_MODEL lives in shared src/lib/voice/config.ts — S2's client must connect with the same constant the token locks
  • Key never leaks: response body is exactly { token }; error logs masked through the one exported maskApiKey (no second copy of the secrecy rule)
  • Abuse guard: in-memory fixed windows — 10 mints/min per session, 60/min global per instance; 429 + retry-after; denied requests never reach the SDK; global trips warn once per window
  • Failures are loud for operators (masked stack) and generic for clients (503); game stays fully playable on buttons

Decisions ⚖️

  • Live model pinned to gemini-3.1-flash-live-preview (current per June 2026 docs) — single swappable constant; S2 validates at first real connect alongside the Gacrux/Kore voice question
  • Voice + system instruction deliberately NOT locked server-side — S2 owns persona client-side
  • /debug stream tee deferred to S2: DebugEvent.part is turn-scoped today; the voice debug taxonomy gets designed once with S2's event contract
  • CHANGELOG.md added to .prettierignore — Release Please owns it; format runs kept rewriting its bullet style

Proof ✅

  • make ai-checks exit 0 (format, lint, typecheck, full suite, build)
  • 25 new tests across route + limiter: happy path, key-leak negatives on both response and log channels, SDK failure shapes (Error / stackless Error / non-Error), nameless token, missing key, per-session + global 429s, retry-storm key-burn guard, window expiry/sweep edges
  • Coverage gates added: limiter 100/95, route 90/85; global 97.56% lines / 90.54% branches
  • Reviewed by 4 agents (code, simplifier, silent-failure, test-coverage); both HIGH findings fixed (silent 429s, lossy error log)

🤖 Generated with Claude Code

- drop the duplicate Gemini voice entry now tracked by the v2 voice spec
- drop the cast win animation item from the v2 queue
- check off the global definition-of-done gates shipped with v1

Commit-generated-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Ashley Childress <6563688+anchildress1@users.noreply.github.com>
- add POST /api/voice/token minting single-use v1alpha tokens scoped to the Live model
- keep the long-lived key out of every response and log; reuse the debug-log mask as the
  single masking implementation
- guard against key burn with fixed-window limits: 10/min per session, 60/min global
- warn once per window on global exhaustion so abuse is visible without log flooding
- share the Live model constant so the client connects with what the token locks
- cover mint, leak, failure, and limiter paths with 39 server tests; gate the limiter at
  100/95 and the route at 90/85 coverage

Generated-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Ashley Childress <6563688+anchildress1@users.noreply.github.com>
- ignore CHANGELOG.md so format runs stop rewriting generated bullet style

Generated-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Ashley Childress <6563688+anchildress1@users.noreply.github.com>
Generated-by: Codex <noreply@openai.com>
Signed-off-by: Ashley Childress <6563688+anchildress1@users.noreply.github.com>
@sonarqubecloud

Copy link
Copy Markdown

@anchildress1
anchildress1 merged commit 8e7430d into main Jun 11, 2026
5 checks passed
@anchildress1
anchildress1 deleted the feat/s1-voice-token-endpoint branch June 11, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant