Skip to content

feat: decrypt sealed payloads in the dashboard and CLI#3097

Open
TooTallNate wants to merge 2 commits into
nate/encp-resume-hook-sealfrom
nate/encp-o11y-decrypt
Open

feat: decrypt sealed payloads in the dashboard and CLI#3097
TooTallNate wants to merge 2 commits into
nate/encp-resume-hook-sealfrom
nate/encp-o11y-decrypt

Conversation

@TooTallNate

@TooTallNate TooTallNate commented Jul 24, 2026

Copy link
Copy Markdown
Member

PR 5 of 7. Stacked on #3096; review the stack in order, starting from #3093.

Why this is required, not optional

Once #3096 lands, a hook resumption from another deployment writes a sealed payload into the run's event log. Observability tooling can't open it: hydrateDataWithKey only ever ran AES-GCM. So the dashboard and CLI would render a 🔒 placeholder on data the user is entitled to read and has already supplied the key for — a visible debugging regression on exactly the runs this work speeds up.

What changed

hydrateDataWithKey delegates to the envelope layer, which dispatches on the 4-byte format prefix, instead of unconditionally decrypting with AES-GCM.

All four o11y key-resolution sites now resolve the run's full key capability rather than just its symmetric key:

Site Path
@workflow/web-shared hydrateResourceIOAsync
@workflow/web use-stream-reader (hand-rolled frame decode)
@workflow/cli --decrypt field hydration
@workflow/cli --decrypt stream output

Each already had the raw 32 bytes in hand, so this costs one extra key derivation and no additional requests or round trips.

A caller that supplies only a symmetric key still gets the ciphertext placeholder for sealed payloads rather than a decryption error — that key never could have opened them, so surfacing a failure would be misleading.

Browser bundling

The natural import for the new helper is @workflow/core/serialization, but that module graph reaches node:util and node:async_hooks and cannot be bundled for the browser — which is precisely what the @workflow/core/serialization-format entrypoint exists to avoid. I hit this as a build failure and moved the key helpers to a re-export from that browser-safe entrypoint; the two browser consumers import from there, while the CLI keeps the direct import since it runs on Node.

Verified by walking the built import graph: serialization-format.js reaches 6 modules and zero Node built-ins.

Tests

Two new cases assert the o11y path opens a real sealed payload with the derived keypair, and that the same resolved key still opens the run's own symmetric payloads — a run's event log mixes both.

Core suite 1598 passing, web-shared 160, CLI 78. Zero new lint diagnostics (diffed against a stashed baseline).

@TooTallNate
TooTallNate requested a review from ijjk as a code owner July 24, 2026 21:09
Copilot AI review requested due to automatic review settings July 24, 2026 21:09
@TooTallNate
TooTallNate requested a review from a team as a code owner July 24, 2026 21:09
@changeset-bot

changeset-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 24ed7ff

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

This PR includes changesets to release 16 packages
Name Type
@workflow/core Minor
@workflow/web-shared Patch
@workflow/cli Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/vitest Patch
@workflow/web Patch
workflow Minor
@workflow/world-testing 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 24, 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 25, 2026 8:51am
example-nextjs-workflow-webpack Ready Ready Preview, Comment Jul 25, 2026 8:51am
example-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-astro-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-express-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-fastify-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-hono-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-nestjs-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-nitro-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-nuxt-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-sveltekit-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-tanstack-start-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workbench-vite-workflow Ready Ready Preview, Comment Jul 25, 2026 8:51am
workflow-docs Ready Ready Preview, Comment, Open in v0 Jul 25, 2026 8:51am
workflow-swc-playground Ready Ready Preview, Comment Jul 25, 2026 8:51am
workflow-tarballs Ready Ready Preview, Comment Jul 25, 2026 8:51am
workflow-web Ready Ready Preview, Comment Jul 25, 2026 8:51am

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

❌ Failed E2E Tests

▲ Vercel Production (389 failed)

astro (27 failed):

  • hookClaimOnlyMutexWorkflow - hook works as a pure run mutex without payload data | wrun_41KYC7V7HR0GKZKK9QAN5RSY3E | 🔍 observability
  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • resume-or-start route pattern - resumeHook retried after start() reaches the new run | wrun_41KYC7VV4K0GT9P9GQK1X5GDMS | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_41KYC7XKB70GZP3HF4AV77MDAP | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV | 🔍 observability
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps

