Add Vercel sandbox provider#700
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Vercel sandbox backend support: Vercel REST client and client tests, bootstrap and base-snapshot tooling with CI integration, full Vercel SandboxProvider with repo-image build flow, DB migration for provider on repo images, lifecycle wiring and tests, Terraform/CI variable binding and conditional snapshot build, frontend capability updates, and documentation. ChangesVercel Sandbox Provider Implementation
DB, Tests, and Migration
Terraform and CI/CD Automation
Web Frontend and API messages
Documentation
Sequence Diagram(s) sequenceDiagram
participant GitHubActions as GitHub Actions (terraform.yml)
participant SnapshotCLI as build-vercel-base-snapshot
participant SnapshotBuilder as buildVercelBaseSnapshot
participant VercelClient as VercelSandboxClient
participant VercelAPI as Vercel Sandbox API
GitHubActions->>SnapshotCLI: run when SANDBOX_PROVIDER=vercel
SnapshotCLI->>SnapshotBuilder: invoke with runtime/repo inputs
SnapshotBuilder->>VercelClient: createSandbox()
VercelClient->>VercelAPI: POST /sandboxes
SnapshotBuilder->>VercelClient: runCommandAndWait(bootstrap)
VercelClient->>VercelAPI: command stream (NDJSON)
SnapshotBuilder->>VercelClient: snapshotSession()
VercelClient->>VercelAPI: POST /snapshots
SnapshotBuilder->>VercelClient: stopSession()
Estimated code review effort 🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/control-plane/src/routes/repo-images.ts (1)
84-112:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winAuthenticate build callbacks before updating D1.
The new Vercel coordinator signs callbacks with
Authorization: Bearer <timestamp>.<hmac>, but neither handler validates that header. Anyone who can guess abuild_idcan mark builds ready/failed, and the success path can cascade into deleting a provider image. Verify the HMAC and timestamp before mutating build state.Also applies to: 176-195
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/control-plane/src/routes/repo-images.ts` around lines 84 - 112, Extract and validate the Authorization header in both handleBuildComplete and the corresponding failure handler (handleBuildFailed) before making any DB mutations: read the raw request body (before parseJsonBody), parse Authorization of form "Bearer <timestamp>.<hmac>", ensure timestamp is within an allowed window (e.g., ±5 minutes), compute an HMAC using the shared coordinator secret from env (e.g., env.COORDINATOR_SECRET) over the same data the coordinator signs (timestamp + "." + rawBody or timestamp + "." + build_id depending on coordinator spec), compare the computed HMAC to the provided one using a constant-time comparison, and return 401 on missing/invalid signature or expired timestamp; only proceed to parseJsonBody and update D1 when validation succeeds.
🧹 Nitpick comments (1)
packages/control-plane/src/sandbox/providers/vercel-provider.ts (1)
477-483: ⚡ Quick winHoist these default command timeouts into named constants.
The new timeout defaults are being restated inline instead of being defined once and reused, which makes drift between provider commands more likely as this file grows.
As per coding guidelines, "Define each default timeout value exactly once as a named constant and import it everywhere rather than restating literal values" and "Do not use bare timeout variable names; always encode the unit (seconds for Python, milliseconds for TypeScript) in the variable name."
Also applies to: 496-501
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/control-plane/src/sandbox/providers/vercel-provider.ts` around lines 477 - 483, Hoist the literal timeout values used in calls like this.client.runCommandAndWait({ sessionId, command: "sudo", args: [...], timeoutMs: 30_000 }) (and the similar call at lines ~496-501) into a named, exported constant (e.g. VERCEL_PROVIDER_COMMAND_TIMEOUT_MS) and import/use that constant instead of the magic number; follow the unit-encoding rule in the constant name (use _MS for TypeScript timeouts). Update all runCommandAndWait invocations in vercel-provider.ts to reference the new constant and remove the inline numeric literals so the default timeout is defined exactly once and reused.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/terraform.yml:
- Around line 312-348: Update the error message in the "Build Vercel base
snapshot" step so it references the actual env var names used elsewhere
(VERCEL_TOKEN and VERCEL_PROJECT_ID) instead of VERCEL_SANDBOX_TOKEN and
VERCEL_SANDBOX_PROJECT_ID; modify the check block that currently echoes
"VERCEL_SANDBOX_TOKEN and VERCEL_SANDBOX_PROJECT_ID are required when
SANDBOX_PROVIDER=vercel" to echo the correct variable names (VERCEL_TOKEN and
VERCEL_PROJECT_ID) so it matches the env keys set and the build script's
requiredEnv calls.
In `@docs/VERCEL_SANDBOX_PROVIDER.md`:
- Line 25: Update the phrasing in the sentence "For GitHub Actions based
deployment, configure the matching repository secrets:" to hyphenate the
compound modifier; change it to "For GitHub Actions-based deployment, configure
the matching repository secrets:" so the compound adjective "GitHub
Actions-based" is clear and grammatically correct.
In `@packages/control-plane/scripts/build-vercel-base-snapshot.ts`:
- Around line 18-25: The script currently allows a missing or invalid --output
value to silently fall back to stdout; modify getArgValue/main so that when
"--output" is present but no following value exists or the following token
starts with "-" (another flag), the script fails fast: detect this condition
after calling getArgValue("--output") in main (or enhance getArgValue to
validate the next token), print a clear error to stderr (including the fact that
--output is missing/invalid) and exit with a non-zero status (e.g., throw or
process.exit(1)) so CI fails instead of continuing.
In `@packages/control-plane/src/sandbox/providers/vercel-provider.ts`:
- Around line 477-485: The remote tunnel-writer invocation using
this.client.runCommandAndWait(...) (with sessionId, VERCEL_PYTHON_BIN and the
script that calls Path.write_text(...)) currently assumes failures will throw;
instead inspect the result returned by runCommandAndWait and fail the launch on
non-zero exit. Modify the caller around runCommandAndWait to capture its return
value (exitCode / status / stdout/stderr fields), check for a non-zero exit code
or error status, log the remote stderr with context, and throw or return an
error so sandbox launch stops when Path.write_text(...) fails.
- Around line 705-721: The happy-path for event "image_build.complete" snapshots
and calls callback but never shuts down the running sandbox, leaving proc alive
until BUILD_TIMEOUT_SECONDS; after snapshot_session() and before returning,
explicitly stop the session by terminating proc (use
proc.send_signal(signal.SIGTERM) then wait with a short timeout and fall back to
proc.kill() and wait) or call the provider's existing cleanup API (e.g.,
stopSandbox/stopSession) to release resources, and ensure any teardown succeeds
before returning from the handler.
- Around line 309-322: The PATH is hard-coded to /vercel/runtimes/node24/bin in
the env construction (Object.assign block) causing mismatched runtime when
this.providerConfig.runtime (or VERCEL_RUNTIME) differs; update the env builders
that set PATH (the block that assigns HOME, NODE_ENV, PATH, etc., and the
similar block around lines 356-377) to interpolate the configured runtime
instead of node24—use this.providerConfig.runtime (or
config.runtime/VERCEL_RUNTIME) to build the runtimePath (e.g.,
`/vercel/runtimes/${runtime}/bin`) and use that value for PATH so the sandbox
runtime and PATH remain consistent.
- Around line 366-376: The sandbox-wide env currently exposes sensitive
Vercel/control-plane secrets (OI_INTERNAL_CALLBACK_SECRET, OI_VERCEL_TOKEN) via
buildBuildEnvVars(), making them visible to repo builds run by
buildCoordinatorScript(); remove these keys from the sandbox-level environment
and instead inject them only into the coordinator/process that performs remote
API callbacks (e.g., pass secrets into the coordinator runtime or a dedicated
callback handler) so repo build env (env=os.environ.copy() used in
buildCoordinatorScript()) never contains OI_INTERNAL_CALLBACK_SECRET or
OI_VERCEL_TOKEN; update buildBuildEnvVars() to omit those two keys (and the same
for the other occurrences called out), and wire secret access into the specific
functions that perform callback/API calls rather than the repo build
environment.
In `@packages/control-plane/src/sandbox/vercel-bootstrap.ts`:
- Line 73: The generated git credential helper script incorrectly references the
shell variable ${VERCEL_PYTHON_BIN} (a build-time TypeScript constant) which is
not defined at runtime; update the script generation so it embeds the actual
Python binary path value instead of the shell variable. Specifically, change the
string written to /usr/local/bin/oi-git-credentials in the code that constructs
that script so the command uses the resolved VERCEL_PYTHON_BIN constant (the
build-time value) and still calls -m
sandbox_runtime.credentials.git_credential_helper "$@" — ensure the resulting
script contains the hardcoded path rather than a ${...} shell variable
reference.
In `@packages/control-plane/src/sandbox/vercel-client.ts`:
- Around line 236-274: The requestText function currently buffers the entire
response body (in requestText) which causes memory exhaustion for NDJSON command
streams; change requestText to consume response.body as a stream (use
response.body.getReader() or a streaming text/NDJSON parser) and process chunks
incrementally, splitting on newlines, parsing each JSON envelope as it arrives,
retaining only the most recent envelope with envelope.type === "command" (or the
"command" field) and discarding prior ones, and if response.ok is false still
read/skips the streamed body then throw VercelSandboxApiError with the captured
status and last error text; ensure headers and error handling logic around
VercelSandboxApiError and httpStatus remain unchanged.
In `@packages/control-plane/src/session/durable-object.ts`:
- Around line 764-766: RepoImageLookup currently only stores provider_image_id
and base_sha which lets SandboxLifecycleManager call the wrong provider after
SANDBOX_PROVIDER changes; update persistence and lookup logic so RepoImageLookup
includes the backend/provider identifier (e.g., provider_name or backend enum)
and ensure code paths that populate or read repoImageLookup (the block guarded
by supportsRepoImageBackend and any callers in SandboxLifecycleManager) filter
by that backend or delete incompatible rows before using the opaque
provider_image_id; also add migration/cleanup logic when reading existing rows
to clear or ignore entries whose stored backend does not match the active
SANDBOX_PROVIDER.
---
Outside diff comments:
In `@packages/control-plane/src/routes/repo-images.ts`:
- Around line 84-112: Extract and validate the Authorization header in both
handleBuildComplete and the corresponding failure handler (handleBuildFailed)
before making any DB mutations: read the raw request body (before
parseJsonBody), parse Authorization of form "Bearer <timestamp>.<hmac>", ensure
timestamp is within an allowed window (e.g., ±5 minutes), compute an HMAC using
the shared coordinator secret from env (e.g., env.COORDINATOR_SECRET) over the
same data the coordinator signs (timestamp + "." + rawBody or timestamp + "." +
build_id depending on coordinator spec), compare the computed HMAC to the
provided one using a constant-time comparison, and return 401 on missing/invalid
signature or expired timestamp; only proceed to parseJsonBody and update D1 when
validation succeeds.
---
Nitpick comments:
In `@packages/control-plane/src/sandbox/providers/vercel-provider.ts`:
- Around line 477-483: Hoist the literal timeout values used in calls like
this.client.runCommandAndWait({ sessionId, command: "sudo", args: [...],
timeoutMs: 30_000 }) (and the similar call at lines ~496-501) into a named,
exported constant (e.g. VERCEL_PROVIDER_COMMAND_TIMEOUT_MS) and import/use that
constant instead of the magic number; follow the unit-encoding rule in the
constant name (use _MS for TypeScript timeouts). Update all runCommandAndWait
invocations in vercel-provider.ts to reference the new constant and remove the
inline numeric literals so the default timeout is defined exactly once and
reused.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7baa04ca-d251-4aad-84cc-602580fa6bf8
📒 Files selected for processing (35)
.github/workflows/terraform.ymldocs/GETTING_STARTED.mddocs/HOW_IT_WORKS.mddocs/IMAGE_PREBUILD.mddocs/SECRETS.mddocs/VERCEL_SANDBOX_PROVIDER.mdpackages/control-plane/package.jsonpackages/control-plane/scripts/build-vercel-base-snapshot.tspackages/control-plane/src/routes/repo-images.tspackages/control-plane/src/sandbox/index.tspackages/control-plane/src/sandbox/lifecycle/manager.test.tspackages/control-plane/src/sandbox/lifecycle/manager.tspackages/control-plane/src/sandbox/provider-name.test.tspackages/control-plane/src/sandbox/provider-name.tspackages/control-plane/src/sandbox/providers/vercel-provider.test.tspackages/control-plane/src/sandbox/providers/vercel-provider.tspackages/control-plane/src/sandbox/vercel-base-snapshot.test.tspackages/control-plane/src/sandbox/vercel-base-snapshot.tspackages/control-plane/src/sandbox/vercel-bootstrap.tspackages/control-plane/src/sandbox/vercel-client.test.tspackages/control-plane/src/sandbox/vercel-client.tspackages/control-plane/src/session/durable-object.tspackages/control-plane/src/types.tspackages/web/src/app/api/repo-images/[owner]/[name]/toggle/route.tspackages/web/src/app/api/repo-images/[owner]/[name]/trigger/route.tspackages/web/src/app/api/repo-images/route.tspackages/web/src/components/settings/images-settings.tsxpackages/web/src/lib/sandbox-provider.test.tspackages/web/src/lib/sandbox-provider.tsterraform/README.mdterraform/environments/production/locals.tfterraform/environments/production/outputs.tfterraform/environments/production/terraform.tfvars.exampleterraform/environments/production/variables.tfterraform/environments/production/workers-control-plane.tf
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
|
Addressed the two review-body items in fffcd32:
|
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
|
Addressed the Vercel runtime-source parity concern in d9163fd. The managed base snapshot now archives the checked-out local packages/sandbox-runtime package and uploads it into the temporary Vercel sandbox before bootstrap, so the snapshot is built from the same commit/workspace as the deployed control plane. I also removed the VERCEL_RUNTIME_REPO_URL / VERCEL_RUNTIME_REPO_REF Terraform, Worker, workflow, and docs surface entirely, and Vercel fresh sessions now require either a repo image snapshot or the managed base-runtime snapshot. |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/control-plane/src/sandbox/providers/vercel-provider.ts (1)
38-38: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winRename
BUILD_TIMEOUT_SECONDStoBUILD_TIMEOUT_MSand store the value in milliseconds.As per coding guidelines, TypeScript timeout constants should use milliseconds and encode the unit with
_MSortimeoutMs. The current constant uses_SECONDSand requires multiplication at the call site (line 244:BUILD_TIMEOUT_SECONDS * 1000), which violates the guideline to "Define each default timeout value exactly once as a named constant and import it everywhere rather than restating literal values."♻️ Proposed fix
-const BUILD_TIMEOUT_SECONDS = 1800; +const BUILD_TIMEOUT_MS = 1800 * 1000; const VERCEL_TUNNEL_ENV_WRITE_TIMEOUT_MS = 30_000;Then update line 244:
- timeoutMs: BUILD_TIMEOUT_SECONDS * 1000, + timeoutMs: BUILD_TIMEOUT_MS,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/control-plane/src/sandbox/providers/vercel-provider.ts` at line 38, Rename the constant BUILD_TIMEOUT_SECONDS to BUILD_TIMEOUT_MS and change its value to milliseconds (1800 seconds → 1_800_000) so timeouts are defined in ms; then update all places that multiply BUILD_TIMEOUT_SECONDS by 1000 (e.g., where BUILD_TIMEOUT_SECONDS * 1000 is used) to use BUILD_TIMEOUT_MS directly, ensuring any exports/imports or references to BUILD_TIMEOUT_SECONDS are updated to the new name BUILD_TIMEOUT_MS.Source: Coding guidelines
🧹 Nitpick comments (1)
packages/control-plane/src/sandbox/vercel-bootstrap.ts (1)
81-83: ⚡ Quick winExtract the duplicated
shellQuotehelper to a shared utility module.The
shellQuotefunction is identical in bothvercel-bootstrap.ts(lines 81-83) andvercel-base-snapshot.ts(lines 166-168). Extract it to a shared module (e.g.,sandbox/shell-utils.ts) and import it in both files to avoid duplication and maintain a single source of truth.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/control-plane/src/sandbox/vercel-bootstrap.ts` around lines 81 - 83, Extract the duplicated shellQuote function into a single shared utility (e.g., sandbox/shell-utils.ts) and replace the local implementations in vercel-bootstrap.ts and vercel-base-snapshot.ts with an import of that shared shellQuote; ensure the exported helper signature remains: function shellQuote(value: string): string, update both files to import and use shellQuote instead of their inline copies, and run tests/build to verify no import/export type issues.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@packages/control-plane/src/sandbox/providers/vercel-provider.ts`:
- Line 38: Rename the constant BUILD_TIMEOUT_SECONDS to BUILD_TIMEOUT_MS and
change its value to milliseconds (1800 seconds → 1_800_000) so timeouts are
defined in ms; then update all places that multiply BUILD_TIMEOUT_SECONDS by
1000 (e.g., where BUILD_TIMEOUT_SECONDS * 1000 is used) to use BUILD_TIMEOUT_MS
directly, ensuring any exports/imports or references to BUILD_TIMEOUT_SECONDS
are updated to the new name BUILD_TIMEOUT_MS.
---
Nitpick comments:
In `@packages/control-plane/src/sandbox/vercel-bootstrap.ts`:
- Around line 81-83: Extract the duplicated shellQuote function into a single
shared utility (e.g., sandbox/shell-utils.ts) and replace the local
implementations in vercel-bootstrap.ts and vercel-base-snapshot.ts with an
import of that shared shellQuote; ensure the exported helper signature remains:
function shellQuote(value: string): string, update both files to import and use
shellQuote instead of their inline copies, and run tests/build to verify no
import/export type issues.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f020d06c-51b2-41e6-8048-c7c3ef03814c
📒 Files selected for processing (19)
.github/workflows/terraform.ymldocs/GETTING_STARTED.mddocs/VERCEL_SANDBOX_PROVIDER.mdpackages/control-plane/scripts/build-vercel-base-snapshot.tspackages/control-plane/src/routes/repo-images.tspackages/control-plane/src/sandbox/index.tspackages/control-plane/src/sandbox/providers/vercel-provider.test.tspackages/control-plane/src/sandbox/providers/vercel-provider.tspackages/control-plane/src/sandbox/vercel-base-snapshot.test.tspackages/control-plane/src/sandbox/vercel-base-snapshot.tspackages/control-plane/src/sandbox/vercel-bootstrap.tspackages/control-plane/src/sandbox/vercel-client.test.tspackages/control-plane/src/sandbox/vercel-client.tspackages/control-plane/src/session/durable-object.tspackages/control-plane/src/types.tsterraform/README.mdterraform/environments/production/terraform.tfvars.exampleterraform/environments/production/variables.tfterraform/environments/production/workers-control-plane.tf
💤 Files with no reviewable changes (6)
- packages/control-plane/src/types.ts
- terraform/environments/production/workers-control-plane.tf
- terraform/environments/production/variables.tf
- terraform/README.md
- packages/control-plane/src/session/durable-object.ts
- packages/control-plane/src/routes/repo-images.ts
✅ Files skipped from review due to trivial changes (1)
- docs/VERCEL_SANDBOX_PROVIDER.md
🚧 Files skipped from review as they are similar to previous changes (5)
- terraform/environments/production/terraform.tfvars.example
- .github/workflows/terraform.yml
- packages/control-plane/src/sandbox/vercel-client.test.ts
- packages/control-plane/src/sandbox/vercel-base-snapshot.test.ts
- docs/GETTING_STARTED.md
|
Moved the Vercel base snapshot build into Terraform in 789190e. The workflow no longer has a separate "Build Vercel base snapshot" step; instead, production Terraform now has a vercel_sandbox_infra module that hashes local packages/sandbox-runtime plus the Vercel builder/bootstrap files, runs a module script to build the managed snapshot from var.project_root, and passes a deterministic VERCEL_BASE_SNAPSHOT_NAME to the Worker. The control plane resolves that name to the latest created Vercel snapshot ID at sandbox creation time, while VERCEL_BASE_SNAPSHOT_ID remains as a manual override that skips the managed build. |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
|
Performed a dead-code / stale-reference pass after the Terraform-managed Vercel snapshot changes. Cleanup committed in
Reference scans did not find remaining PR-specific runtime repo/ref plumbing, stale workflow snapshot outputs, or unused Validation:
|
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
) ## Summary Groups the Vercel sandbox modules added in #700 into a dedicated `packages/control-plane/src/sandbox/providers/vercel/` directory and drops the redundant `vercel-` filename prefix. Previously the Vercel files were split between the top of `sandbox/` (client, bootstrap, base-snapshot) and `sandbox/providers/` (the provider). ## Structure ``` src/sandbox/providers/vercel/ ├── provider.ts (was providers/vercel-provider.ts) ├── provider.test.ts ├── client.ts (was vercel-client.ts) ├── client.test.ts ├── bootstrap.ts (was vercel-bootstrap.ts) ├── base-snapshot.ts (was vercel-base-snapshot.ts) └── base-snapshot.test.ts ``` ## Why under `providers/` (not `sandbox/vercel/`) Keeping the provider under `providers/` preserves that directory as the home for every provider and establishes a per-provider convention (`providers/<name>/`) that Modal and Daytona can adopt later, leaving top-level `sandbox/` for cross-provider concerns (`provider.ts` interface, `provider-name.ts`, `index.ts`, `lifecycle/`). ## Scope / notes - Pure move + import-path update. **No exported symbols change**, so the `sandbox` barrel's public API is identical. - All 7 files moved via `git mv` (renames detected at 96–100% similarity, history preserved). - Import specifiers updated in 5 consumers: the sandbox barrel (`index.ts`), `routes/repo-images.ts` (+ test, including the `vi.mock` path string), `session/durable-object.ts`, and `scripts/build-vercel-base-snapshot.ts`. - Modal/Daytona providers intentionally left as flat files for now — a follow-up can nest them into `providers/modal/` and `providers/daytona/` for full symmetry. - No changes needed to `package.json`, Terraform, CI, or docs (verified — no hardcoded module paths; snapshot bundle output stays `dist/vercel-base-snapshot.js`). ## Validation - `npm run typecheck -w @open-inspect/control-plane` - `npm run lint -w @open-inspect/control-plane` - `npm test -w @open-inspect/control-plane` — 77 files, **1257 tests passed** - `npm run build:vercel-base-snapshot -w @open-inspect/control-plane` - `npm run build -w @open-inspect/control-plane` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Internal reorganization of Vercel sandbox provider and client modules and related imports. No changes to user-facing functionality or behavior. * Updated tests and build/infra reference inputs to align with the new module layout; test behavior and runtime behavior remain unchanged. * Re-exports adjusted to reflect the new internal structure without altering public APIs. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
VERCEL_BASE_SNAPSHOT_NAMEwired into the control planeNotes
The provider intentionally leaves Vercel sandbox resources unset. Vercel therefore uses its default sandbox size, currently observed as 2 vCPU / 4 GB RAM. Resource sizing can be added later by threading a
resources.vcpusvalue through the Vercel create-sandbox request.vercel_base_snapshot_idremains as a manual override. When it is unset andsandbox_provider = "vercel", Terraform builds the managed base-runtime snapshot from the local checkout as part of the normal sandbox infrastructure apply.Vercel repo-image build sandboxes do not receive
INTERNAL_CALLBACK_SECRET. They receive a random 64-hex per-build callback token whose hash is stored in D1 and consumed only after the callback'sbuild_idandprovider_session_idmatch the registered building row.The repo-image callback endpoints are public only at the global router layer so provider runtimes can reach them. The route handlers still authenticate callbacks themselves: Modal with the existing internal HMAC, Vercel with the scoped callback token plus the bound Vercel session ID. Successful Vercel repo-image build sessions are stopped after the control plane snapshots the completed build.
Validation
npm cinpm run build -w @open-inspect/sharednpm test -w @open-inspect/control-plane -- src/sandbox/vercel-base-snapshot.test.ts src/sandbox/providers/vercel-provider.test.ts src/sandbox/vercel-client.test.ts src/sandbox/provider-name.test.ts src/sandbox/lifecycle/manager.test.tsnpm test -w @open-inspect/web -- src/lib/sandbox-provider.test.tsnpm run build:vercel-base-snapshot -w @open-inspect/control-planenpm run typecheck -w @open-inspect/control-planenpm run lint -w @open-inspect/control-planenpm run build -w @open-inspect/control-planenpm run typecheck -w @open-inspect/webnpm run lint -w @open-inspect/webterraform fmt -check -recursive terraformterraform -chdir=terraform/environments/production validate -no-colornpm test -w @open-inspect/control-plane -- src/db/repo-images.test.ts src/routes/repo-images.test.ts src/sandbox/providers/vercel-provider.test.tsnpm run test:integration -w @open-inspect/control-plane -- test/integration/repo-images.test.tsuv run --extra dev pytest tests/test_repo_image_callback.py tests/test_entrypoint_build_mode.py -qfrompackages/sandbox-runtimeuv run --extra dev ruff check src/sandbox_runtime/repo_image_callback.py tests/test_repo_image_callback.pyfrompackages/sandbox-runtimegit diff --checkNote: local Terraform validation required a temporary darwin_arm64 Cloudflare provider checksum from
terraform init; that lock-file change was removed before commit.