Skip to content

feat(integrations): add Vercel World integrations - #5460

Merged
NathanFlurry merged 2 commits into
mainfrom
eve-rivet
Jul 22, 2026
Merged

feat(integrations): add Vercel World integrations#5460
NathanFlurry merged 2 commits into
mainfrom
eve-rivet

Conversation

@NathanFlurry

Copy link
Copy Markdown
Member
  • Add the Rivet World implementation for Vercel Workflow SDK and Eve.
  • Add a native end-to-end Vercel Workflow example and code-first integration guides.
  • Link Eve sandboxing to the canonical agentOS example without adding a cross-repository dependency.
  • Add the integrations catalog and website documentation.

@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 10:40 Destroyed
@railway-app

railway-app Bot commented Jul 22, 2026

Copy link
Copy Markdown

🚅 Deployed to the rivet-pr-5460 environment in rivet-frontend

Service Status Web Updated (UTC)
kitchen-sink 😴 Sleeping (View Logs) Web Jul 22, 2026 at 1:23 pm
frontend-inspector 😴 Sleeping (View Logs) Web Jul 22, 2026 at 1:23 pm
frontend-cloud 😴 Sleeping (View Logs) Web Jul 22, 2026 at 1:21 pm
website 😴 Sleeping (View Logs) Web Jul 22, 2026 at 1:21 pm
mcp-hub ✅ Success (View Logs) Web Jul 22, 2026 at 1:13 pm
ladle ✅ Success (View Logs) Web Jul 22, 2026 at 10:43 am

@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 11:06 Destroyed
@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 11:49 Destroyed
@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 11:51 Destroyed
@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 11:53 Destroyed
@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 11:54 Destroyed
@claude

claude Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review: PR #5460 — feat(integrations): add Vercel World integrations

Reviewed the full diff (102 files, ~13.3k additions) covering the new integrations/vercel-world package (Rivet-Actor-backed storage for the Vercel Workflow SDK), the supporting rivetkit-core/NAPI/TypeScript registry + migrations infrastructure, the examples/vercel-workflow sample app, and the website/docs/CI changes.

Overall this is a well-structured, thoroughly-tested integration. The event-sourcing design in workflow-run.ts (revision-gated upserts, partial-unique-index dedup on creation events, terminal-state guards, durable-timer-with-backstop wake scheduling) is sound, and the test suite is unusually strong for a first PR of this size — real SQLite, real HTTP, real actor runtime, no vi.mock/module mocking anywhere. A few concrete issues below, roughly ranked by severity.

Bugs

  1. Build-breaking content lookup in website/src/pages/integrations/index.astro

    const entry = await getEntry('docs', 'integrations');

    The actual Astro content-collection ID for website/src/content/docs/integrations/index.mdx is integrations/index, not integrations — the sibling [...slug].astro route confirms this by explicitly excluding entry.id !== 'integrations/index', and the existing getContentSlugPath() helper elsewhere in the codebase strips the same /index suffix pattern. As written, getEntry won't match and the route throws Missing integrations index content at build/render time. Should be getEntry('docs', 'integrations/index').

  2. Fault-injection env vars in integrations/vercel-world/src/actors/streams.ts aren't gated to test mode, unlike their siblings. shouldDropBroadcast (RIVET_WORLD_RIVET_INJECT_BROADCAST_DROP_RATE) and injectReadDelay (RIVET_WORLD_RIVET_INJECT_STREAM_READ_DELAY_MS) run unconditionally in the production stream-append/read path, whereas forceStaleInflightForTesting and expireClosedStreamForTesting correctly require RIVET_WORLD_RIVET_TESTING === "1" before doing anything. A stray env var in a real deployment would silently drop broadcasts or add latency with no interlock. Worth adding the same testing gate for consistency with the fail-by-default convention.

  3. drainPendingOps in workflow-run.ts swallows the real error on failure (bare catch {} around the coordinator/hook-token RPC call) and requeues with capped exponential backoff forever — there's no terminal/dead-letter state for pending_ops (its status column is CHECK (status IN ('ready','inflight')), no failed). Contrast with dispatcher_queue, which has MAX_DISPATCH_ATTEMPTS and a failDispatch terminal path. A permanently broken payload (or a real bug in coordinator.update/hookToken.confirm) retries silently every ≤30s forever with zero operator visibility. At minimum this catch should debugLog the error.

  4. Possible race in coordinator.ts's ownership checks. updateCorrelation/updateHook validate ownership with a SELECT followed by a separate INSERT ... ON CONFLICT DO UPDATE, but the ON CONFLICT WHERE clause only gates on run_revision/status, not on the pre-checked run_id/kind match. This differs from hook-token.ts's reserve, which does a true compare-and-swap in the mutating statement's WHERE clause. If the actor's transaction isn't taking an immediate write lock across the read-then-write, two concurrent coordinator.update calls with conflicting runIds could race past the "already owned by another workflow entity" guard. Worth folding the ownership match directly into the WHERE clause, and adding a concurrency test for this (currently untested).

