Commit Graph
537 Commits
Author SHA1 Message Date
Neil 95bb1dd372 Merge pull request #249 from nwparker/cloud/w6-a9-recipe
A9 sign-out before delete + recipe env-forwarding warning (P-4)
2026-11-10 06:03:08 -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 21ac87b972 feat(cloud-start): setup return link, setup telemetry, X1 error model, B2 team-plans lookup (NP-4)
- N9: orca://cloud/setup/return?session=cs_… is routed (open-url + second
  instance), validated, focuses Orca and fans out to renderer listeners
  (onCloudSetupReturn) so the setup session re-reads at once.
- N10: cloud_setup_step_{started,done,failed}, cloud_setup_first_sandbox and
  cloud_setup_plan_chosen, enum-only, derived from the setup rows.
- X1: setup error kinds (timed_out, checkout_canceled, bank_step,
  trial_unavailable, team_create_failed, wrong_account) and their actions.
- B2: billing POST /v1/billing/team-plans returns other teams' plan state with
  the caller's own token; auth confirms membership from that token (no new
  credential). Desktop IPC billingTeamPlans + useSwitchToPlannedTeam. The team
  switch logic moves out of SidebarTeamSubmenu so the composer can reuse it.
2026-11-10 05:50:29 -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 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
Neil 7fa51b6a0b Merge pull request #246 from nwparker/np4/github-repo-access
NP-4: GitHub repo access, preselected install URLs, install requests, webhook auto-start, repository list (N2/N3/N12, D2/D3)
2026-11-10 05:42:57 -08:00
Neil 4c1ee40ffe Merge remote-tracking branch 'private/cloud/integration' into cloud/w6-codex-broker
# Conflicts:
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
2026-11-10 05:32:29 -08:00
Neil 849a12773b fix(cloud): find agent CLIs in /opt/orca/tools/bin; delete note only for running sandboxes; test retry skip
Verified on a dev sandbox (Claude Code 2.1.319, codex-cli 0.166.0): runCommand runs as ubuntu with
HOME=/vercel (same user as orcad); `claude auth logout` and `codex logout` exist and exit 0; the
script reported {loggedOut:2,left:0}, removed both credential files and kept other ~/.claude.json keys.
2026-11-10 05:27:41 -08:00
Neil 5b9d2735e0 fix(cloud): OpenCode with no credentials shows 'Connect a provider' instead of failing on Copilot or Zen
With nothing configured, OpenCode picked its GitHub Copilot provider (GITHUB_TOKEN is the workspace
GitHub App stand-in: 'Authorization header is badly formatted') or OpenCode Zen (opencode.ai is not
on the egress allowlist). The VM seeding keeps both in OpenCode's disabled_providers unless the user
connected them in OpenCode (auth.json); the user's own list is kept (ledger of what Orca added).
Checked on a dev VM: the composer opens on 'Connect a provider'.
2026-11-10 05:23:31 -08:00
Neil 1bca45b536 fix(sandbox-control): Codex broker review fixes (M1-M4, L5-L8)
- M1: a permanent refresh failure revokes only the login it refreshed (CAS on updated_at).
- M2: dead logins (refresh_token_expired/reused/invalidated) are never retried; a new login clears it.
- M3: the Codex account route only carries the token to /backend-api/codex/*, the plugin catalog and
  wham/usage (GET), seen live; plain segments only.
- M4: one atomic INSERT enforces one live broker per person (409 broker_in_progress) and 6 starts/hour;
  broker sandboxes use 2 vCPUs.
- L5: auth.json is read only after Codex exited 0.
- L6: the 401 hook respects the refresher's backoff and dead logins.
- L7: a cancel while the broker is starting wins: the sandbox goes and POST answers 409 cancelled.
- L8: orca-sandbox-env writes the marker before the swap, recognises any Orca placeholder, and never
  overwrites a login already set aside.
2026-11-10 05:22:43 -08:00
Neil 100b9d4699 feat(sandbox-control): tell billing the GitHub owner/user ids of each bind (trial abuse keys, POST /v1/internal/trial/github) 2026-11-10 05:19:45 -08:00
Neil 521c9fe3c5 feat(cloud): desktop repo access hook, GitHub row model and repo list plumbing (NP-4 N2/N12, D2/D3) 2026-11-10 05:19:45 -08:00
Neil a4e0b7a656 feat(sandbox-control): GitHub repo access, preselected install URLs, install requests, repository list (NP-4 N2/N3/N12, D2) 2026-11-10 05:19:44 -08:00
Neil 4af8f7fe04 feat(sandbox-control): Codex account broker (contract D11, flag S2)
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.
2026-11-10 05:03:50 -08:00
Neil a81afb57e0 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 04:49:31 -08:00
Neil 40b33811b5 Merge pull request #242 from nwparker/cloud/w6-agent-accounts
W6: sign in once via your Orca account — Claude account store + egress-time Source (D10/D11/D13/D14)
2026-11-10 04:48:11 -08:00
Neil aedf0809eb Merge remote-tracking branch 'private/cloud/integration' into cloud/w6-a9-recipe
# Conflicts:
#	src/renderer/src/i18n/locales/en.json
2026-11-10 04:43:10 -08:00
Neil de8a65b7f1 Merge pull request #241 from nwparker/cloud/w9-eval
feat(cloud): acceptance — phone UI read-asleep (sim), cloud run.ports headless, nonconcurrent per #233
2026-11-10 04:41:08 -08:00
Neil 0832550290 feat(cloud): provider-specific onUnauthorized hook (default: revoke) 2026-11-10 04:39:25 -08:00
Neil 5e1a5d7ac5 refactor(cloud): drop env-build scrub-on-clone (spec v4 D14); keep sign-out before delete 2026-11-10 04:33:45 -08:00
Neil dd34314dc0 feat(billing): bill overage by the minute, put sandboxes to sleep at the cap (U22, U24)
- Overage stays $1.00 per sandbox hour (ORCA_CLOUD_OVERAGE_CENTS_PER_HOUR) and is now billed by
  the minute: a per-minute metered TEST price (unit_amount_decimal = rate / 60 to 12 decimals,
  transform_quantity divide_by 60, round up), created the same way by stripe-test-setup.ts.
  capSeconds rounds the cap down to whole minutes and spentCents mirrors the invoice, so the
  cap math matches Stripe. The meter still counts seconds.
- Opting in re-prices an overage item still on an older price (e.g. $0.75 / h) instead of adding
  a second item on the same meter, and removes any extra stale one.
- Alerts at 75%, 90% and 100% of included hours (warnAtPercent).
- New top-level entitlement.suspendRunning: payment grace expired, or at the limit (out of hours
  with overage off, or at the spend cap). The start check and usage answers carry it, so the
  control plane puts running sandboxes to sleep (snapshot kept, never deleted). Payment fields and
  /v1/internal/suspensions stay payment-only, so no data-retention clock starts at a cap.
- Copy (desktop billing panel, plan card, build sheet, phone, CLI): "billed by the minute" after
  the rate; at the limit "Running sandboxes go to sleep and new ones can't start. Nothing is
  deleted, and your files are safe."
2026-11-10 04:33:07 -08:00
Neil ab106b93cc feat(cloud): cloud run.ports passes on the #233 golden (3000 + second worktree block, stable across sleep) 2026-11-10 04:29:04 -08:00
Neil 8b2701636c feat(cloud): acceptance headless cloud run.ports (first workspace 3000, second worktree block, sleep/wake) 2026-11-10 04:29:04 -08:00
Neil 2a0790deef docs(cloud): run.ports cloud fail is desktop/golden skew pending #233 golden 2026-11-10 04:29:04 -08:00
Neil c6484c005b feat(cloud): desktop check for #233 run-action semantics and cloud port block (W9D_ONLY=run-ports2)
- run.nonconcurrent: echo-loop started in B stops only A's echo-loop; web keeps serving in A and B
- run.ports (cloud): ORCA_PORT in the first workspace's terminal and run action, before and after
  Sleep -> wake, with the VM's port registry; whether a second worktree on the same VM is offered
2026-11-10 04:29:04 -08:00
Neil d009ec750c chore(acceptance): W9 headless iOS sim run for life.read-asleep-phone (pass), lift audit cap 2026-11-10 04:29:04 -08:00
Neil 956ddeb626 fix(cloud): account review — owner bound into account routes + env rebuilt on owner/visibility change, 401 revokes the account, explicit deny reasons, unreadable token never holds account mode, 10s account cache, bounded heal map, credentialBinding/extraHeaders for the Codex provider 2026-11-10 04:27:49 -08:00
Neil ae7750b7af fix(sandbox-control): re-bind the build runner Worker (step 2 of 2 after the delete-class migration) (#240) 2026-11-10 04:24:12 -08:00
Neil a25934cf64 feat(cloud): sign in once via your Orca account (contract D10/D11/D13/D14) — Claude setup-token store (Personal only, flag S1, kill switch), egress-time Source with one stable account placeholder per sandbox, never in shared workspaces; migration 0044 2026-11-10 04:22:16 -08:00
Neil 47dc83b869 Merge pull request #238 from nwparker/cloud/agents-copilot-ph
fix(cloud): Copilot's token stand-in looks like a GitHub token
2026-11-10 04:19:18 -08:00
Neil 77af3b072a fix(sandbox-control): unblock dev deploy (10061): apply the build-runner delete-class migration without the binding, step 1 of 2 (#237)
* fix(sandbox-control): unblock dev deploy: apply the build-runner delete-class migration without the binding (step 1 of 2)

* test(sandbox-control): build-runner config test allows the binding-less step of the rollout
2026-11-10 04:17:03 -08:00
Neil be30702701 Merge remote-tracking branch 'private/cloud/integration' into cloud/w6-a9-recipe
# Conflicts:
#	cloud/apps/sandbox-control/image/provision-golden.sh
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
2026-11-10 04:11:07 -08:00
Neil d323e4a20f Merge pull request #223 from nwparker/cloud/w5-cli-glossary
feat(cli): orca cloud glossary copy, workspace delete, routine list/run (DS-25, DS-36 CLI)
2026-11-10 04:09:58 -08:00
Neil b55b368887 fix(sandbox-control): host EnvironmentBuildRunner in its own Worker so control-plane preview URLs work (#234)
Cloudflare generates no preview URLs for a Worker that implements a Durable Object, so every
--preview-alias upload of orca-sandbox-control-dev 404ed. The runner DO moves to
orca-sandbox-build-runner-dev (wrangler.build-runner.dev.jsonc); the control plane binds it with
script_name and deletes its own class (migration env-build-runner-v2). The runner only keeps the
alarm: each step calls back into the control plane's BuildTicker RPC entrypoint, which runs the same
tickBuild with the control plane's D1, provider and secrets, so nothing is duplicated.
2026-11-10 04:08:45 -08:00
Neil 12fe0c867f feat(cloud): sign agents out before sandbox delete, scrub env-build images, recipe env warning (A9, P-4)
- 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.
2026-11-10 04:07:13 -08:00
Neil 33202f5bd9 Merge remote-tracking branch 'private/cloud/integration' into cloud/w5-cli-glossary
# Conflicts:
#	src/cli/root-help-text-primary.ts
2026-11-10 04:06:22 -08:00
Neil adc417cae5 feat(cloud): acceptance read-asleep access (operator member removal, private prune) and phone protocol path, by W9 2026-11-10 03:54:00 -08:00
Neil 3f2b8ead4e Merge pull request #228 from nwparker/cloud/w9-eval
feat(cloud): acceptance — run actions + ports (m4air UI), read-while-asleep (live E2EE), gap rows
2026-11-10 03:51:42 -08:00
Neil f88c09c7fa Merge pull request #211 from nwparker/cloud/w2-squad-archive
fix(cloud): archive from the team list really stops the sandbox (DS-01 P0, DS-09)
2026-11-10 03:47:46 -08:00
Neil c14e875adc Merge pull request #225 from nwparker/fix/ds-34-44-billing-polish
fix(billing): DS-34 billing polish + DS-44 nits
2026-11-10 03:42:47 -08:00
Neil b199587d7e feat(cloud): desktop run actions + ports checks (W9D_ONLY=run-actions)
- local.run-actions: autoRunAfterSetup after a good setup and not after a failed one, Run button,
  one trust prompt, Stop -> Stopped, menu Restart replaces the tab, Cmd+Opt+Enter start/restart
- run.nonconcurrent: echo-loop started in B stops A's
- run.ports: ORCA_PORT/ORCA_PORT_COUNT/CONDUCTOR_PORT per terminal, distinct blocks, stable across
  an app restart, served locally; cloud half: the action in the VM reachable here via auto-forward
- run.cloud-resume: action back after Sleep/wake and after Restart sandbox
2026-11-10 03:42:31 -08:00
Neil 29cdd2cb99 feat(cloud): acceptance read-while-asleep (live, E2EE, no wake) plus access/phone rows (owner-reported) 2026-11-10 03:42:31 -08:00
Neil 322ba5eabb feat(cloud): acceptance catalog rows for run actions and per-workspace ports (gap 4) 2026-11-10 03:42:31 -08:00
Neil c5199433a9 Merge pull request #214 from nwparker/cloud/w6-secret-request
feat(cloud): agent secret requests: orcad RPC, orca secret request, orca-env (contract §3)
2026-11-10 03:42:02 -08:00
Neil 6b2ff92825 fix(cloud): Copilot's token stand-in looks like a GitHub token (Copilot ignored orca-ph-…)
Dry routine run on dev: Copilot CLI answered 'No authentication information found' with
COPILOT_GITHUB_TOKEN=orca-ph-…; it only takes GitHub-shaped tokens (github_pat_/gho_/ghu_; classic
ghp_ refused). The stand-in for that one credential is now github_pat_orcaph_<sandbox>, still
swapped by exact match on api.github.com (Copilot endpoints only) and the Copilot API.
2026-11-10 03:40:24 -08:00
Neil 6fa10c836b Merge remote-tracking branch 'private/cloud/integration' into cloud/w2-squad-archive
# Conflicts:
#	src/renderer/src/components/orca-cloud/cloud-workspace-actions.ts
2026-11-10 03:40:01 -08:00
Neil 01d2482a3a fix(billing): one billing store, skeleton, plurals, plans focus and billing nits (DS-34, DS-44)
DS-34:
- One billing store (billing-summary-store) replaces the summary, the hook's local state and the
  Run-on picker cache; it keeps the last good result through a failed read and still drops answers
  from before a team or account switch (DS-17).
- Skeleton while Plan & billing loads.
- '{{count}} sandbox hours left' and '{{count}} sandbox hours over the included amount this month'
  as i18n plurals; no bare 'hours'; the unreachable 100% branch is gone.
- Usage warning driven by usageWarningPercent ('Your team has used {{percent}}% of this month's
  sandbox hours.'), in Settings, the plans page and the account menu.
- capTooHigh states the maximum ('The spend cap can be at most {{max}}.'), from offers.maxSpendCapCents.
- Plans dialog focuses its heading on open, so Tab reaches the interval toggle before the cards.
- Payment notice uses InlineError; the build card's overage buttons land on the overage section.
- Account menu names the team once and adds the hours-left line.

DS-44: warning tone at 90%+, '$' as an input prefix, neutral paid check, 24px dialog close hit
area, no <p> inside the CheckoutPanel <dl>.
2026-11-10 03:39:21 -08:00
Neil e604bd4f39 Merge pull request #226 from nwparker/cloud/u22-cpu-fairuse
feat(sandbox-control): internal per-session CPU + operator fair-use report (U22)
2026-11-10 03:38:55 -08:00
Neil e02edd279f Merge remote-tracking branch 'private/cloud/integration' into cloud/w6-secret-request
# Conflicts:
#	cloud/apps/sandbox-control/image/vm-scripts.generated.ts
2026-11-10 03:34:32 -08:00
Neil d76cb62c57 fix(sandbox-control): keep preview URLs on for the dev Worker (preview aliases 404ed) (#224) 2026-11-10 03:34:07 -08:00