惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
D
Docker
D
DataBreaches.Net
V
Vulnerabilities – Threatpost
P
Palo Alto Networks Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
L
LINUX DO - 热门话题
T
The Blog of Author Tim Ferriss
雷峰网
雷峰网
Project Zero
Project Zero
T
Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
宝玉的分享
宝玉的分享
Stack Overflow Blog
Stack Overflow Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Securelist
Cisco Talos Blog
Cisco Talos Blog
Google DeepMind News
Google DeepMind News
Scott Helme
Scott Helme
The Cloudflare Blog
Know Your Adversary
Know Your Adversary
T
Tor Project blog
博客园_首页
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
Security Latest
Security Latest
Cyberwarzone
Cyberwarzone
S
Schneier on Security
T
The Exploit Database - CXSecurity.com
H
Help Net Security
Simon Willison's Weblog
Simon Willison's Weblog
阮一峰的网络日志
阮一峰的网络日志
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Proofpoint News Feed
AWS News Blog
AWS News Blog
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
T
Troy Hunt's Blog
量子位
G
GRAHAM CLULEY
O
OpenAI News
Engineering at Meta
Engineering at Meta
博客园 - Franky
SecWiki News
SecWiki News
F
Fortinet All Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

Workflow SDK Documentation

Patterns for Defining Tools Human-in-the-Loop Building Durable AI Agents Queueing User Messages Resumable Streams Sleep, Suspense, and Scheduling Streaming Updates from Tools API Reference Workflow Globals Changelog Resilient run start Cookbook Building a World Deploying Astro Express Fastify Hono Getting Started NestJS Next.js Nitro Nuxt Python SvelteKit Vite corrupted-event-log fetch-in-workflow hook-conflict Errors node-js-module-in-workflow serialization-failed start-invalid-workflow-function step-not-registered timeout-in-workflow webhook-invalid-respond-with-value webhook-response-not-sent workflow-not-registered Errors & Retrying Hooks & Webhooks Idempotency Foundations Serialization Starting Workflows Streaming Versioning Workflows and Steps How the Directives Work Event Sourcing Framework Integrations Understanding Directives Migration Guides Migrating from AWS Step Functions Migrating from Inngest Migrating from Temporal Observability Testing Server-Based Testing createHook createWebhook defineHook FatalError fetch getStepMetadata getWorkflowMetadata getWritable workflow RetryableError sleep @workflow/vitest DurableAgent @workflow/ai WorkflowChatTransport getHookByToken getRun getWorld workflow/api resumeHook resumeWebhook Chat Session Modeling runtime-decryption-failed Upgrading Workflows abort-signal-timeout-in-workflow Cancellation How Cancellation Works Internal Serializable AbortController and AbortSignal Eager Processing of Steps & Incremental Event Replay TanStack Start Agent Cancellation Sequential & Parallel Execution Workflow Composition Local World | Workflow SDK Postgres World | Workflow SDK Vercel World | Workflow SDK Migrating from trigger.dev Secure Credential Handling Local World | Workflow SDK Postgres World | Workflow SDK Vercel World | Workflow SDK
Encryption
2026-05-31 · via Workflow SDK Documentation

Learn how Workflow SDK encrypts user data end-to-end in the event log.

This guide explains how Workflow SDK encrypts user data in the event log. Understanding these details is not required to use workflows — encryption is automatic and requires no code changes. For getting started, see the getting started guides for your framework.

Workflow SDK supports automatic end-to-end encryption of all user data before it is written to the event log. When a World implementation provides encryption support, it is safe to pass sensitive data — such as API keys, tokens, or user credentials — as workflow inputs, step arguments, and return values. The storage backend only ever sees ciphertext.

Encryption support varies by World implementation. See the Worlds page to check which worlds support this feature. World implementations opt into encryption by providing a getEncryptionKeyForRun() method — the core runtime will use it automatically when present.

