mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 18:37:24 +00:00
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
This commit is contained in:
@@ -28,9 +28,10 @@ fetch_verified() { # url sha256 dest
|
||||
}
|
||||
|
||||
log 'orcad bundle'
|
||||
fetch_verified "$ORCAD_BUNDLE_URL" "$ORCAD_BUNDLE_SHA256" /tmp/orcad.tgz
|
||||
tar -xzf /tmp/orcad.tgz -C "$ORCA_HOME/runtime"
|
||||
rm -f /tmp/orcad.tgz
|
||||
bundle="$(mktemp -d)/orcad.tgz"
|
||||
fetch_verified "$ORCAD_BUNDLE_URL" "$ORCAD_BUNDLE_SHA256" "$bundle"
|
||||
tar -xzf "$bundle" -C "$ORCA_HOME/runtime"
|
||||
rm -rf "$(dirname "$bundle")"
|
||||
test -s "$ORCA_HOME/runtime/orcad/orcad-server.js"
|
||||
node="$(find "$ORCA_HOME/runtime/runtimes" -type f -name node | head -n 1)"
|
||||
test -x "$node"
|
||||
|
||||
@@ -30,4 +30,6 @@ export type Env = {
|
||||
|
||||
/** Public URL of this Worker's /v1/egress/proxy; Vercel forwardURL rules point here. */
|
||||
EGRESS_PROXY_URL?: string
|
||||
/** Shortened session deadline (ms) for staging rollover rehearsals; refused when SANDBOX_ENV=prod. */
|
||||
SESSION_DEADLINE_MS?: string
|
||||
}
|
||||
|
||||
@@ -77,7 +77,9 @@ function lifecycleDeps(env: Env, deps: Deps): LifecycleDeps | null {
|
||||
environment: env.SANDBOX_ENV,
|
||||
goldenSnapshotId: env.GOLDEN_SNAPSHOT_ID,
|
||||
defaultRegion: env.VERCEL_REGION ?? 'iad1',
|
||||
egressProxyUrl: env.EGRESS_PROXY_URL
|
||||
egressProxyUrl: env.EGRESS_PROXY_URL,
|
||||
sessionDeadlineMs:
|
||||
env.SESSION_DEADLINE_MS && env.SANDBOX_ENV !== 'prod' ? Number(env.SESSION_DEADLINE_MS) : undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ export type LifecycleDeps = {
|
||||
goldenSnapshotId: string
|
||||
defaultRegion: string
|
||||
egressProxyUrl?: string
|
||||
/** Staging rehearsals shorten the cap; production uses SESSION_DEADLINE_MS. */
|
||||
sessionDeadlineMs?: number
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,12 +82,13 @@ function egressPolicy(deps: LifecycleDeps, row: SandboxRow) {
|
||||
return compileNetworkPolicy({ mode: 'allowlist', credentials })
|
||||
}
|
||||
|
||||
export function sessionFields(state: ProviderSandboxState, now: number): SessionFields {
|
||||
export function sessionFields(deps: LifecycleDeps, state: ProviderSandboxState): SessionFields {
|
||||
const now = deps.now()
|
||||
const startedAt = state.session.startedAt ?? now
|
||||
return {
|
||||
session_id: state.session.id,
|
||||
session_started_at: startedAt,
|
||||
session_deadline_at: startedAt + SESSION_DEADLINE_MS,
|
||||
session_deadline_at: startedAt + (deps.config.sessionDeadlineMs ?? SESSION_DEADLINE_MS),
|
||||
lease_expires_at: startedAt + state.session.timeoutMs,
|
||||
usage_settled_at: startedAt
|
||||
}
|
||||
@@ -116,7 +119,7 @@ async function boot(deps: LifecycleDeps, row: SandboxRow, state: ProviderSandbox
|
||||
repo,
|
||||
githubPlaceholder: deps.config.egressProxyUrl ? githubPlaceholderToken(row) : undefined
|
||||
})
|
||||
const running = await claim(deps, row, { status: 'running', last_error: null, ...sessionFields(state, deps.now()) })
|
||||
const running = await claim(deps, row, { status: 'running', last_error: null, ...sessionFields(deps, state) })
|
||||
return { row: running, connection }
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ async function reconcileRunning(deps: LifecycleDeps, row: SandboxRow, summary: R
|
||||
async function repairTransition(deps: LifecycleDeps, row: SandboxRow): Promise<void> {
|
||||
const state = await deps.provider.getSandbox(row.provider_name, { resume: false })
|
||||
if (state?.session.status === 'running') {
|
||||
await transition(deps.db, row, { status: 'running', ...sessionFields(state, deps.now()) }, deps.now())
|
||||
await transition(deps.db, row, { status: 'running', ...sessionFields(deps, state) }, deps.now())
|
||||
return
|
||||
}
|
||||
await markProviderStopped(deps, row)
|
||||
|
||||
@@ -162,6 +162,24 @@ Compiled per sandbox by `compileNetworkPolicy()`:
|
||||
recipe adapter; start one scheduler per ready hosted runtime (stop on suspend/destroy); an orcad RPC exposing
|
||||
the idle-probe verdict + last PTY input for `readActivity`; header warning + mobile push for `warn`.
|
||||
|
||||
## Live results (2026-11-09, Vercel Pro team `lovecast`, project `orca-sandbox-control`, iad1)
|
||||
|
||||
Driven by the real Worker handler in-process (real Vercel REST, node:sqlite D1, stub billing) and the real desktop
|
||||
driver/scheduler. Base OS is Amazon Linux 2023 (dnf), not Ubuntu.
|
||||
- Golden image: orcad built from public stablyai/orca@7c14832 in a 8 vCPU build sandbox in 98s (67 MB tgz);
|
||||
provision 14.3s (gh 2.103.3, Claude Code 2.1.319, Codex 0.166.0; orcad loopback smoke passed); wipe ok;
|
||||
snapshot 8.2s. Bug found and fixed: provision downloaded the bundle over its own source path.
|
||||
- Snapshot → orcad ready (`POST /v1/sandboxes`, incl. Vercel create + orca-sandbox-start): 5.4 / 4.1 / 4.9 s; WS open.
|
||||
- Suspend (drain + stop) 7.6s; resume → ready 6.0s; same endpoint and same orcad host key (no re-pair).
|
||||
- Shortened cap (6 min): scheduler warned T−15, then forced rollover at the deadline in 17.3s (drain, stop, boot,
|
||||
orcad ready), reconnect WS open, new deadline set. Destroy 0.4–0.7s; zero sandboxes/snapshots left.
|
||||
- Egress: allowlist resolves npm (200), `example.com` does not resolve (curl rc 6). Policy update 0.25s.
|
||||
Placeholder → injected fake GitHub credential reaches GitHub (curl/gh `token` scheme: 401 Bad credentials);
|
||||
attacker token and placeholder-less git → 403 `orca-egress-denied`. Node fetch under a transform rule still hangs
|
||||
on Pro; `orca-egress-probe` reports `egress_framing_hang` (npm, untransformed: ok). No real GitHub token was used,
|
||||
so a successful authenticated push is still unverified.
|
||||
- Not covered live: forwardURL egress proxy (needs a deployed Worker URL), agent auto-resume with a real chat.
|
||||
|
||||
## What needs live access (not done)
|
||||
|
||||
Vercel Pro team id + project id + a Sandbox-scoped token (as Worker secrets), wrangler auth for a dev D1, a
|
||||
|
||||
Reference in New Issue
Block a user