Skip to content

Commit 34d0668

Browse files
V48 (impl-only): Force sandbox host on serverless; LocalHost is local-only
Serverless (VERCEL=1 / VERCEL_ENV / Lambda) always selects sandbox for deposit synthesis, even if BITCODE_PIPELINE_HOST=local is mis-set. LocalHost remains the default only on developer machines. Docs and tests match the host law.
1 parent 2c09a4e commit 34d0668

4 files changed

Lines changed: 67 additions & 14 deletions

File tree

packages/pipeline-image/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,19 @@ stock `node24` runtime that cannot install the monorepo on every run.
1515
| `/opt/bitcode/.bitcode/pipeline-host/*.mjs` | Host-smoke + live runners (`../../packages` resolves) |
1616
| `/vercel/sandbox` | Customer git checkout + run manifest/artifacts |
1717

18+
## Host law
19+
20+
| Runtime | Host |
21+
|---------|------|
22+
| **Local machine** (laptop, full FS) | **LocalHost** by default — optional `BITCODE_PIPELINE_HOST=sandbox` to exercise boxes |
23+
| **Serverless** (Vercel Production/Preview) | **Always sandbox** — LocalHost is never used (`VERCEL=1` forces sandbox) |
24+
25+
LocalHost cannot run deposit/read pipelines on serverless. Serverless always spawns a Sandbox microVM; prefer a VCR pipeline image for cold-start cost.
26+
1827
## Env (Production)
1928