All user data flowing through the event log is encrypted:

  • Workflow inputs — arguments passed when starting a workflow
  • Workflow return values — the final output of a workflow
  • Step inputs — arguments passed to step functions
  • Step return values — the result returned by step functions
  • Hook metadata — data attached when creating a hook
  • Hook payloads — data received by hooks and webhooks
  • Stream data — each frame in a ReadableStream or WritableStream

Metadata such as workflow names, step names, entity IDs, timestamps, and lifecycle states are not encrypted. This allows the observability tools to display run structure and timelines without requiring decryption.

Key Management

Each workflow run is encrypted with its own unique key, provided by the World implementation via getEncryptionKeyForRun(). How the key is generated and stored is up to the World.

For example, the Vercel World provides unique keys per run and execution environment, ensuring that a given run can only decrypt data from that run itself.

Encryption Algorithm

Data is encrypted using AES-256-GCM via the Web Crypto API:

  • A random 12-byte nonce is generated for each encryption operation
  • The GCM authentication tag provides integrity verification — any tampering with the ciphertext is detected
  • The same plaintext produces different ciphertext each time due to the random nonce

When viewing workflow runs through the observability tools, encrypted fields display as locked placeholders until you explicitly choose to decrypt them.

Permissions

Decryption access is controlled by the World implementation. On Vercel, decryption follows the same permissions model as project environment variables — if you don't have permission to view environment variable values for a project, you won't be able to decrypt workflow data either. Each decryption request is recorded in your Vercel audit log, giving your team full visibility into when and by whom workflow data was accessed.

Web Dashboard

Click the Decrypt button in the run detail panel to decrypt all data fields. Decryption happens entirely in the browser via the Web Crypto API — the observability server retrieves the encryption key but never sees your plaintext data.

CLI

Add the --decrypt flag to any inspect command:

# Inspect a specific run
npx workflow inspect run <run-id> --decrypt

# Inspect a specific step
npx workflow inspect step <step-id> --run <run-id> --decrypt

# List events for a run
npx workflow inspect events --run <run-id> --decrypt

# Inspect a specific stream
npx workflow inspect stream <stream-id> --run <run-id> --decrypt

Without --decrypt, encrypted fields display as 🔒 Encrypted placeholders.

The core runtime encrypts data automatically when the World implementation provides a getEncryptionKeyForRun() method. The core runtime can call this method in two forms:

getEncryptionKeyForRun?(run: WorkflowRun): Promise<Uint8Array | undefined>;
getEncryptionKeyForRun?(
  runId: string,
  context?: Record<string, unknown>
): Promise<Uint8Array | undefined>;

Use getEncryptionKeyForRun(run) when the run entity already exists. Use getEncryptionKeyForRun(runId, context?) in runtime paths like start() where the run has not been created yet but the world may still need context such as deploymentId.

To add encryption support to a custom World:

  1. Implement getEncryptionKeyForRun() on your World class, handling both call shapes
  2. Return the raw 32-byte key as a Uint8Array — the core runtime uses it for AES-256-GCM operations
  3. Ensure the same key is returned for the same run ID across invocations (for decryption during replay)
import type { WorkflowRun, World } from "@workflow/world";

export const getEncryptionKeyForRun: World["getEncryptionKeyForRun"] = async (
  run: WorkflowRun | string,
  context?: Record<string, unknown>
) => {
  const runId = typeof run === "string" ? run : run.runId;
  const deploymentId =
    typeof run === "string"
      ? (context?.deploymentId as string | undefined)
      : run.deploymentId;

  return await lookupRunKey(runId, deploymentId);
};

async function lookupRunKey(
  runId: string,
  deploymentId?: string
): Promise<Uint8Array | undefined> {
  // Look up or derive the encryption key for this run
  // Return undefined to skip encryption
  return new Uint8Array(32);
}

The Vercel World implementation uses HKDF derivation from a deployment-scoped key, but any consistent key management scheme will work.