example (60 failed):

  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF | 🔍 observability
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_41KYC7XKB70GZP3HF4AV77MDAP | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_41KYC7X1ZN0GRPRDF1VFVR0AKB | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortAfterCompletionWorkflow: abort after step completes is a no-op
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortExternalSignalWorkflow: signal passed as workflow input
  • AbortController abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps
  • AbortController abortAnyInWorkflowWorkflow: AbortSignal.any composes signals inside the workflow VM
  • AbortController abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries
  • AbortController abortReasonTypesWorkflow: various abort reason types propagate correctly
  • AbortController abortFetchUncaughtWorkflow: uncaught fetch AbortError is FatalError, no retries
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchWorkflow: if-check takes same path on first-run and replay
  • AbortController abortListenerWorkflow: signal.addEventListener fires on the deserialized step signal
  • AbortController abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_41KYC80G8Q0GZ9HAC4GCR5229Z | 🔍 observability
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_41KYC80JBX0GSP828EF67AKFK7 | 🔍 observability
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_41KYC80MJC0GXP0CTPY2RM8AD9 | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_41KYC80W6B0GXQPFR5QPSWV68T | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_41KYC814EZ0GY0NNPTSH0RAGXV | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_41KYC81BM60GQ6QXT7JCP81G9T | 🔍 observability
  • setAttributes start: initial attributes are seeded on run creation
  • setAttributes start: reserved-prefix initial attributes are seeded with allowReservedAttributes
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run

express (53 failed):

  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF | 🔍 observability
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY | 🔍 observability
  • cancelRun via CLI - cancelling a running workflow | wrun_41KYC7XA3M0GPG666MGG1R3C9K | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_41KYC7XKB70GZP3HF4AV77MDAP | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_41KYC7X1ZN0GRPRDF1VFVR0AKB | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortAlreadyAbortedWorkflow: pre-aborted signal seen by step
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortAfterCompletionWorkflow: abort after step completes is a no-op
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortExternalSignalWorkflow: signal passed as workflow input
  • AbortController abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps
  • AbortController abortAnyInWorkflowWorkflow: AbortSignal.any composes signals inside the workflow VM
  • AbortController abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortListenerWorkflow: signal.addEventListener fires on the deserialized step signal
  • AbortController abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • getterStepWorkflow - getter functions with "use step" directive | wrun_41KYC80PJX0GTWHZKHZC4S39XX | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_41KYC80W6B0GXQPFR5QPSWV68T | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_41KYC814EZ0GY0NNPTSH0RAGXV | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_41KYC81BM60GQ6QXT7JCP81G9T | 🔍 observability
  • setAttributes setAttributesWorkflow: workflow-body calls append native attr_set events and merge correctly
  • setAttributes setAttributesInsideStepWorkflow: step-body calls append attributed native events
  • setAttributes fire-and-forget: void setAttributes lands without awaiting
  • setAttributes Promise.all of disjoint-key writes: every key lands
  • setAttributes workflow throws after awaited setAttributes: attribute still persists on the failed run

fastify (26 failed):

  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41KYC7TY650GQYRSCD6J71GVMY | 🔍 observability
  • hookClaimOnlyMutexWorkflow - hook works as a pure run mutex without payload data | wrun_41KYC7V7HR0GKZKK9QAN5RSY3E | 🔍 observability
  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • resume-or-start route pattern - resumeHook retried after start() reaches the new run | wrun_41KYC7VV4K0GT9P9GQK1X5GDMS | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A | 🔍 observability
  • cancelRun via CLI - cancelling a running workflow | wrun_41KYC7XA3M0GPG666MGG1R3C9K | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_41KYC7XKB70GZP3HF4AV77MDAP | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV | 🔍 observability
  • AbortController abortAfterCompletionWorkflow: abort after step completes is a no-op

hono (21 failed):

  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • resume-or-start route pattern - resumeHook retried after start() reaches the new run | wrun_41KYC7VV4K0GT9P9GQK1X5GDMS | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF | 🔍 observability
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability

