Skip to content

Add world.snapshots storage interface (local, postgres, vercel) - #3050

Draft
TooTallNate wants to merge 1 commit into
quickjs-vm-perffrom
quickjs-vm-snapshots
Draft

Add world.snapshots storage interface (local, postgres, vercel)#3050
TooTallNate wants to merge 1 commit into
quickjs-vm-perffrom
quickjs-vm-snapshots

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Stacked PR — based on #3049 (quickjs-vm-perf), which is based on #3048 (quickjs-vm). Review only the top commit here until the bases merge.

Summary

PR 3 of the QuickJS VM roadmap: the world.snapshots storage interface and its implementations, ported from the original snapshot-runtime branch (#1300). Inert until PR 4 — nothing in the runtime calls these APIs yet.

What's included

  • @workflow/world: Storage.snapshots interface — save(runId, data, metadata) / load(runId) / delete(runId) — plus SnapshotMetadata (eventsCursor, createdAt). The cursor is storage-layer metadata stored alongside the opaque snapshot bytes so a restore only fetches events recorded after the snapshot.
  • @workflow/world-local: filesystem storage under {basedir}/snapshots/ ({runId}.bin + {runId}.json sidecar), with round-trip unit tests.
  • @workflow/world-postgres: workflow_snapshots table (migration 0016, renumbered from the original branch to follow main's 00120015).
  • @workflow/world-vercel: client for the workflow-server snapshot endpoints (PUT/GET/DELETE /v2/runs/:runId/snapshot, binary body + metadata headers — endpoints are live in workflow-server since vercel/workflow-server#339). Includes:
    • the undici.request() (not fetch()) PUT path so Buffer bodies survive RetryAgent retries (Retry Handler Fails When Request Has a Body nodejs/undici#3288),
    • explicit W3C trace-context injection on all three request paths (they route around makeRequest, per the repo's trace-propagation rule), covered by new trace-propagation.test.ts cases.

Notes

  • Bytes are transported opaquely: compression/encryption is @workflow/core's responsibility (PR 4's save pipeline); worlds must not add their own compression (ciphertext doesn't compress).
  • Adding a required member to Storage is a breaking change for community World implementations — appropriate for the v5 beta line; called out in the changeset.
  • The always-on WORLD_SNAPSHOT_DIAG warn logging from the original branch was demoted to console.debug.

@changeset-bot

changeset-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1e0b6e6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 20 packages
Name Type
@workflow/world Minor
@workflow/world-local Minor
@workflow/world-postgres Minor
@workflow/world-vercel Minor
@workflow/cli Patch
@workflow/core Patch
@workflow/vitest Patch
@workflow/web-shared Patch
@workflow/web Patch
@workflow/world-testing Patch
@workflow/builders Patch
workflow Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/nuxt Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment Jul 22, 2026 10:36am
example-nextjs-workflow-webpack Ready Ready Preview, Comment Jul 22, 2026 10:36am
example-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-astro-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-express-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-fastify-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-hono-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-nestjs-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-nitro-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-nuxt-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-sveltekit-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-tanstack-start-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workbench-vite-workflow Ready Ready Preview, Comment Jul 22, 2026 10:36am
workflow-docs Ready Ready Preview, Comment, Open in v0 Jul 22, 2026 10:36am
workflow-swc-playground Ready Ready Preview, Comment Jul 22, 2026 10:36am
workflow-tarballs Ready Ready Preview, Comment Jul 22, 2026 10:36am
workflow-web Ready Ready Preview, Comment Jul 22, 2026 10:36am

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 1455 0 239 1694
✅ 💻 Local Development 270 0 38 308
✅ 📦 Local Production 270 0 38 308
✅ 🐘 Local Postgres 270 0 38 308
✅ 🪟 Windows 154 0 0 154
✅ 📋 Other 252 0 56 308
✅ vercel-multi-region 27 0 0 27
Total 2698 0 409 3107

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 126 0 28
✅ example 126 0 28
✅ express 126 0 28
✅ fastify 126 0 28
✅ hono 126 0 28
✅ nextjs-turbopack 151 0 3
✅ nextjs-webpack 151 0 3
✅ nitro 126 0 28
✅ nuxt 126 0 28
✅ sveltekit 145 0 9
✅ vite 126 0 28
✅ 💻 Local Development
App Passed Failed Skipped
✅ nextjs-turbopack-canary 135 0 19
✅ nextjs-webpack-canary 135 0 19
✅ 📦 Local Production
App Passed Failed Skipped
✅ nextjs-turbopack-canary 135 0 19
✅ nextjs-webpack-canary 135 0 19
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ nextjs-turbopack-canary 135 0 19
✅ nextjs-webpack-canary 135 0 19
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 154 0 0
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-vercel-prod-nest 126 0 28
✅ e2e-vercel-prod-tanstack-start 126 0 28
✅ vercel-multi-region
App Passed Failed Skipped
✅ nextjs-turbopack 27 0 0

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: success
  • Local Dev: failure
  • Local Prod: failure
  • Local Postgres: failure
  • Windows: success

Check the workflow run for details.

*/
export function createSnapshotsStorage(basedir: string) {
const snapshotsDir = path.join(basedir, 'snapshots');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

snapshots-storage.ts builds filesystem paths from an untrusted runId without validation, allowing path traversal outside the {basedir}/snapshots/ directory in save/load/delete.

Fix on Vercel

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