2029
```bash
30+
# Host is auto-sandbox on Vercel; still fine to set explicitly:
2131
BITCODE_PIPELINE_HOST=sandbox
2232
BITCODE_PIPELINE_SANDBOX_IMAGE=bitcode-pipeline:v48-<gitsha>
2333
# or full ref:

uapi/.env.example

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ XAI_API_KEY=<your xAI API key>
3333
BITCODE_ASSET_PACK_REAL_INFERENCE=false
3434
BITCODE_ASSET_PACK_REAL_INFERENCE_PROFILE=bounded
3535
BITCODE_ENABLE_PIPELINE_HOST_API=false
36-
# Pipeline Host: local = LocalHost (in-process; use while debugging locally)
37-
# sandbox = VercelSandboxHost (prod/staging box dispatch)
36+
# Pipeline Host:
37+
# - Local machine: default LocalHost (BITCODE_PIPELINE_HOST=local or unset).
38+
# Optional sandbox from laptop: BITCODE_PIPELINE_HOST=sandbox (needs Vercel auth).
39+
# - Serverless (Vercel Production/Preview): always sandbox — LocalHost is never used.
40+
# VERCEL=1 forces sandbox even if BITCODE_PIPELINE_HOST=local is mis-set.
3841
BITCODE_PIPELINE_HOST=local
3942
BITCODE_PIPELINE_HOST_MAX_RUNTIME_MS=600000
40-
# VCR pipeline appliance (when set, Sandbox.create uses image, not stock runtime):
43+
# VCR pipeline appliance (Production sandbox image; Sandbox.create({ image })):
4144
# BITCODE_PIPELINE_SANDBOX_IMAGE=bitcode-pipeline:v48-<sha>
4245
# BITCODE_PIPELINE_IMAGE_ENTRY=/opt/bitcode/pipeline/run-pipeline.mjs
4346

uapi/lib/deposit-source-provisioning.ts

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@
77
* already has the tree (e.g. VercelSandboxHost image source), adopt it;
88
* otherwise LocalHost clones via `deposit:cloneRepositoryForRun`.
99
*
10-
* LocalHost only reads files from the workspace cloned for that run.
10+
* Host law:
11+
* - **LocalHost** — developer machine only (full system access). Never on
12+
* serverless/Production. Used when iterating locally with the monorepo on disk.
13+
* - **Sandbox (VercelSandboxHost)** — always on serverless (Vercel / Lambda).
14+
* Synthesis spawns a microVM; optional VCR pipeline image via
15+
* `BITCODE_PIPELINE_SANDBOX_IMAGE`.
1116
*
12-
* Host selection: `BITCODE_PIPELINE_HOST` (`local` | `sandbox`).
17+
* Host selection: `BITCODE_PIPELINE_HOST` (`local` | `sandbox`); serverless
18+
* runtimes always resolve to `sandbox` even if `local` is misconfigured.
1319
*/
1420

1521
import {
@@ -60,18 +66,40 @@ export interface ProvisionedDepositCheckout {
6066
}
6167

6268
/**
63-
* Select the deposit HostKind by CONFIGURATION (not environment): `BITCODE_PIPELINE_HOST`
64-
* (`local` | `sandbox`; `inline` = alias of `local`) chooses which HostKind runs the synthesis pipeline; default
65-
* `local`. (A SandboxHost's provider is `BITCODE_SANDBOX_PROVIDER`, `vercel` | `aws`.)
66-
* Pure + testable; no dev/prod or local/remote semantics.
69+
* True when the process is a deployed serverless runtime (not a laptop dev server).
70+
* Vercel sets `VERCEL=1` / `VERCEL_ENV` on Production and Preview functions.
71+
*/
72+
export function isServerlessPipelineRuntime(
73+
env: NodeJS.ProcessEnv = process.env,
74+
): boolean {
75+
if (env.BITCODE_PIPELINE_RUNTIME?.trim().toLowerCase() === 'serverless') {
76+
return true;
77+
}
78+
if (env.VERCEL === '1') return true;
79+
if (env.VERCEL_ENV === 'production' || env.VERCEL_ENV === 'preview') return true;
80+
if (env.AWS_LAMBDA_FUNCTION_NAME) return true;
81+
return false;
82+
}
83+
84+
/**
85+
* Select deposit HostKind.
86+
*
87+
* - **Serverless:** always `sandbox` (LocalHost cannot run pipelines on Vercel).
88+
* Explicit `BITCODE_PIPELINE_HOST=local` is ignored on serverless.
89+
* - **Local machine:** default `local` (LocalHost); set `BITCODE_PIPELINE_HOST=sandbox`
90+
* to exercise the sandbox path from a laptop (needs Vercel auth).
91+
* - `inline` is a deprecated alias of `local`.
6792
*/
6893
export function selectDepositHostKind(
6994
env: NodeJS.ProcessEnv = process.env,
7095
): BitcodeHostKind {
96+
if (isServerlessPipelineRuntime(env)) {
97+
return 'sandbox';
98+
}
7199
const explicit = env.BITCODE_PIPELINE_HOST?.trim().toLowerCase();
72-
if (explicit === "sandbox") return "sandbox";
73-
// `inline` is a deprecated alias of `local` (LocalHost, formerly LocalHost).
74-
return "local";
100+
if (explicit === 'sandbox') return 'sandbox';
101+
// local | inline | unset → LocalHost on developer machines only
102+
return 'local';
75103
}
76104

77105
/**

uapi/tests/lib/depositSourceProvisioning.test.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,25 @@ describe('provisionDepositSourceInventory (compat full catalog load)', () => {
138138
});
139139

140140
describe('selectDepositHostKind', () => {
141-
it('selects by configured BITCODE_PIPELINE_HOST (default local; env does not auto-select)', () => {
141+
it('uses LocalHost only on local machines; serverless always sandbox', () => {
142+
// Local machine (no Vercel/Lambda markers)
142143
expect(selectDepositHostKind({ BITCODE_PIPELINE_HOST: 'sandbox' } as any)).toBe('sandbox');
143144
expect(selectDepositHostKind({ BITCODE_PIPELINE_HOST: ' Sandbox ' } as any)).toBe('sandbox');
144145
expect(selectDepositHostKind({ BITCODE_PIPELINE_HOST: 'local' } as any)).toBe('local');
145146
expect(selectDepositHostKind({ BITCODE_PIPELINE_HOST: 'inline' } as any)).toBe('local');
146147
expect(selectDepositHostKind({} as any)).toBe('local');
147-
expect(selectDepositHostKind({ VERCEL: '1' } as any)).toBe('local');
148+
149+
// Serverless: always sandbox — LocalHost is never valid here
150+
expect(selectDepositHostKind({ VERCEL: '1' } as any)).toBe('sandbox');
151+
expect(selectDepositHostKind({ VERCEL: '1', BITCODE_PIPELINE_HOST: 'local' } as any)).toBe(
152+
'sandbox',
153+
);
154+
expect(selectDepositHostKind({ VERCEL_ENV: 'production' } as any)).toBe('sandbox');
155+
expect(selectDepositHostKind({ VERCEL_ENV: 'preview' } as any)).toBe('sandbox');
156+
expect(selectDepositHostKind({ AWS_LAMBDA_FUNCTION_NAME: 'fn' } as any)).toBe('sandbox');
157+
expect(
158+
selectDepositHostKind({ BITCODE_PIPELINE_RUNTIME: 'serverless' } as any),
159+
).toBe('sandbox');
148160
});
149161
});
150162

0 commit comments

Comments
 (0)