nextjs-turbopack (28 failed):

  • error handling catchability workflow throw of a non-Error value round-trips verbatim as cause
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_41KYC7SHTM0GJGXEEH6JN1MX6A | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_41KYC7SXFT0GQV3KD07FD6DRMB | 🔍 observability
  • 'hookGetConflictWithPriorStepWorkflow' - hook.getConflict() does not block step execution | wrun_41KYC7TBVG0GSY6S8JJ1S79ZD2 | 🔍 observability
  • 'hookGetConflictWithParallelStepWorkfl…' - hook.getConflict() does not block step execution | wrun_41KYC7TE510GW7272GQ9XZK12Y | 🔍 observability
  • hookGetConflictThenStepParallelWorkflow - hook.getConflict() continuation step runs alongside other steps | wrun_41KYC7TGF70GRMVVGYS9SPR321 | 🔍 observability
  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41KYC7TY650GQYRSCD6J71GVMY | 🔍 observability
  • hookClaimOnlyMutexWorkflow - hook works as a pure run mutex without payload data | wrun_41KYC7V7HR0GKZKK9QAN5RSY3E | 🔍 observability
  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF | 🔍 observability

nextjs-webpack (25 failed):

  • hookGetConflictWorkflow - hook.getConflict() resolves with the conflicting run when token is already registered | wrun_41KYC7TY650GQYRSCD6J71GVMY | 🔍 observability
  • hookClaimOnlyMutexWorkflow - hook works as a pure run mutex without payload data | wrun_41KYC7V7HR0GKZKK9QAN5RSY3E | 🔍 observability
  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • resume-or-start route pattern - resumeHook retried after start() reaches the new run | wrun_41KYC7VV4K0GT9P9GQK1X5GDMS | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF | 🔍 observability
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY | 🔍 observability

nitro (38 failed):

  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A | 🔍 observability
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_41KYC7XKB70GZP3HF4AV77MDAP | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step
  • AbortController abortAlreadyAbortedWorkflow: pre-aborted signal seen by step
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortAfterCompletionWorkflow: abort after step completes is a no-op
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries
  • AbortController abortReasonTypesWorkflow: various abort reason types propagate correctly
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortListenerWorkflow: signal.addEventListener fires on the deserialized step signal
  • AbortController abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step

nuxt (47 failed):

  • hookClaimOnlyMutexWorkflow - hook works as a pure run mutex without payload data | wrun_41KYC7V7HR0GKZKK9QAN5RSY3E | 🔍 observability
  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • resume-or-start route pattern - resumeHook retried after start() reaches the new run | wrun_41KYC7VV4K0GT9P9GQK1X5GDMS | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF | 🔍 observability
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY | 🔍 observability
  • cancelRun via CLI - cancelling a running workflow | wrun_41KYC7XA3M0GPG666MGG1R3C9K | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_41KYC7XKB70GZP3HF4AV77MDAP | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step
  • AbortController abortAlreadyAbortedWorkflow: pre-aborted signal seen by step
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortAfterCompletionWorkflow: abort after step completes is a no-op
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps
  • AbortController abortAnyInWorkflowWorkflow: AbortSignal.any composes signals inside the workflow VM
  • AbortController abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries
  • AbortController abortReasonTypesWorkflow: various abort reason types propagate correctly
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_41KYC80G8Q0GZ9HAC4GCR5229Z | 🔍 observability

sveltekit (26 failed):

  • hookClaimOnlyMutexWorkflow - hook works as a pure run mutex without payload data | wrun_41KYC7V7HR0GKZKK9QAN5RSY3E | 🔍 observability
  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • resume-or-start route pattern - resumeHook retried after start() reaches the new run | wrun_41KYC7VV4K0GT9P9GQK1X5GDMS | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A | 🔍 observability
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_41KYC7X1ZN0GRPRDF1VFVR0AKB | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortAlreadyAbortedWorkflow: pre-aborted signal seen by step
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries

vite (38 failed):

  • hookClaimOnlyMutexWorkflow - hook works as a pure run mutex without payload data | wrun_41KYC7V7HR0GKZKK9QAN5RSY3E | 🔍 observability
  • hookAdoptOwnerResultWorkflow - duplicate adopts the owner result via conflict.returnValue | wrun_41KYC7V63T0GQJ179NE4YPD20K | 🔍 observability
  • hookSignalOwnerWorkflow - duplicate forwards its payload to the owner via resumeHook | wrun_41KYC7VBVR0GTBCKC9Q4AFXHWP | 🔍 observability
  • hookSupersedeOwnerWorkflow - duplicate cancels the owner and claims the released token | wrun_41KYC7VFX20GR60V00J7CPJ8M1 | 🔍 observability
  • resume-or-start route pattern - resumeHook retried after start() reaches the new run | wrun_41KYC7VV4K0GT9P9GQK1X5GDMS | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V | 🔍 observability
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73 | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25 | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5 | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_41KYC7WR8J0GJ48TZB2EZYGJD4 | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF | 🔍 observability
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY | 🔍 observability
  • cancelRun via CLI - cancelling a running workflow | wrun_41KYC7XA3M0GPG666MGG1R3C9K | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_41KYC7XKB70GZP3HF4AV77MDAP | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_41KYC7X1ZN0GRPRDF1VFVR0AKB | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortExternalSignalWorkflow: signal passed as workflow input
  • AbortController abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps
  • AbortController abortAnyInWorkflowWorkflow: AbortSignal.any composes signals inside the workflow VM
  • AbortController abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchWorkflow: if-check takes same path on first-run and replay
  • AbortController abortListenerWorkflow: signal.addEventListener fires on the deserialized step signal
  • AbortController abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step

💻 Local Development (1 failed)

nuxt-stable (1 failed):

  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q

📦 Local Production (1 failed)

nuxt-stable (1 failed):

  • webhookWorkflow | wrun_41KYC7GTP60GQBE9YDNBR63ZSR
📋 Other (57 failed)

e2e-vercel-prod-nest (27 failed):

  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_41KYC7WREG0GG3KPH84Q7NYCAF
  • cancelRun - cancelling a running workflow | wrun_41KYC7WX9B0GMK4KWXV2HWYNYY
  • cancelRun via CLI - cancelling a running workflow | wrun_41KYC7XA3M0GPG666MGG1R3C9K
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortAfterCompletionWorkflow: abort after step completes is a no-op
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortExternalSignalWorkflow: signal passed as workflow input
  • AbortController abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps
  • AbortController abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals

e2e-vercel-prod-tanstack-start (30 failed):

  • resume-or-start route pattern - resumeHook retried after start() reaches the new run | wrun_41KYC7VV4K0GT9P9GQK1X5GDMS
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_41KYC7VVVG0GZEHBHQZTENVV1V
  • hookTokenReuseLoopWorkflow - same run recreates a hook with the same token after dispose() | wrun_41KYC7VPYG0GRM3V4WBS9XQB4Q
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_41KYC7W9K70GP0EFXPYTF6CG3K
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_41KYC7WFQ20GJTY2S67Y16J6YC
  • closureVariableWorkflow - nested step functions with closure variables | wrun_41KYC7VVV30GYRQWR776CJAA73
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_41KYC7VYR30GGX76830T8MHX25
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_41KYC7W2SW0GPW52N4MSWBKYP6
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_41KYC7W6CH0GSKBKG2KJ0HYNWW
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_41KYC7VSWD0GNEJX8CWR76CSMJ
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_41KYC7W6YE0GTVW0GRNWGF3VGF
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_41KYC7WCPE0GH003Y010CJ8FHE
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_41KYC7XMGZ0GP6VKBA0W7960S5
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_41KYC7WJBF0GVXYENCK80D08J8
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_41KYC7WY330GG34YV7TFGDCWEK
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_41KYC7X40N0GW3JYSDS6ZHV7JJ
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_41KYC7XETF0GVSX2A9ZR2Q82KQ
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_41KYC7XNSX0GS5YXV3A2F1PJ8A
  • cancelRun via CLI - cancelling a running workflow | wrun_41KYC7XA3M0GPG666MGG1R3C9K
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_41KYC7XCZQ0GZHXDKVJ1J12TNF
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_41KYC7XKB70GZP3HF4AV77MDAP
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_41KYC7XZNE0GXG43MRB1ABWCAV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_41KYC7X1ZN0GRPRDF1VFVR0AKB
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step
  • AbortController abortAlreadyAbortedWorkflow: pre-aborted signal seen by step
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortAfterCompletionWorkflow: abort after step completes is a no-op
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries

E2E Test Summary

Summary
Passed Failed Skipped Total
❌ ▲ Vercel Production 1066 389 239 1694
❌ 💻 Local Development 1620 1 227 1848
❌ 📦 Local Production 1620 1 227 1848
✅ 🐘 Local Postgres 1621 0 227 1848
✅ 🪟 Windows 154 0 0 154
❌ 📋 Other 963 57 212 1232
✅ vercel-multi-region 27 0 0 27
Total 7071 448 1132 8651
Details by Category

❌ ▲ Vercel Production

App Passed Failed Skipped
❌ astro 99 27 28
❌ example 66 60 28
❌ express 73 53 28
❌ fastify 100 26 28
❌ hono 105 21 28
❌ nextjs-turbopack 123 28 3
❌ nextjs-webpack 126 25 3
❌ nitro 88 38 28
❌ nuxt 79 47 28
❌ sveltekit 119 26 9
❌ vite 88 38 28

❌ 💻 Local Development

App Passed Failed Skipped
✅ astro-stable 128 0 26
✅ express-stable 128 0 26
✅ fastify-stable 128 0 26
✅ hono-stable 128 0 26
✅ nextjs-turbopack-canary 135 0 19
✅ nextjs-turbopack-stable 154 0 0
✅ nextjs-webpack-canary 135 0 19
✅ nextjs-webpack-stable 154 0 0
✅ nitro-stable 128 0 26
❌ nuxt-stable 127 1 26
✅ sveltekit-stable 147 0 7
✅ vite-stable 128 0 26

❌ 📦 Local Production

App Passed Failed Skipped
✅ astro-stable 128 0 26
✅ express-stable 128 0 26
✅ fastify-stable 128 0 26
✅ hono-stable 128 0 26
✅ nextjs-turbopack-canary 135 0 19
✅ nextjs-turbopack-stable 154 0 0
✅ nextjs-webpack-canary 135 0 19
✅ nextjs-webpack-stable 154 0 0
✅ nitro-stable 128 0 26
❌ nuxt-stable 127 1 26
✅ sveltekit-stable 147 0 7
✅ vite-stable 128 0 26

✅ 🐘 Local Postgres

App Passed Failed Skipped
✅ astro-stable 128 0 26
✅ express-stable 128 0 26
✅ fastify-stable 128 0 26
✅ hono-stable 128 0 26
✅ nextjs-turbopack-canary 135 0 19
✅ nextjs-turbopack-stable 154 0 0
✅ nextjs-webpack-canary 135 0 19
✅ nextjs-webpack-stable 154 0 0
✅ nitro-stable 128 0 26
✅ nuxt-stable 128 0 26
✅ sveltekit-stable 147 0 7
✅ vite-stable 128 0 26

✅ 🪟 Windows

App Passed Failed Skipped
✅ nextjs-turbopack 154 0 0

❌ 📋 Other

App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 128 0 26
✅ e2e-local-dev-tanstack-start- 128 0 26
✅ e2e-local-postgres-nest-stable 128 0 26
✅ e2e-local-postgres-tanstack-start- 128 0 26
✅ e2e-local-prod-nest-stable 128 0 26
✅ e2e-local-prod-tanstack-start- 128 0 26
❌ e2e-vercel-prod-nest 99 27 28
❌ e2e-vercel-prod-tanstack-start 96 30 28

✅ vercel-multi-region

App Passed Failed Skipped
✅ nextjs-turbopack 27 0 0

📋 View full workflow run

Copilot AI left a comment

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.

Pull request overview

Updates observability decryption paths (dashboard + CLI) to correctly open sealed (encp) envelopes by deriving the run’s full payload-key capability and delegating decryption to the envelope layer (prefix-dispatch), avoiding the prior AES-GCM-only behavior.

