Skip to content

promote: test → main (build-org-snapshot workflow + Vercel Workflow runtime)#532

Merged
sweetmantech merged 1 commit intomainfrom
test
May 7, 2026
Merged

promote: test → main (build-org-snapshot workflow + Vercel Workflow runtime)#532
sweetmantech merged 1 commit intomainfrom
test

Conversation

@sweetmantech
Copy link
Copy Markdown
Contributor

@sweetmantech sweetmantech commented May 7, 2026

Promotes the build-org-snapshot workflow port (and the Vercel Workflow runtime integration that landed alongside it) from test to main.

What lands on main

  • feat(sandbox): port buildOrgSnapshotWorkflow + Vercel Workflow runtime (feat(sandbox): port buildOrgSnapshotWorkflow + Vercel Workflow runtime #531, squash-merged into test as 05f321d4)
  • First Vercel Workflow integration in api: workflow package + withWorkflow(nextConfig)
  • app/workflows/buildOrgSnapshotWorkflow.ts + buildSnapshotStep.ts (SRP-split, shellEscape on cloneUrl, no URL in logs)
  • Recoup-team base snapshot built and committed (snap_RgVtpDO4y1BJHQiUbptMwS3Rt2EQ) with documented refresh procedure
  • Wired into createSandboxHandler to fire on recoupable misses

Verification

Out of scope (still missing from cutover)

  • Phase 2: sandboxLifecycleWorkflow (auto-pause + status-check-overdue) — bigger lift, separate PR
  • gitUser plumbing
  • hibernate_after derivation

🤖 Generated with Claude Code


Summary by cubic

Promotes the org snapshot build workflow and Vercel Workflow runtime to main, so we auto-build a per‑org base snapshot on a miss and future sessions warm‑boot. This reduces cold-start clone time for recoupable org repos.

  • New Features

    • Added app/workflows/buildOrgSnapshotWorkflow.ts + buildSnapshotStep.ts using Vercel Workflows (workflow) and enabled via withWorkflow(nextConfig).
    • Hooked into createSandboxHandler to kick a background build on a recoupable miss; current request proceeds cold, the next warms from the new snapshot.
    • Introduced DEFAULT_SANDBOX_BASE_SNAPSHOT_ID (env override: VERCEL_SANDBOX_BASE_SNAPSHOT_ID) pointing to the recoup-team snapshot with documented refresh steps.
    • Added tests to verify kick-on-miss, no-kick on hit, and no-kick for non-recoupable repos.
  • Bug Fixes

    • Escaped cloneUrl with shellEscape in the git clone command to prevent injection.
    • Removed URLs from workflow logs to avoid leaking embedded credentials; only sandboxName is logged.

Written for commit 05f321d. Summary will update on new commits.

#531)

* feat(sandbox): port buildOrgSnapshotWorkflow + Vercel Workflow runtime

Closes the biggest remaining cutover gap: when a recoupable org repo
is requested via POST /api/sandbox and no snapshot exists yet, fire a
durable background workflow that builds one. The current request still
pays the slow full-clone path; what's protected is that *future*
sessions for the same org warm-boot from the new snapshot in seconds.

This is the first Vercel Workflow integration in api. Per the
direction of using Vercel Workflow as the workflow runner going
forward (deprecating Trigger.dev over time), this PR also lands the
infra: the `workflow` package, `withWorkflow(nextConfig)` wrapper, and
the `app/workflows/` convention.

Files:
- `next.config.ts` — wraps the config with `withWorkflow` from
  `workflow/next` so workflow files (with `"use workflow"` /
  `"use step"` directives) are deployable
- `app/workflows/buildOrgSnapshot.ts` — preserves the open-agents
  workflow code structure exactly. One step that calls api's existing
  `refreshBaseSnapshot` (inlined via PR #507) to provision a sandbox
  named `<orgRepoName>`, run `git clone --depth=1 <cloneUrl>`, and
  snapshot the result
- `lib/sandbox/kickBuildOrgSnapshotWorkflow.ts` — fire-and-forget
  invocation via `start(buildOrgSnapshotWorkflow, [input])` from
  `workflow/api`. Failures are logged but never surface in the
  request — the request always falls back to the slow full-clone path
- `lib/sandbox/defaultBaseSnapshotId.ts` — `DEFAULT_SANDBOX_BASE_SNAPSHOT_ID`
  constant, env-overridable. Used by the build workflow as the base
  image (bun + jq + agent-browser + chromium + code-server) so the
  workflow only does the clone, not the runtime install
- `lib/sandbox/createSandboxHandler.ts` — wired in: when
  `extractOrgRepoName` returns non-null and `findOrgSnapshot` misses,
  kick the workflow

TDD red -> green:
- 3 new createSandboxHandler tests:
  - kicks the workflow on recoupable miss with the right input
  - does NOT kick when an existing snapshot is found (hit case)
  - does NOT kick for non-recoupable repos
- All existing tests pass (the mock for kickBuildOrgSnapshotWorkflow
  is no-op so unchanged tests don't see the kick)
- Suite: 2574 -> 2577 (+3). pnpm lint:check + tsc --noEmit clean.

Phase 2 (sandboxLifecycleWorkflow + evaluateSandboxLifecycle) follows
in a separate PR — that one's much bigger and ports the stateful
auto-pause / status-check-overdue logic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(sandbox): point base snapshot id at the recoup-team-built snapshot

The previous hardcoded id (snap_EjsphVxi07bFKrfojljJdIS41KHT) lived in
open-agents' Vercel team and returned 404 from api's project, breaking
the build-org-snapshot workflow on its first step.

Built a recoup-team equivalent snapshot manually via the @vercel/sandbox
SDK by provisioning a clean Amazon Linux 2023 sandbox and running:

  - sudo dnf install -y jq
  - curl -fsSL https://bun.sh/install | sudo BUN_INSTALL=/usr/local bash
  - sudo npm install -g agent-browser
  - curl -fsSL https://code-server.dev/install.sh | sudo sh

Then snapshotted via `vercel sandbox snapshot <id> --stop`. Result:
snap_RgVtpDO4y1BJHQiUbptMwS3Rt2EQ.

Tooling note (in the file comment): chromium is intentionally NOT in
this base. Amazon Linux 2023's default repo doesn't carry it, and
agent-browser fetches a managed Playwright browser on first use, so
having it in the base would just bloat the image.

The header comment now also documents the install commands and
refresh procedure so the next person who needs to add tooling has a
clear path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(sandbox): SRP split + shellEscape cloneUrl + drop URL from logs

Three review fixes bundled:

1) SRP per sweetmantech: split app/workflows/buildOrgSnapshot.ts into
   - app/workflows/buildSnapshotStep.ts (the "use step" function)
   - app/workflows/buildOrgSnapshotWorkflow.ts (the "use workflow"
     function — filename now matches the export, addressing the
     cubic P2 about filename mismatch)

2) P0 command injection (cubic): wrap cloneUrl with shellEscape() in
   the `git clone --depth=1 ...` command. The Zod + parseGitHubRepoUrl
   validators upstream of this workflow already reject anything that
   doesn't match `^https:\/\/github\.com\/recoupable\/...`, so this
   isn't exploitable today — but shell-escaping is defense-in-depth
   that survives validator changes. Zero behavior change for valid
   inputs (extra single quotes around an already-clean URL).

3) P1 credential leak (cubic): dropped `cloneUrl` from every log line
   in the workflow + kick. The `https://user:token@github.com/...`
   shape is also blocked by the regex validator, but log scrubbing
   is the cheaper of the two layers if the validator ever loosens.
   `sandboxName` (the regex-extracted repo name only) remains in logs
   — uniquely identifies the org for observability without
   exposing tokens.

Out of scope: cubic's P2 about duplicate workflow runs (same
fire-and-forget pattern as open-agents — duplicates are wasteful but
not incorrect; can add a Vercel Workflow idempotency key in a
follow-up if observed in practice).

Tests: existing handler tests still pass unchanged (the kick is mocked
at the lib path, which didn't change). Suite remains 2577 / 2577.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
api Building Building Preview May 7, 2026 9:23pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Warning

Rate limit exceeded

@sweetmantech has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 47 minutes and 27 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4c856034-0e08-49ea-8bdd-4a96df65b6d1

📥 Commits

Reviewing files that changed from the base of the PR and between cdc9e5f and 05f321d.

⛔ Files ignored due to path filters (4)
  • lib/sandbox/__tests__/createSandboxHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • next.config.ts is excluded by none and included by none
  • package.json is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
📒 Files selected for processing (5)
  • app/workflows/buildOrgSnapshotWorkflow.ts
  • app/workflows/buildSnapshotStep.ts
  • lib/sandbox/createSandboxHandler.ts
  • lib/sandbox/defaultBaseSnapshotId.ts
  • lib/sandbox/kickBuildOrgSnapshotWorkflow.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sweetmantech sweetmantech merged commit 6efdd99 into main May 7, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant