Commit Graph
252 Commits
Author SHA1 Message Date
Neil 134fc24436 feat(cloud): boot-time orcad refresh so environment and older-image workspaces get VM fixes (ENV-STALE)
Golden source builds publish their orcad + in-VM CLI as a commit-pinned bundle (R2, uploaded by the build VM over a signed PUT; the Worker computes the stored sha256). On every boot and wake, before orcad starts and inside the existing orcad phase, a sandbox whose /opt/orca/runtime/orcad/SOURCE_COMMIT differs from its region's active golden fetches that bundle from the control plane's own host (already on the egress allowlist) with a 10-minute signed URL, verifies the sha256 the control plane passes in, checks the commit and node runtime, and swaps orcad + orca-cli atomically. Any failure keeps the old orcad and boot continues; every outcome is logged (runtime_refresh: outcome, from, to, ms). RUNTIME_REFRESH=off is the kill switch. Dev R2 bucket orca-sandbox-runtime-dev.
2026-11-11 03:21:01 -08:00
Neil 215564db55 fix(cloud): signed-out Claude message matches the strip and glossary (design-squad) 2026-11-11 02:03:47 -08:00
Neil a206be57ef fix(cloud): a signed-out account answers like the provider, not 403 host_not_proxied (W-106)
Once an Orca account stops applying (revoked after a confirmed 401, expired, removed, turned off, shared, owner changed), requests still carrying the sandbox's account placeholder (shells and agents already running, a Vercel forward that hasn't caught up) now get Anthropic's own 401 authentication_error, saying the Orca sign-in for Claude needs renewing, instead of 403 host_not_proxied or a bare deny. Nothing is swapped on those routes.
2026-11-11 01:43:46 -08:00
Neil c1c1cb387f Merge remote-tracking branch 'private/cloud/integration' into cloud/read-snapshot-signed
# Conflicts:
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
#	cloud/apps/sandbox-control/image/vm/orca-sandbox-grant
2026-11-11 00:08:43 -08:00
Neil bfc8849b22 fix(cloud): grant sealer records the device only when the script provides the ledger path 2026-11-10 23:21:47 -08:00
Neil 766e0b23b6 Merge remote-tracking branch 'private/cloud/integration' into cloud/read-snapshot-signed
# Conflicts:
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
#	src/main/ipc/cloud-workspaces.ts
2026-11-10 23:20:55 -08:00
Neil 6a4adaa2dd Merge remote-tracking branch 'private/cloud/integration' into cloud/local-command
# Conflicts:
#	src/main/hosted-sandbox/hosted-sandbox-install.ts
#	src/renderer/src/components/cloud-workspaces/use-cloud-workspaces.ts
#	src/renderer/src/components/settings/orca-cloud/OrcaCloudSettingsLinks.tsx
#	src/renderer/src/components/settings/orca-cloud/OrcaCloudSettingsPanes.tsx
#	src/renderer/src/components/settings/orca-cloud/orca-cloud-settings-search.ts
#	src/renderer/src/hooks/settings-navigation-orca-cloud-sections.ts
#	src/renderer/src/i18n/locales/en.json
#	src/renderer/src/lib/settings-navigation-types.ts
2026-11-10 22:39:07 -08:00
Neil 0217501693 Merge remote-tracking branch 'private/cloud/integration' into cloud/multiplayer-gaps 2026-11-10 21:30:03 -08:00
Neil 39ffbdd862 feat(cloud): MEMBER_REMOVED_TOKEN, a bearer valid only for /v1/internal/org-members/removed
Auth pushes PropelAuth offboarding and Orca-side member removals here (stablyai/orca-cloud#739);
it should not need the full operator token for that. The operator token is still accepted.
2026-11-10 21:08:10 -08:00
Neil d6b3646081 Merge remote-tracking branch 'private/cloud/integration' into cloud/local-command
# Conflicts:
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
#	src/renderer/src/i18n/locales/en.json
2026-11-10 21:04:43 -08:00
Neil 8a2603a68e Merge private/cloud/integration into cloud/multiplayer-gaps (team-presence, routines) 2026-11-10 20:37:56 -08:00
Neil 425ef9c06e Merge pull request #353 from nwparker/create-speed/ja-27
fix(cloud): VM hostname is the workspace name, not the provider's per-boot id (JA-27)
2026-11-10 20:31:26 -08:00
Neil 779e1dbc12 Merge pull request #355 from nwparker/cloud/w3-ports-external-collapsed
fix(w3): hide the sandbox's own services from External ports in cloud workspaces
2026-11-10 20:29:33 -08:00
Neil ed46c5e149 fix(cloud): VM hostname is the workspace's name, not the provider's per-boot id (JA-27, hostname half)
Terminal prompts read ubuntu@<random VM id> and changed after every wake. Each start (create and wake)
now sets the hostname to the workspace's title (else its repo's name) as a hostname label, plus an
/etc/hosts entry, inline before orcad starts: no image change. Verified on a dev VM: hostname ja-hello,
127.0.1.1 ja-hello, no sudo warnings.
2026-11-10 20:28:52 -08:00
Neil 4f9164e599 Merge pull request #343 from nwparker/cloud/routine-home-filter
cloud Home: hide routine runs by default, with a Routine runs filter (G15)
2026-11-10 20:23:56 -08:00
Neil 9dd23dcca1 Merge pull request #336 from nwparker/cloud/team-presence
feat(cloud): teammate profiles (usage heatmap) and opt-in Pokes
2026-11-10 20:15:14 -08:00
Neil 3f5f314efc fix(cloud): local commands — security review fixes
- orcad: only the owner's desktop may attach/settle; devices paired through a grant are listed
  by orca-sandbox-grant and refused (forks keep their offer's origin id)
- desktop: per-workspace limits (3 waiting, 60/hour), always-allow runs one at a time and 30/hour,
  one banner per burst, refusal floods logged once a minute
- dialog: commands over 20 lines refused; long ones must be scrolled to the end; agent name muted;
  Turn off for this workspace; read delay counts from when a prompt reaches the front
- lookalike spaces and combining marks refused; settled events only close their own workspace's prompt
- executor reports soon after the shell exits even if an escaped process holds the pipes; hard stop
- audit log keeps 3 files, long commands stored as prefix + sha256
- rules expire after 30 days and are cleared when a shared workspace is allowed
2026-11-10 20:11:56 -08:00
Neil d029218f18 fix(w3): keep pid-less user listeners visible; hide only declared platform ports
Vercel's sandbox-init listens on 23456 as root (pid invisible to the user); the
VM declares it via ORCA_HOST_MANAGED_UNOWNED_PORTS. Any other pid-less
listener (root-run postgres, Docker-published ports) stays under External.
2026-11-10 20:10:47 -08:00
Neil 0b986f1fc6 fix(w3): hide the sandbox's own services from External ports in cloud workspaces 2026-11-10 20:04:36 -08:00
Neil e4283fd41d fix(cloud-create): Idempotency-Key on create, named rows, and the repository step named once (PC-8 backstop, PC-4)
- POST /v1/sandboxes takes an Idempotency-Key (api_idempotency, 24 h, scoped per account and member):
  the same key and body return the first create's sandbox instead of starting another; same key with a
  different body is a 422. The desktop sends context.idempotencyKey when its caller provides one.
- The desktop sends the workspace name as the create's title, so lists show it, not an untitled row.
- GET /v1/sandboxes/boot-plan?repo= says whether a create would clone or update (environment build);
  the driver asks in parallel with the create, so the build sheet names 'Clone repository' or 'Update
  repository' once, with a placeholder until it knows, and never relabels mid-run.
2026-11-10 19:59:50 -08:00
Neil f2d3af0f74 feat(cloud-home): hide routine runs from Home by default, with a Routine runs filter (G15)
Home's team list leaves routine-run VMs out unless the new Routine runs switch is on. The switch is
offered only when the team has routines, counts the running runs it hides, and is remembered per
account. Hidden runs leave the workspace count but keep their sandbox hours in the total. Listed
runs carry a routine mark and 'Routine · <name>'. Control plane: GET /v1/team/workspaces
?routines=include, plus fromRoutine/routineName per row and a routineRuns summary.
2026-11-10 19:52:58 -08:00
Neil 8f28913dba feat(cloud): W-numbers, org slug links, and pins/order/sections that sync across desktops and the phone (G13, G14) 2026-11-10 19:50:22 -08:00
Neil a098faf917 feat(cloud): TEAMMATE_ACTIVITY_SHARING config (opt_in default | team) for the activity heatmap 2026-11-10 19:49:09 -08:00
Neil d84659983e feat(teammates): share activity only with 'Pokes and activity' on; View profile in Team row menu
Design-squad review of #336: a teammate's heatmap is shown only if they opted in (same
Experimental switch as Pokes, renamed 'Pokes and activity'); otherwise their profile says they
haven't shared it. Your own heatmap always shows. Team rows get 'View profile' first in the menu.
Own-profile hint: 'Hover a day to see your sandbox hours.'
2026-11-10 19:48:34 -08:00
Neil ed270537cf Merge pull request #340 from nwparker/cloud/api-gaps
cloud API + MCP: new chat, cancel, rename, unarchive, attachments, list_models (G10)
2026-11-10 19:40:28 -08:00
Neil d275561e7f feat(cloud-api): sessions, cancel, rename, unarchive, attachments and models in REST + MCP (G10) 2026-11-10 19:26:25 -08:00
Neil b48bbb5f87 Merge remote-tracking branch 'private/cloud/integration' into cloud/team-presence 2026-11-10 19:25:38 -08:00
Neil 28ae29ba2d feat(cloud): teammate profiles with a usage heatmap, and opt-in Pokes
Conductor 0.91 parity. Clicking a teammate opens their profile, which shows their role, a
26-week daily usage heatmap and their recent team workspaces. Teammates see only 0-4 levels,
and amounts are shown only to you. Pokes are opt-in in Settings > Experimental and need both
people to have them on. They are rate-limited to 1 per minute per teammate and 20 per hour, and
delivered in-app by a 30 s poll that runs only while Pokes are on and Orca is in front.

