fix: check target run capabilities before encrypting hook payloads#1572
fix: check target run capabilities before encrypting hook payloads#1572TooTallNate merged 2 commits intomainfrom
Conversation
🦋 Changeset detectedLatest commit: 9d700c0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
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 |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests🌍 Community Worlds (60 failed)mongodb (3 failed):
redis (2 failed):
turso (55 failed):
Details by Category✅ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
❌ 🌍 Community Worlds
✅ 📋 Other
|
📊 Benchmark Results
workflow with no steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Next.js (Turbopack) | Express workflow with 1 step💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express workflow with 10 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Next.js (Turbopack) | Express workflow with 25 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 50 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express Promise.all with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express Promise.all with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Next.js (Turbopack) | Express Promise.all with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) Promise.race with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) | Nitro Promise.race with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Promise.race with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 10 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) workflow with 25 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 50 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 10 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Next.js (Turbopack) | Express workflow with 25 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 50 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) | Nitro stream pipeline with 5 transform steps (1MB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) 10 parallel streams (1MB each)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) fan-out fan-in 10 streams (1MB each)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express | Nitro SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
|
There was a problem hiding this comment.
Pull request overview
Adds backward-compatible hook/webhook resume behavior by disabling payload encryption when the target workflow run was created by an older @workflow/core deployment that can’t decode the encr serialization format.
Changes:
- Introduces
getRunCapabilities()(version-based capabilities) and uses it inresumeHook()to suppress encryption for pre-4.2.0-beta.64runs. - Adds unit tests for capability detection across version ranges.
- Adds
semverto the pnpm catalog and updates workspace packages/lockfile to consume it viacatalog:.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-workspace.yaml | Adds semver to the shared version catalog. |
| pnpm-lock.yaml | Updates lockfile for semver and related type deps/catalog usage. |
| packages/next/package.json | Switches semver dependency to catalog:. |
| packages/core/package.json | Adds semver (+ @types/semver) to support runtime capability checks. |
| packages/core/src/runtime/resume-hook.ts | Checks target run capabilities before encrypting dehydrated hook payloads. |
| packages/core/src/capabilities.ts | Implements capability lookup based on workflowCoreVersion. |
| packages/core/src/capabilities.test.ts | Tests version threshold behavior for encryption support. |
| .changeset/fix-hook-resume-encryption-compat.md | Publishes a patch changeset documenting the compatibility fix. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When resumeHook()/resumeWebhook() is called on a newer deployment that supports encryption, it would encode the payload with the 'encr' format. If the target workflow run was created by an older deployment that predates encryption support, the run would fail with: Error: Unknown serialization format: "encr". Known formats: devl Add a capabilities table that maps @workflow/core versions to supported serialization formats. Before encoding, resumeHook() now checks the target run's workflowCoreVersion and suppresses encryption when the run's deployment doesn't support it.
389467d to
d251cd6
Compare
pranaygp
left a comment
There was a problem hiding this comment.
Looks good to me. The compatibility gate in resumeHook() matches the rollout boundary for encrypted serialization and the added capability tests cover the key version cases.
- Validate with semver.valid() before comparing, falling back to baseline formats for malformed version strings - Add typeof guard at the call site in resumeHook() since executionContext is Record<string, any> - Add tests for invalid version strings (dev, empty, partial, etc.) - Add encryption commit reference to capabilities module header
…1-refresh * origin/main: (21 commits) Fix node-module-error plugin matching identifiers in multi-line comments (#1554) fix(swc-plugin): use binding name for class expression method registrations (#1599) fix(builders): override `sideEffects: false` for discovered workflow/step/serde entries (#1598) [world-vercel] align header names to `x-vercel-workflow-*` convention (#1602) [docs] Add vercel world consumer function security documentation (#1543) Make `start()` types `unknown` when `deploymentId` is provided (#1367) fix(next): stop force-setting WORKFLOW_PUBLIC_MANIFEST=1 during next dev (#1597) Version Packages (beta) (#1593) [docs] Tidy world API docs and document new stream helpers (#1581) Rename 'Workflow Development Kit' / 'DevKit' to 'Workflow SDK' (#1595) [world] Use zod/v4 in queue files to match @workflow/world schemas (#1588) [ai] Fix fatal stream errors surfacing as [object Object] (#1589) [web] Fix server crash on unmatched routes (#1590) docs: rename 'Complex Example' to 'Instance Methods as Steps' (#1592) Version Packages (beta) (#1563) [core] Extend flow route duration to "max" and fail runs where replay takes too long (#1567) fix: check target run capabilities before encrypting hook payloads (#1572) [core] Combine initial run fetch, event fetch, and run_started event creation (#1569) [docs] Split World API docs into sub-pages, update skill.md (#1457) [nitro] Preserve workflow step registration side effects (#1386) ... # Conflicts: # skills/workflow/SKILL.md
Summary
resumeHook()/resumeWebhook()failing withUnknown serialization format: "encr"when the target workflow run was created by a pre-encryption deploymentpackages/core/src/capabilities.ts) that maps@workflow/coreversions to supported serialization formats, using thesemverpackage for version comparisonresumeHook()now checks the target run'sworkflowCoreVersion(fromexecutionContext) and suppresses encryption when the run's deployment predates theencrformat (introduced in4.2.0-beta.64via 7618ac36 "Wire AES-GCM encryption into serialization layer (Wire AES-GCM encryption into serialization layer #1251)")How it works
Three data formats exist in the wild:
specVersion === 1(legacy)isLegacySpecVersion()devlbinaryspecVersion === 2,workflowCoreVersion < 4.2.0-beta.64encr+devlspecVersion === 2,workflowCoreVersion >= 4.2.0-beta.64When
workflowCoreVersionisundefined(very old runs that predate the field) or not a valid semver string, we assume the most conservative capabilities (no encryption).The capabilities table (
FORMAT_VERSION_TABLE) is designed to be extensible — when new formats likecbororenc2are added in the future, they just need a new entry with the min version.Additional changes
semverto the pnpm workspace catalog and updated@workflow/nextto usecatalog:instead of a hardcoded version