mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 18:37:24 +00:00
Codex signs in once via the person's Orca account:
- POST /v1/agent-credentials/codex/broker starts a short-lived broker sandbox (golden image, egress
auth.openai.com + chatgpt.com only, non-persistent, tagged orcaCodexBroker/orcaInfra so the workspace
orphan sweep and billing never see it) running `codex login --device-auth` (Codex 0.166), and returns
{brokerId, verificationUrl, userCode}. GET .../broker/:id -> {status: pending|active|failed}; DELETE
cancels. On completion the Worker reads auth.json through the files API, stores the tokens
envelope-encrypted and Personal-only in agent_credentials, and deletes the broker sandbox.
- Lease refresher (cron, every 5 min): refreshes the access token with the refresh token before expiry,
single-flight per person (D1 lease) with a compare-and-swap write, so a refresh token is spent once and
a delete or new login is never overwritten (no refresh_token_reused). Failures mark expiring/expired
(by the real access-token expiry) or revoked (refresh_token_reused/invalidated). A chatgpt.com 401
triggers a refresh instead of revoking.
- codexAccount AccountProvider: placeholder access token bound to the sandbox id (D14), swapped for the
real one on chatgpt.com with ChatGPT-Account-Id; never in a shared workspace (D13); kill switch
AGENT_ACCOUNTS_CODEX_DISABLED=1.
- VM: orca-sandbox-env writes a placeholder ~/.codex/auth.json (no refresh token) from
ORCA_CODEX_AUTH_PLACEHOLDER, sets a managed HTTPS ChatGPT provider (Codex's Responses WebSocket can't
pass the egress proxy; verified live), and sets a person's own login aside / restores it.
- Migration 0045_codex_broker (codex_broker_sessions, codex_leases; no token columns).
- Flag S2 on in wrangler.dev.jsonc; absent in prod.
40 lines
1.8 KiB
SQL
40 lines
1.8 KiB
SQL
-- Codex account broker (agent-accounts spec A2, contract D11 / flag S2). Additive only.
|
|
-- The credential itself lives in agent_credentials (0044); these tables hold no token.
|
|
|
|
-- One device login in a short-lived broker sandbox. The user code is shown only to its owner and
|
|
-- is useless after `expires_at` (Codex device codes last 15 minutes).
|
|
CREATE TABLE IF NOT EXISTS codex_broker_sessions (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
account_id TEXT NOT NULL,
|
|
provider_name TEXT NOT NULL,
|
|
session_id TEXT,
|
|
status TEXT NOT NULL CHECK (status IN ('starting', 'pending', 'completing', 'active', 'failed')),
|
|
verification_url TEXT,
|
|
user_code TEXT,
|
|
error TEXT,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
expires_at INTEGER NOT NULL,
|
|
-- Set once the broker sandbox is gone; the cron retries deletes until it is.
|
|
destroyed_at INTEGER
|
|
);
|
|
CREATE INDEX IF NOT EXISTS codex_broker_sessions_user ON codex_broker_sessions (user_id, created_at);
|
|
CREATE INDEX IF NOT EXISTS codex_broker_sessions_live ON codex_broker_sessions (destroyed_at, expires_at);
|
|
|
|
-- The refresher's single-flight lease and schedule, one row per person with a Codex credential.
|
|
-- A refresh token is single-use: only the lease holder may spend it (refresh_token_reused otherwise).
|
|
CREATE TABLE IF NOT EXISTS codex_leases (
|
|
user_id TEXT PRIMARY KEY,
|
|
lease_owner TEXT,
|
|
lease_until INTEGER,
|
|
access_expires_at INTEGER,
|
|
refreshed_at INTEGER,
|
|
-- Backoff after a transient failure (the refresher skips the row until then).
|
|
next_attempt_at INTEGER,
|
|
failures INTEGER NOT NULL DEFAULT 0,
|
|
-- An error code from the token endpoint (e.g. refresh_token_expired), never a token.
|
|
last_error TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS codex_leases_due ON codex_leases (access_expires_at);
|