Control plane: migration 0050 (member_usage_hours, member_poke_prefs, member_pokes),
src/team-presence.ts routes. The heatmap reads usage_outbox sandbox time plus dated
token_usd_micros deltas. A member's poke opt-in is dropped when they are removed.
2026-11-10 19:24:26 -08:00
Neil 46b467d847 feat(cloud): workspace numbers (W-123), org slug links and synced sidebar prefs on the control plane (G13, G14) 2026-11-10 19:22:39 -08:00
Neil a86a8d6850 feat(cloud-create): automatic environments — repos come prebuilt after the first create
The first create of a repo that no environment of the account lists makes a default environment for it
(just the repo, cloned blobless, no install script) and builds it in the background with the existing
environment build pipeline (EnvironmentBuildRunner). Later creates boot from its active build and fetch
only what changed, in the background, shown as 'Update repository' with git's real progress.

- environments.kind 'org' | 'auto' + last_used_at (migration 0049, applied to dev); an admin's edit
  adopts an auto environment; an admin environment listing the repo always wins
- auto environments unused for 14 days are deleted with their snapshots (cron); per account only
- golden refresh, staleness, pruning and the warm pool apply as for any environment
- the caller's machine size stands for auto environments; an explicit other region skips them
- AUTO_ENVIRONMENTS=off disables it
- desktop: feature repo-update, 'Update repository' / 'Fetching changes…' / sidebar 'Updating the
  repository…'

