Commit Graph
9 Commits
Author SHA1 Message Date
Neil ba7db6d219 fix(sandbox-control): read the orgRole claim that Orca Cloud auth mints (#29)
Auth mints the live org role as orgRole on sandbox tokens (same claim as billing
tokens, stablyai/orca-cloud#695); the verifier read org_role, so admins would
never have been recognized.
2026-11-09 04:07:04 -08:00
Neil 9922e32a68 feat(cloud): Orca Cloud in the desktop end to end (provider, lease scheduler, upsell, dogfood) (#26)
* feat(sidebar): replace footer Settings and Help icons with an account menu

* fix: keep account menu header on primitive spacing; move focus-read allowance

* fix(sidebar): address account menu review findings

* feat(billing): Cloudflare Worker for Stripe checkout, portal, webhooks, entitlements and usage (#7)

Test-mode-only foundation for paid Orca plans: hosted Checkout/Portal,
signed + idempotent Stripe webhooks that re-read subscriptions, a D1 ledger
for sandbox usage with overage-only Billing meter events, and entitlement
checks for the desktop and the sandbox control plane.

* feat(billing): Plan & billing in the Orca account settings and account menu (#9)

Shows the signed-in account's plan, sandbox hours used and left, and opens
hosted Stripe Checkout (Upgrade) or the Customer Portal (Manage billing) in
the browser. Main mints a short-lived billing token from Orca Cloud auth and
only opens checkout.stripe.com / billing.stripe.com URLs. Hidden until
ORCA_BILLING_API_URL is set; the account menu item is gated on the 'billing'
cloud capability and registers through a local adapter that mirrors the
upcoming account menu API.

* feat(billing): plans and prices from config, opt-in Stripe Tax, real account menu

- Worker: BILLING_PLANS JSON overrides the plan catalog (labels, display price,
  hours, limits); entitlements return the plan list so the desktop shows no
  hardcoded prices. STRIPE_AUTOMATIC_TAX=true adds automatic_tax and tax id
  collection to Checkout (default off). Setup script takes prices from env.
- Desktop: register Plan & billing through the sidebar account menu
  (merged nwparker/sidebar-account-menu) and drop the local adapter.
- Register the billing Worker's tests with the test-runner check.

* feat(billing): Team pricing, opt-in overage, Stripe test-mode e2e, dev deploy (#18)

* feat(billing): Team-only pricing, opt-in overage with spend cap, live Stripe test-mode e2e

- Catalog: Team $50/seat/mo or $480/seat/yr, 60 Standard h/seat/month pooled
  (monthly windows on annual plans), Large 2x, 3 running/seat, 15-min idle sleep;
  Enterprise is contact-only. All numbers/labels in BILLING_PLANS defaults.
- Overage is opt-in (adds the metered item), $0.75/h, monthly spend cap (default
  $25, admin-raisable) enforced in the meter outbox; 80%/100% usage warnings.
- Checkout: plan/interval/seats with adjustable quantity; portal configuration var.
- Workers reject fetch redirect 'error': use 'manual'. Log route errors.
- scripts/stripe-test-setup.ts creates the test catalog + portal configuration;
  scripts/e2e-test-mode.ts drives Checkout (headless, test card), overage, meter,
  cap, annual, test-clock renewal, payment failure and cancel.
- Desktop: Team/Enterprise cards with interval + seats, usage warnings, overage
  toggle + cap; split into copy/offers/usage modules.

* feat(billing): dev deployment config, dev operator keys, return page

- wrangler.dev.jsonc for orca-billing-dev (workers.dev, dev D1, test-mode prices).
- BILLING_DEV_JWKS (issuer orca-billing-dev-test) accepted only when BILLING_ENV
  is not prod, for e2e runs until auth mints billing tokens.
- GET /return: static 'return to Orca' page for Checkout/Portal redirects.
- Design doc: final pricing, dev URL and resources for the control plane.

* feat(billing): team seats follow membership, payment grace + suspend signal, Team UI

Worker
- Seats = org members from Orca Cloud auth (single source of truth; pending invites
  never count; min 1): auth pushes POST /v1/internal/seats, billing pulls
  /v1/internal/billing/org-members at Checkout and in a reconcile cron, fails closed
  (503) if auth is configured but unreachable. No token claim carries a count.
- Proration: adds always_invoice, removals create_prorations (Stripe default).
- Billing admin actions require a token minted in the last 6 minutes.
- Payment failure: past_due_since (migration 0003); new starts stop at once;
  after 96 h (paymentGraceHours) reason payment_grace_expired + suspendRunning on
  check/usage, and GET /v1/internal/suspensions for the control plane.
- Portal config: monthly<->annual + cancel only (seats follow membership).
- e2e: seat add/remove proration, grace expiry -> suspend -> pay -> resume.

Desktop
- Team section + account menu item: members/roles, invite, change role, remove
  with confirm, revoke invites (owners/admins, auth role rules mirrored).
- Payment issue banner with suspension date and Update payment method.

* feat(billing): in-app plans page (#22)

A pricing/plans page reachable from the account menu ("Plan & billing"), the
Settings plan section ("Choose a plan" / "Compare plans"), and any upsell via
openPlansPage(). Everything comes from the billing service's offers: Team
monthly/annual (with the computed annual saving), pooled hours, Large weight,
concurrency, idle sleep, opt-in overage with spend cap, and Enterprise contact.

- States: choose (admin), locked (member), current plan with usage, payment
  failure (status-first), checkout in progress, loading and failure with retry.
- Seats are read-only: one per team member (billing re-reads the count).
- Shared card shell keeps both cards' footers level; sliding interval toggle and
  price fade respect reduced motion; dialog opens without a pre-focused button.
- Worker offers gain per-seat cents and the Large weight for totals.
- Copy matches the marketing /cloud promises: agents keep running, wake in
  seconds, secrets never stored in the VM.

* wip(cloud): Orca Cloud built-in provider wiring

* feat(cloud): no-plan upsell opens the plans page

* feat(cloud): Orca Cloud dogfood fixes (provider persistence, picker label, any-input activity, idle override)

* fix(cloud): live dogfood fixes (snapshot already-deleted, agent egress wildcards, golden image id) + results

* fix(cloud): i18n keys, typed dev JWK, verdict typing

* feat(cloud): billing caps from billing (maxConcurrentSandboxes, per-member), userId on usage; concurrency copy

* feat(cloud): golden image can pin a released orca-server tarball (--release), source build stays the fallback

* fix(cloud): async dev key read, runtime localization catalog
2026-11-09 02:59:02 -08:00
Neil 0744798c98 fix(cloud): bind GitHub App installations to Orca accounts; kill switch, caps, rate limit; orphan sweep and retention (#24)
Security (B1): repo tokens were minted for any repo.url where the app was installed. Now an
installation must be bound to the caller's account (signed single-use connect state + OAuth proof
that the installer owns the account or is an org admin), tokens are scoped to the one repo and the
binding is re-checked on cached tokens. Operator binding route for support/dev.

Guardrails (B3/G4): D1 kill switch + static flag refuse create/resume/rollover and drain running
sandboxes; global running cap; 3/seat per-account backstop; per-account create rate limit.

Retention (B4/B6): hourly orphan sweep (stop, then delete after grace; partial listings delete
nothing), 30-day deletion after cancel/unpaid with a T-7 warning hook, 90-day idle retention,
104-day provider snapshot expiry backstop, repo_url tombstoned on destroy.
2026-11-09 02:19:25 -08:00
Neil ad6646c303 feat(cloud): org/personal/repo secret store with envelope encryption and session-start injection (#23)
D1 secrets table (migration 0003), AES-256-GCM per-secret DEK wrapped by SECRETS_KEK with
(scope, owner, name) AAD and key-id rotation; write-only /v1/secrets CRUD with org owner/admin
checks; precedence-resolved injection into orcad's env at every boot (no disk, no rebuild);
optional egress placeholder swap for api.anthropic.com / api.openai.com via the forwardURL proxy.
2026-11-09 02:19:24 -08:00
Neil 53d00d1985 fix(cloud): GitHub App setup page, dev-account billing bypass, live push results (#21)
* fix(cloud): GitHub App manifest page uses a visible submit button

* feat(cloud): dev operator accounts bypass billing outside prod; GitHub App push results
2026-11-09 02:19:24 -08:00
Neil 018c986c34 feat(cloud): dev deployment of the sandbox control plane (dev operator keys, dev egress credential) (#17) 2026-11-09 02:19:23 -08:00
Neil a4d6079510 fix(cloud): live Vercel Pro findings (bundle download, rehearsal cap) + results (#16)
* fix(cloud): provision bundle download no longer overwrites its source; shortened session deadline for staging rehearsals

* docs(cloud): live Vercel Pro results
2026-11-09 02:19:23 -08:00
Neil a91ae681f5 feat(cloud): 24h rollover, idle stop and agent auto-resume for Orca Cloud sandboxes (#13)
* feat(cloud): hosted session lease scheduler — 24h rollover, idle stop, agent auto-resume

* refactor: parse restart offers without casts
2026-11-09 02:19:23 -08:00
Neil e7989e6d6e docs(cloud): white-label Vercel sandbox driver design (#8) 2026-11-09 02:19:21 -08:00