- Worker: run orca-agent-signout (each agent's logout, then credential files) on a running sandbox
before the provider delete; bounded (20 s) and best effort, never blocks the delete.
- Environment builds: scrub agent auth (--scrub-only) before the snapshot; fail closed.
- New VM script registered in VM_SCRIPTS + provision loop; vm-scripts regenerated.
- Main IPC ephemeralVm:forwardedEnvSummary returns names only, grouped by credential-looking.
- P-4 warning component (+ fixture) shown under Settings > recipes; delete dialog line for awake
Orca Cloud sandboxes.
Live on dev the first capture sealed zero sessions: agentSession.subscribeStatus needs a streaming
transport and the unix socket refuses it, and worktree.ps lists only agents live right now. The
collector now reads orcad's own session records (agent-session-journal.db, read-only): provider,
name and last turn, open tabs first; live worktree.ps rows override status; history still comes
from agentSession.history, with the stored last turn as fallback.
- 'Save as personal Cloud secret' is offered, and accepted by main, only for names the egress proxy
swaps (a shared list the control-plane test holds equal to the proxy's); anything else would sit
on the VM in full, so main answers not_swappable.
- SSH launches into an Orca Cloud workspace (orca-* aliases or an 'orca ssh-proxy' ProxyCommand
surfaced through ~/.ssh/config Includes) get no desktop keys.
- Defense in depth on the VM: orcad with ORCA_IS_CLOUD=1 drops a carried keyEnv.
Line items: '{{seats}} x {{price}} per seat, billed yearly' / 'per seat per month'
(plural keys); totals '{{total}} per year' / 'per month'; Worker plan labels
'$50 per seat per month' and '$480 per seat, billed yearly'. Drops /mo, /yr,
/year and /seat/month strings.
- COPILOT_GITHUB_TOKEN on api.github.com: GET /user and GET /copilot_internal/* only (normalized
paths; dot or encoded segments refused); the Copilot API hosts are unchanged. It resolves like
an env variable (personal beats team): it is one person's GitHub identity.
- Routine summaries for opencode (JSON events), cursor (JSON result) and copilot (--silent) are the
agent's final message, and every summary has the session's secret values replaced before it can
be posted as a comment or PR body.
- Webhook/GitHub context in a routine prompt is capped at 48 KiB (compact, then cut), so a prompt
passed as one argv entry stays under Linux's 128 KiB limit.
- A test fails if an agent credential is neither swapped nor marked 'Stored on workspace'.
- COPILOT_GITHUB_TOKEN: placeholder in the VM, swapped on api.github.com (Bearer or token form, next to
the workspace token's own route) and on the Copilot API hosts (left open for Copilot's own session
token). GOOGLE_API_KEY: swapped on generativelanguage.googleapis.com and aiplatform.googleapis.com
(Vertex express). A credential may now route to several hosts.
- Routines accept claude, codex, opencode, gemini, cursor and copilot; the in-VM runner has a
headless command for each (checked against a local stand-in model: prompts starting with '-' stay
prompts). The editor picks the agent from a list.
- AWS_* keys (SigV4, signed in the VM) and Bedrock API keys can't be swapped: the secrets UI marks
them 'Stored on workspace' with the reason, in the list, the .env preview, the effective view and
the editor.
- Gemini's auth method is seeded for GOOGLE_API_KEY too (vertex-ai with GOOGLE_GENAI_USE_VERTEXAI);
headless Gemini refuses to start without one.
Copilot prefers GH_TOKEN/GITHUB_TOKEN over a stored /login. In Orca Cloud those hold the workspace
GitHub App placeholder, so every Copilot start said 'Resource not accessible by integration' and a
user who signed in could never use it. A wrapper drops the two placeholders for Copilot only, unless
BYOK is configured (no GitHub sign-in needed; gh in Copilot's shell keeps working).
* feat(cloud): pdx1 default region with iad1 fallback and one golden per region; Standard is 8 vCPU / 16 GB (U17, U18)
- golden_images and environment_builds record their region (0040, backfilled iad1); rotation,
git-source builds, smoke and activation run per region; lifecycle picks the region's golden.
- New creates default to pdx1; a create with no pinned region falls back to iad1 automatically on a
capacity/provider error (VERCEL_FALLBACK_REGIONS). Until pdx1 has an image, creates use iad1.
- Environment builds boot and smoke in their own region; workspaces from a build boot there.
- One size: Standard = 8 vCPU / 16 GB (ORCA_CLOUD_SANDBOX_SPEC). Legacy 'large' requests map to
standard; 0040 rewrites existing large rows.
* merge cloud/integration (ORCA_CLOUD_SANDBOX_SPEC landed in #196)
Hosts with credential rules (model APIs, api.github.com) are answered by Vercel's egress proxy with a
certificate from its CA. Vercel's command env trusts it (NODE_USE_SYSTEM_CA, NODE_EXTRA_CA_CERTS,
SSL_CERT_FILE) but orcad starts under env -i, so Node clients in terminals used Node's bundled roots:
Gemini CLI retried forever ('This is taking a bit longer') while the same call from a command
returned at once. Found on the live proof of the new agents; NODE_USE_SYSTEM_CA=1 in the terminal
fixed it there (1 s to the provider's answer).
Staging sign-in now works end to end in dev without a dev operator key on the user's machine.
Same account ids as billing dev (which trusts staging already); never honored when SANDBOX_ENV=prod;
a staging key cannot pass as the prod issuer.
Security review: a Copilot BYOK key without a usable base URL (or with one from another scope) had
no route, so it went to the VM as itself. Every swappable name now becomes a placeholder, routed or
not, and the Copilot pair resolves like the other agent keys (shared beats personal, as a pair).
The Cursor exchange reply is parsed whatever its content type and cut down to accessToken; headers
(set-cookie) are not passed. opencode.ai is not allowlisted (anonymous share uploads).
Image: pinned opencode-ai 1.19.5, @google/gemini-cli 0.67.0, @github/copilot 1.0.108 (npm) and
cursor-agent 2026.11.05-86047df (checksummed tarball). opencode's unused linux build variant is
dropped (~205 MB). First-run screens are answered at every boot/secret refresh (folder trust for
Gemini, Cursor and Copilot; Gemini's auth picker when a Gemini key is set; OpenCode's gateway model
from ANTHROPIC_MODEL/OPENAI_MODEL); self-update is off for all four.
Egress: GEMINI_API_KEY / GOOGLE_GENERATIVE_AI_API_KEY (generativelanguage.googleapis.com,
x-goog-api-key), CURSOR_API_KEY (api2.cursor.sh, only POST /auth/exchange_user_api_key; the
refresh token is stripped so nothing long-lived lands on the VM) and COPILOT_PROVIDER_API_KEY /
BEARER_TOKEN (host of COPILOT_PROVIDER_BASE_URL, same scope only) are placeholders in the VM and
swapped by the proxy. Allowlist adds the agents' API and sign-in hosts. API/MCP accept the image's
agents; routines stay on claude/codex.
- local.core-workflow: composer local worktree (Blank Terminal), edit in its terminal, diff in
Source Control and the diff tab, Stage All, commit
- acc.download: Explorer Download… (20 MiB file) and Download as ZIP… (folder) with progress and
success toasts and sha256 checks; only the native Save panel's answer is stubbed in main via the
inspector (W9D_MAIN_INSPECT)
- acc.remote-desktop: workspace menu Open remote desktop -> orcaDesktop connected, noVNC canvas
sampled, a red xterm launched on DISPLAY=:1 shows up; guest screenshots over CDP
- local rows without a host badge count as local
The wake phase "orcad ready" (W9) runs from orcad's spawn to the control plane
having the pairing offer. After orca-sandbox-start exits, the control plane
made a second Vercel round trip (files API, ~120 ms from here) to read the
offer, because command stdout is kept as logs.
startOrcad now passes a fresh 32-byte key per call in env (env is not kept).
The start script adds "sealedOffer": "<iv>.<base64 AES-256-CTR(offer line)>"
to the pointer line it already prints, so the logs only hold ciphertext and
the control plane opens the offer locally. The key is unset first thing in the
script and in the prelude, so nothing the script starts inherits it. If the
offer is missing or does not open (older image, no openssl, wrong key), the
control plane reads the file as before. Older Workers send no key, and
current images then print the plain pointer.
The ready poll in the start script drops from 50 ms to 10 ms (~20 ms mean),
keeping the 60 s minimum timeout.
Verified on a VM from snap_aQmW, driving the start script like the control
plane: all four starts, including an idempotent second start, opened without
the files API, and the stdout never held the pairing code.
NODE_COMPILE_CACHE only stores what V8 compiles before a script runs: 5.4 MB of
orcad-server.js's 15 MB. Every function startup runs still compiled lazily on
every boot. Measured on a VM from golden snap_aQmW, orcad ready went from
0.95-1.06 s to 0.70-0.78 s (5 pairs, alternated), and from ~1.25 s to ~0.95 s
on a slower host.
image/vm/orcad-boot runs orcad-server.js through a vm.Script whose code cache
is taken as the image's smoke run exits, so it covers what startup compiled.
orcad sees the same argv, __filename, require and import() resolution as under
plain node. The cache file starts with a header (Node version, arch, bundle
length and crc32): V8 itself only checks the source length, so a cache from
other bundle bytes would otherwise run stale code. Without a matching cache
orcad loads through require exactly as before.
Verified in that VM: the cache is accepted, the experimental-loader warning
stays out of orcad.log, and a terminal created through the CLI runs (node-pty
resolves via import() from the bundle directory).
Desktop-created cloud workspaces already run setup through orcad's worktree
create after the setup prompt. Workspaces made through createWorkspace use the
VM's primary checkout, which no worktree create touches, so their setup never
ran. Start it detached on create (once per workspace, orcad's env, skipped on
environment builds) and have routine runners wait for it.