Measured on dev (stablyai/orca, staging OWNER): before 6 s to ready + 58 s clone; the background build
took 79 s; after, ready in 6.6-8.7 s with the repo current 0.7 s later (7.4-9.4 s total).
2026-11-10 19:10:29 -08:00
Neil 06075e682f feat(cloud): POST /v1/agent-credentials/claude/verify for the desktop's pre-launch check
Runs the confirm-before-revoke auth check on demand: a pass within 10 min answers at once (verified_at, migration 0048), otherwise one check rate-limited to one a minute per person, revoking (audited) only on a definite authentication_error. Storing a new token forgets the old verification.
2026-11-10 18:10:43 -08:00
Neil 61fd3ecf0f fix(cloud): read snapshot reads the workspace's own checkout (branch worktree), not the base clone; profile-cloud-service under max-lines 2026-11-10 18:01:58 -08:00
Neil ca73c6c8dc fix(cloud): confirm a provider 401 with one auth check before revoking an Orca account
A single 401 on an Orca-account request no longer revokes the person's Claude account everywhere. The hook only fires after the real credential was swapped in and sent. The control plane then makes one free auth check with the real token (Anthropic count_tokens, oauth beta) and revokes only on a definite authentication_error; anything else (passes, 429, 5xx, other 401 types, network) keeps the account. Checks are rate-limited to one per person and agent per minute (agent_credentials.checked_at), and every keep/revoke is audited (agent_credential_audit, migration 0047). Codex keeps its lease-refresh path.
2026-11-10 17:47:58 -08:00
Neil ddf6cfe09f fix(cloud): a provider 401 drops the dead account placeholder from all the person's running sandboxes 2026-11-10 17:40:14 -08:00
Neil c2e250bcfe fix(cloud-start-gate): a sandbox going to sleep or an abandoned create no longer refuses a start
The team and per-member concurrency counts (billing's checkStart input and the guardrail backstop)
counted 'suspending' rows, which drain for up to 5 min after someone chose Sleep and read as
asleep everywhere, and 'creating' rows whose Worker was cut off (until the cron released them).
Both could refuse a start that the user's view says fits. The global capacity cap still counts them.
2026-11-10 17:02:49 -08:00
Neil 47395617b2 Merge remote-tracking branch 'private/cloud/integration' into cloud/read-snapshot-signed
# Conflicts:
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
2026-11-10 17:02:00 -08:00
Neil 793292a6fb fix(cloud-create): clone percent covers remote counting; blob fetch reads as checkout, held 2026-11-10 15:55:35 -08:00
Neil 19cb3f2eac fix(cloud-create): blobless repo clone, optional background clone with progress, bounded create failures
A repo-backed create of stablyai/orca (2.7 GB) did a full git clone inside the 120 s orcad start
command, failed at ~127 s with a bare create_failed, then the pooled path retried on a fresh VM
(~255 s total). When the desktop gave up, the cut-off Worker left the retry row in 'creating' for
15 min.

- workspace prelude clones --filter=blob:none (stablyai/orca: 68 s instead of >120 s timeout)
- feature clone-progress: the clone runs detached after ready; GET /v1/sandboxes/:id/clone reports
  {state, percent, stage} and records a failed clone's reason in last_error; 15 min clone timeout
- failed creates record why (orcad_start_failed, provider_<status>, ...) instead of create_failed
- a pooled boot that failed after 30 s is not retried on a fresh VM
- 'creating' rows whose Worker was cut off are released after 5 min (create_abandoned)
2026-11-10 15:51:46 -08:00
Neil 5883d7eaf6 fix(cloud): tell a provider that was never offered (flag off) from the kill switch
GET /v1/agent-credentials adds providerState {claude, codex: on|off|disabled} next to providerEnabled.
Clients read it through orcaCloudProviderState (older servers: disabled = kill switch; a state that
contradicts providerEnabled is never trusted). Flag off is a new 'unavailable' kind: Settings says
it isn't available in Orca Cloud yet (no 'right now / until it's back'), and the composer hides the
Agent row like an agent without an account path. Kill-switch copy is unchanged.
2026-11-10 09:02:08 -08:00
Neil e6cdedd45e Merge pull request #247 from nwparker/cloud/agents-aws-badge
fix(cloud): W10-2: AWS keys marked 'Real value in sandbox' with a focusable tooltip; fixtures
2026-11-10 08:21:14 -08:00
Neil 5a0eabd864 fix(cloud): compare the boot env inline; refresh in the background only when it changed 2026-11-10 07:29:12 -08:00
Neil b20120d4d0 fix(cloud): secrets saved while a sandbox boots reach its session
The boot resolves the session env before the VM is up, and a secret change only refreshes running sandboxes, so a value saved from the build-sheet Secrets row during the boot never reached the workspace (found in the W6 live e2e). Once running, the boot re-resolves the env and refreshes the session when it changed.
2026-11-10 07:26:29 -08:00
Neil f094594d0e merge integration; design-squad copy: generic 'this key' sentence for non-AWS keys, subscription-token refusal points to Settings → Agent accounts 2026-11-10 06:58:16 -08:00
Neil 576ea3ae4f fix(cloud): D13 fails closed when a workspace's sharing is unknown
Server: only a row known to be private counts as unshared. Desktop panel: a failed sharing read leaves out the caller's Personal values and the Personal save scope, as for a teammate.
2026-11-10 06:49:40 -08:00
Neil 91e82b870d feat(sandbox-control): bind a GitHub install by the Orca sign-in's GitHub identity (N5/O3)
Billing's setup chain now passes the GitHub identity that Orca Cloud auth
verified from a GitHub sign-in (githubUserId, githubLogin). The install URL's
signed state carries it, and the setup URL checks it against the installation
with the App's own credentials: the user's own account, or an active org admin
(members:read installation token). A match binds with method 'idp' and skips
GitHub's separate Authorize page. Anything else falls back to the OAuth step
(A4b) as before.
2026-11-10 06:14:02 -08:00
Neil 2f06814020 test: imports before the preset-name list 2026-11-10 05:57:40 -08:00
Neil 99c52ba889 Merge remote-tracking branch 'private/cloud/integration' into cloud/w6-a9-recipe
# Conflicts:
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
2026-11-10 05:53:41 -08:00
Neil 0606c25105 Merge pull request #250 from nwparker/cloud/w6-codex-broker
feat(sandbox-control): Codex account broker (contract D11, flag S2)
2026-11-10 05:49:20 -08:00
Neil 4030deeba8 fix(cloud): every agent credential a sandbox gets in full is marked 'Real value in sandbox', not only AWS keys
A shared list of agent and model-provider credential names (AWS, Bedrock, OpenRouter, Groq, xAI,
Mistral, DeepSeek, Together, Fireworks, Perplexity, Cerebras, Moonshot/Kimi, DashScope, Z.ai,
MiniMax, NVIDIA, Cohere, Azure OpenAI, Hugging Face, Amp, Factory, ...) marks every one that has no
egress swap. AWS keeps its own sentence; others read 'Orca can't swap {{name}} at the network edge,
...'. The control-plane test now walks the server's agent keys, this list and the desktop's Agent
API key presets: each is swapped, or flagged.
2026-11-10 05:43:43 -08:00
Neil 732c04ddd7 Merge remote-tracking branch 'private/cloud/integration' into cloud/w6-a9-recipe
# Conflicts:
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
2026-11-10 05:43:06 -08:00