Skip to content

feat(workflow): journal store + script sandbox#95

Draft
Waishnav wants to merge 3 commits into
pr/dw-1-types-effortfrom
pr/dw-2-store-sandbox
Draft

feat(workflow): journal store + script sandbox#95
Waishnav wants to merge 3 commits into
pr/dw-1-types-effortfrom
pr/dw-2-store-sandbox

Conversation

@Waishnav

Copy link
Copy Markdown
Owner

Summary

  • DB v5: workflow_runs / workflow_events / workflow_agent_calls
  • WorkflowStore journal API (create/claim/events/agent calls/reap)
  • Script meta extract + vm.Script compile
  • Restricted sandbox (Date/Math bans, no process/require/fetch)

Stack

PR2 of 5 · base: pr/dw-1-types-effort

Test plan

  • tsx src/workflow-store.test.ts
  • tsx src/workflow-script.test.ts
  • tsx src/workflow-sandbox.test.ts
  • npm run typecheck

Waishnav and others added 3 commits July 21, 2026 17:10
Create workflow_runs, workflow_events, and workflow_agent_calls with
indexes. Effort rename remains v4; journal schema is v5.

Co-Authored-By: Claude <noreply@anthropic.com>
Create/claim/cancel/complete runs, monotonic event append+drain,
agent call lifecycle, and stale-worker reaping. Wire unit tests.

Co-Authored-By: Claude <noreply@anthropic.com>
Parse export const meta (pure literal), compile scripts as vm.Script,
and run them with banned Date.now/Math.random/bare new Date plus no
process/require/fetch. Rehydrate results into the host realm.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 125a12a4-edd8-4c4b-ba07-7e0a02300ec5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pr/dw-2-store-sandbox

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.

Comment thread src/workflow-sandbox.ts
throw new Error("Workflow script did not compile to a function");
}

const result = await withTimeout(

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[P0] This timeout does not stop synchronous workflow code. The vm.Script timeout only covers creation of the async factory, and this Promise timer cannot fire while factory() is blocking the event loop (for example, while (true) {}). The workflow body needs to run in an externally terminable worker/child process, with a regression test for a synchronous infinite loop.

Comment thread src/workflow-sandbox.ts
consoleProxy: Record<string, (...args: unknown[]) => void>,
): Record<string, unknown> {
return {
Object,

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[P0] Injecting host-realm constructors makes this sandbox escapable. I reproduced Object.constructor('return process.version')() successfully recovering the host process. Omitting process/require from globals is therefore insufficient. Please stop exposing host constructors and treat a disposable worker/child process as the actual capability boundary; add constructor-chain escape tests.

Comment thread src/workflow-script.ts
const body = normalized.replace(META_EXPORT, " const meta =");

// Reject further imports / exports after transform
if (/\bimport\s+/.test(body) || /\bexport\s+/.test(body)) {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[P1] This scans raw source, so valid strings/comments containing import or export are rejected; agent('Explain export syntax') reproduces it. Please use a parser/tokenizer, or a lexical scan that correctly ignores strings, comments, template literals, and regex literals.

Comment thread src/workflow-store.ts
return {
events,
nextSeq,
terminal: TERMINAL_STATUSES.has(run.status),

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[P1] terminal can become true while later event pages still exist. A completed run with more events than the page limit makes callers stop after the first page and silently lose the remainder. Please return hasMore/journal-complete separately and only tell a reader it is done when the run is terminal and no events remain after this page.

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