Changes:

  • Web dashboard stream reader now decrypts via decryptEnvelope and derives RunPayloadKeys (not just a symmetric key) so sealed frames can be opened.
  • Web-shared hydration derives full run payload keys and uses envelope-aware hydrateDataWithKey.
  • Core hydrateDataWithKey now decrypts via the envelope decryptor (prefix dispatch), with new tests covering real sealed payload hydration.
  • CLI --decrypt paths derive full run payload keys for both field hydration and stream output.
  • Adds a changeset bumping @workflow/core, @workflow/web-shared, and @workflow/cli.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/web/app/lib/hooks/use-stream-reader.ts Switches stream frame decryption to envelope-aware decrypt and derives full run payload keys for sealed frames.
packages/web-shared/src/lib/hydration.ts Derives full run payload keys in async hydration so sealed payloads can be decrypted for UI display.
packages/core/src/serialization.ts Re-exports deriveRunPayloadKeys from the envelope layer for Node/CLI consumers.
packages/core/src/serialization-format.ts Adds browser-safe re-exports of envelope/key helpers; updates hydrateDataWithKey to use envelope decryption.
packages/core/src/serialization-format.test.ts Adds tests ensuring o11y hydration can open real sealed payloads and still opens symmetric payloads.
packages/cli/src/lib/inspect/output.ts Updates stream output decryption key resolution to derive full run payload keys.
packages/cli/src/lib/inspect/hydration.ts Updates --decrypt field hydration to derive full run payload keys for sealed payload support.
.changeset/encp-o11y-decrypt.md Changeset for the new o11y sealed-payload decryption support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/web-shared/src/lib/hydration.ts
Comment thread packages/core/src/serialization-format.ts

@vercel vercel Bot left a comment

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.

Additional Suggestion:

Two accidentally-committed generated files import the undeclared quickjs-wasi module, causing tsc to fail with TS2307 and breaking @workflow/core:build.

Fix on Vercel

Without this, any payload another run sealed to this one renders as a lock
icon with no way to open it — a visible regression for anyone debugging a
run that received a cross-deployment hook resumption. The user is entitled
to read the data and has already supplied the key; only the plumbing was
missing.

`hydrateDataWithKey` now delegates to the envelope layer, which dispatches
on the format prefix, instead of unconditionally running AES-GCM. All four
o11y key-resolution sites (web-shared hydration, the web stream reader,
and both CLI `--decrypt` paths) resolve the full capability rather than
just the symmetric key. Each already had the raw 32 bytes in hand, so this
costs one extra derivation and no additional requests.

A caller that supplies only a symmetric key still gets the ciphertext
placeholder for sealed payloads rather than a decryption error, since that
key never could have opened them.

**Browser bundling.** The obvious import for the new helper is
`@workflow/core/serialization`, but that module graph reaches `node:util`
and `node:async_hooks` and cannot be bundled for the browser — which is
what `@workflow/core/serialization-format` exists to avoid. The key
helpers are re-exported from that browser-safe entrypoint instead, and the
two browser consumers import from there; the CLI keeps the direct import
since it runs on Node. Verified by walking the built import graph: the
entrypoint reaches 6 modules and zero Node built-ins.

Unrelated: `pnpm --filter @workflow/web build` currently fails on `main`
too (`reducers/common.js` importing `node:util`). Turbo caching had been
hiding it; touching core caused a cache miss that surfaced it. Not
addressed here.
- `hydrateDataWithKey` accepted `PayloadKey`, which includes `SealTarget`.
  A seal target holds only a public key, so it can open neither scheme —
  passing one compiled fine and then always failed at runtime. Added a
  `DecryptionKey` alias (`CryptoKey | RunPayloadKeys`) and narrowed the
  signature, so that misuse is now a compile error. A `@ts-expect-error`
  test pins the guarantee.
- `hydrateResourceIOAsync` dynamically imported
  `@workflow/core/serialization-format` twice. Destructure both bindings
  from the single existing import instead.

@karthikscale3 karthikscale3 left a comment

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.

ai review: Reviewed the sealed observability read path across core, CLI, web-shared, and the dashboard stream reader. All four key-resolution sites now derive the full RunPayloadKeys capability, envelope dispatch handles both encr and encp, the browser-facing entrypoint avoids static Node built-ins, and decrypt-side typing excludes write-only SealTarget values. The two existing inline findings are fixed and resolved. This PR also addresses the already-flagged CLI regression on #3096.

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.

3 participants