Minor / lower confidence

  • rivetkit-typescript/packages/rivetkit/tests/registry-readiness.test.ts has two vi.waitFor(...) calls ("shares one cold startup and readiness promise", "surfaces and retains a startup failure") without the immediately-preceding // justification comment this repo's check:wait-for-comments script mechanically enforces — these will fail that check.
  • runtime.ts in vercel-world hardcodes required env vars (RIVET_ENDPOINT/RIVET_NAMESPACE/RIVET_POOL) and force-sets registry config (test.enabled, runtime: "native", startEngine: false) rather than deferring to RivetKit's own config resolution, which the repo's Dependency Management guidance asks integrations to avoid. Low impact today since the file isn't in package.json's public exports, but worth aligning if it becomes a documented entry point.
  • codec.ts::decodeValue falls through to return value as T for unrecognized shapes instead of throwing — could mask a real driver/storage bug as silently-corrupted application data rather than a loud failure, contrary to this repo's fail-by-default convention.
  • registry/index.ts's hardcoded REGISTRY_READY_TIMEOUT_MS = 30_000 races against the full engine-spawn + ensure_local_normal_runner_config retry chain in runner_config.rs (itself up to ~30s worst case), so a legitimately-slow cold start (first binary download, etc.) could trip a generic timeout error even though the lower layer was still making progress. No knob currently exists to raise it.
  • docs-internal/integrations/vercel-world-defaults-audit.md references a personal, non-repo path (/home/nathan/tmp/...) — harmless since it's internal-only docs, but not reproducible for other readers.
  • Dead code: DispatcherVars.serialTail is declared/initialized in dispatcher.ts but never read or written there (double check it's actually used from workflow-run.ts before removing).

Solid areas worth calling out

  • Test coverage for the dispatcher queue (claim/retry/dead-letter/stale-reclaim) and the core event-sourcing paths (crash-restart, hook-token generation fencing, streams) is thorough and uses real infrastructure throughout, per repo convention.
  • withSerializedAction's release happens in a finally, so a throwing action can't deadlock the serial chain.
  • New sitemap entries for the integrations docs pages are correctly wired into website/src/sitemap/mod.ts.
  • No SQL injection risk anywhere — all queries are parameterized; only fixed, code-chosen SQL text is ever interpolated into WHERE clauses.
  • unstable/migrations.ts correctly validates table names against injection, enforces a contiguous version ladder, and relies on the actor single-writer invariant rather than adding redundant locking.
  • Rust changes (runner_config.rs) keep tests in the tests/ directory per convention, avoid _ => fallthrough on enums, and don't introduce any raw Mutex<HashMap> patterns.

Two gaps worth a follow-up test: concurrent/conflicting coordinator.update calls on the same correlation/hook (bug #4 above), and the pending_ops outbox retry/failure path (currently only schema-shape tested, unlike its dispatcher_queue counterpart).

@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 12:23 Destroyed
@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 13:00 Destroyed
@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 13:12 Destroyed
@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5460 July 22, 2026 14:37 Destroyed
@NathanFlurry
NathanFlurry merged commit 50a6387 into main Jul 22, 2026
4 of 10 checks passed
@NathanFlurry
NathanFlurry deleted the eve-rivet branch July 22, 2026 14:37
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