@ewhauser/world-celld 0.8.1 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 0.9.1 (2026-10-13)
6
+
7
+ ## What's Changed
8
+ * chore: qualify stable Workflow 5 packages for world-celld by @ewhauser in https://github.com/ewhauser/world-celld/pull/93
9
+ * fix: repair hook index records stranded by an interrupted creation by @ewhauser in https://github.com/ewhauser/world-celld/pull/96
10
+
11
+
12
+ **Full Changelog**: https://github.com/ewhauser/world-celld/compare/v0.9.0...v0.9.1
13
+
14
+ ## 0.9.0 (2026-10-06)
15
+
16
+ ## What's Changed
17
+ * feat: support World spec v8 and deliver demo queues by @ewhauser in https://github.com/ewhauser/world-celld/pull/90
18
+
19
+
20
+ **Full Changelog**: https://github.com/ewhauser/world-celld/compare/v0.8.1...v0.9.0
21
+
5
22
  ## 0.8.1 (2026-10-02)
6
23
 
7
24
  ## What's Changed
package/README.md CHANGED
@@ -14,11 +14,18 @@ self-hosted alternative to platform-specific Workflow backends.
14
14
 
15
15
  ## World protocol compatibility
16
16
 
17
- This adapter supports World spec v7 with the Workflow 5 beta packages. Event
18
- slots are allocated in the same transaction that stores each event, so reads
19
- see a dense log and failed writes leave no gaps. No background sealing or
20
- `noop` events are needed. Runs stamped with earlier spec versions are rejected
21
- when applying events; finish existing runs before upgrading.
17
+ This adapter supports World spec v8 with the Workflow 5 stable packages. This is
18
+ a breaking upgrade for applications using a v7 Workflow runtime: that runtime
19
+ rejects a World advertising v8. This adapter also rejects event writes to runs
20
+ stamped v7. Keep the v7 adapter and matching Workflow packages in place until
21
+ those runs finish, then upgrade the application and adapter together.
22
+
23
+ Event slots are allocated in the same transaction that stores each event, so
24
+ reads see a dense log and failed writes leave no gaps. No background sealing or
25
+ `noop` events are needed.
26
+
27
+ World v8 adds forced hook claims. This adapter does not advertise the optional
28
+ `hookForceClaim` capability, so `experimental_force` is unavailable.
22
29
 
23
30
  Run listing accepts either a single status or an array of statuses (OR matching).
24
31
  An empty status array matches no runs.
@@ -85,6 +92,22 @@ const world = createCelldWorld({
85
92
  `WORKFLOW_BASE_URL` (or `baseUrl`) is where the native Queue bridge delivers flow
86
93
  requests. It must be reachable from every celld node.
87
94
 
95
+ For overlapping Workflow builds, give each build a distinct `CELLD_DEPLOYMENT_ID`
96
+ and keep its compiled workflow endpoints available while any of its runs remain
97
+ active. Set `WORKFLOW_DEPLOYMENT_URLS` on every app that may accept hooks for those
98
+ runs and in the primary celld worker's private `vars` to the same JSON map, for
99
+ example `{"celld-default":"https://beta.internal","stable-v1":"https://stable.internal"}`.
100
+ The equivalent `createCelldWorld({ deploymentUrls: { ... } })` option configures
101
+ an app directly. Each URL must be an absolute HTTP(S) origin or base path without
102
+ credentials, query, or fragment. Keep every mapped destination reachable from
103
+ the Queue delivery worker. A mapped run's stored deployment ID selects its
104
+ callback build, including for messages queued before this setting was added;
105
+ new messages also snapshot their destination at enqueue. Missing mappings and
106
+ unavailable destinations remain retryable rather than acknowledging the work.
107
+ Keep the map and old build in service through the last old run and pending
108
+ delivery. Do not change an existing deployment ID to point at different
109
+ compiled workflow code. The in-process test queue accepts the same map.
110
+
88
111
  ## Deploy the worker
89
112
 
90
113
  Before deploying, you need a celld v0.6.0 fleet, `esbuild` on `PATH`, and an
@@ -220,16 +243,17 @@ post-compaction costs are recorded in
220
243
  Application options can be passed to `createCelldWorld()` unless an environment
221
244
  variable is shown below.
222
245
 
223
- | Option | Environment variable | Default |
224
- | ----------------------- | ------------------------ | ------------------------ |
225
- | `fleetUrl` | `CELLD_FLEET_URL` | required |
226
- | `secret` | `CELLD_WORLD_SECRET` | required with `fleetUrl` |
227
- | `baseUrl` | `WORKFLOW_BASE_URL` | `http://localhost:$PORT` |
228
- | `deploymentId` | `CELLD_DEPLOYMENT_ID` | `celld-default` |
229
- | `runRetentionMs` | `CELLD_RUN_RETENTION_MS` | `0` (disabled) |
230
- | `streamLongPollMs` | — | `20000` |
231
- | `streamFlushIntervalMs` | — | `0` |
232
- | `rpcTimeoutMs` | — | `30000` (max `300000`) |
246
+ | Option | Environment variable | Default |
247
+ | ----------------------- | -------------------------- | ------------------------ |
248
+ | `fleetUrl` | `CELLD_FLEET_URL` | required |
249
+ | `secret` | `CELLD_WORLD_SECRET` | required with `fleetUrl` |
250
+ | `baseUrl` | `WORKFLOW_BASE_URL` | `http://localhost:$PORT` |
251
+ | `deploymentId` | `CELLD_DEPLOYMENT_ID` | `celld-default` |
252
+ | `deploymentUrls` | `WORKFLOW_DEPLOYMENT_URLS` | unset |
253
+ | `runRetentionMs` | `CELLD_RUN_RETENTION_MS` | `0` (disabled) |
254
+ | `streamLongPollMs` | — | `20000` |
255
+ | `streamFlushIntervalMs` | — | `0` |
256
+ | `rpcTimeoutMs` | — | `30000` (max `300000`) |
233
257
 
234
258
  The deployed worker also accepts these celld variables:
235
259
 
@@ -237,6 +261,7 @@ The deployed worker also accepts these celld variables:
237
261
  | ------------------------------- | ------- | ---------------------------------------------------- |
238
262
  | `WORLD_SECRET` | none | Required bearer secret for RPC routes |
239
263
  | `WORKFLOW_CALLBACK_SECRET` | none | Sent with deliveries as `x-workflow-callback-secret` |
264
+ | `WORKFLOW_DEPLOYMENT_URLS` | unset | JSON map of pinned deployment IDs to callback URLs |
240
265
  | `WORKFLOW_RETENTION_MS` | `0` | Maximum run age from creation; includes active runs |
241
266
  | `WORKFLOW_RETENTION_BATCH_SIZE` | `128` | Runs admitted by each cron sweep (maximum `1000`) |
242
267
 
@@ -49,6 +49,15 @@ in the primary Wrangler config and redeploy to enable a maximum workflow age
49
49
  measured from run creation. celld rejects `CELLD_VAR_*` node overrides.
50
50
  `.dev.vars` overrides apply only to `celld dev`, not production deployments.
51
51
 
52
+ To keep in-flight runs on their original compiled Workflow build, set
53
+ `vars.WORKFLOW_DEPLOYMENT_URLS` in the private primary worker config to a JSON
54
+ object of deployment IDs and reachable HTTP(S) callback URLs. Configure the
55
+ same map in the applications with `WORKFLOW_DEPLOYMENT_URLS` or `deploymentUrls`.
56
+ The worker resolves already queued run messages from the persisted run ID, so
57
+ the map must retain old destinations until their runs and queued deliveries
58
+ finish. Keep each old compiled app available at its mapped URL. An unknown or
59
+ unavailable destination is retried, including a callback 404.
60
+
52
61
  `7776000000` is 90 days. The policy includes pending and running workflows as
53
62
  well as terminal ones. Each cron occurrence admits at most
54
63
  `WORKFLOW_RETENTION_BATCH_SIZE` runs (default `128`); the existing per-run alarm
@@ -48,6 +48,9 @@
48
48
  "WORLD_SECRET": "",
49
49
  // Optional: forwarded as x-workflow-callback-secret on queue deliveries.
50
50
  "WORKFLOW_CALLBACK_SECRET": "",
51
+ // Optional trusted JSON map of persisted deployment IDs to immutable app
52
+ // callback URLs. Keep celld-default mapped to its original beta build.
53
+ "WORKFLOW_DEPLOYMENT_URLS": "",
51
54
  // Optional fleet-wide maximum workflow age, measured from run creation.
52
55
  // Applies to pending, running, and terminal runs. "0" disables it.
53
56
  "WORKFLOW_RETENTION_MS": "0",
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { n as NativeQueueSendOptions, r as NativeQueueSendResult, t as NativeQueueEnvelope } from "./queue-protocol-8iiZ8o_1.js";
1
2
  import { CreateEventParams, CreateEventRequest, Event, GetChunksOptions, Hook, RunCreatedEventRequest, Step, StreamChunksResponse, StreamInfoResponse, Streamer, TerminalWorkflowRunStatus, Wait, WorkflowRun, WorkflowRunStatus, World } from "@workflow/world";
2
3
  //#region src/retention.d.ts
3
4
  type CleanupPhase = 'retained' | 'index' | 'streams' | 'queues' | 'payload' | 'tombstoned';
@@ -312,45 +313,9 @@ interface StreamDOId {
312
313
  toString(): string;
313
314
  }
314
315
  //#endregion
315
- //#region src/queue-protocol.d.ts
316
- /**
317
- * Small broker message carried by celld's native Queue.
318
- *
319
- * Run-bearing payload bytes live in object storage so the broker's 128 kB limit does not
320
- * narrow the Workflow World contract and run retention can delete those bytes
321
- * without waiting for the Queue's fixed four-day retention window.
322
- */
323
- interface NativeQueueEnvelope {
324
- version: 1;
325
- messageId: string;
326
- queueName: string;
327
- targetBaseUrl: string;
328
- runId?: string;
329
- idempotencyKey?: string;
330
- payloadKey?: string;
331
- /**
332
- * Inline body. Health checks always travel inline; a run-bearing body may
333
- * travel inline when it is small and carries no user data, in which case
334
- * delivery checks the run's expiry instead of reading a payload object.
335
- */
336
- body?: string;
337
- /** Absolute workflow redelivery deadline; long waits are chained by the consumer. */
338
- notBefore?: number;
339
- /**
340
- * Where the idempotency claim lives. Absent: the claim cell named by queue
341
- * and key. `run`: an entry in the run's own cell (requires `runId`).
342
- */
343
- claimScope?: 'run';
344
- /** Failed deliveries carried across suspension re-publishes. */
345
- deliveryFailures?: number;
346
- suspensionCount?: number;
347
- }
348
- interface NativeQueueSendOptions {
349
- delaySeconds?: number;
350
- }
351
- interface NativeQueueSendResult {
352
- messageId: string;
353
- }
316
+ //#region src/deployment-routing.d.ts
317
+ /** Operator-owned immutable callback destinations, keyed by stored deployment ID. */
318
+ type DeploymentUrls = Readonly<Record<string, string>>;
354
319
  //#endregion
355
320
  //#region src/queue.d.ts
356
321
  interface CelldQueueProducer {
@@ -465,6 +430,8 @@ interface CelldWorldConfig {
465
430
  * Default: process.env.WORKFLOW_BASE_URL || `http://localhost:${PORT ?? 3000}`
466
431
  */
467
432
  baseUrl?: string;
433
+ /** Immutable callback URLs for explicitly targeted deployments. Optional. */
434
+ deploymentUrls?: DeploymentUrls;
468
435
  /**
469
436
  * Keep terminal run payloads for this many milliseconds before replacing
470
437
  * them with metadata-only tombstones. Zero disables automatic cleanup.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/retention.ts","../src/apply-event.ts","../src/storage.ts","../src/stream-protocol.ts","../src/streamer.ts","../src/queue-protocol.ts","../src/queue.ts","../src/run-list.ts","../src/indexes.ts","../src/config.ts","../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/retention.ts","../src/apply-event.ts","../src/storage.ts","../src/stream-protocol.ts","../src/streamer.ts","../src/deployment-routing.ts","../src/queue.ts","../src/run-list.ts","../src/indexes.ts","../src/config.ts","../src/index.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as checkedQueueTimestampAdd, B as MAX_STREAM_READ_BYTES, D as MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS, E as MAX_QUEUE_DELIVERY_TIMEOUT_MS, F as strictIntegerSetting, G as decodeStreamReadResult, H as MAX_STREAM_WRITE_CHUNKS, I as MAX_STREAM_BATCH_BYTES, L as MAX_STREAM_CHUNK_BYTES, P as queueDelayDeadline, Q as normalizeStreamError, R as MAX_STREAM_ERROR_BYTES, T as MAX_FLEET_RPC_TIMEOUT_MS, U as STREAM_BATCH_CONTENT_TYPE, V as MAX_STREAM_READ_CHUNKS, W as STREAM_CHUNK_LIMIT_HEADER, Y as encodeStreamWriteBatch, Z as isChunkLimitRejection, _ as rpcStringify, b as createWorkflowIndex, c as nativeQueueDelaySeconds, g as rpcParse, h as compact, k as boundedIntegerOption, l as queueClaimName, n as listRunsPage, q as decodeStreamWriteResult, v as parse, x as runIndexMetadata, y as stringify, z as MAX_STREAM_LONG_POLL_MS } from "./run-list-DGsdv6Jf.js";
1
+ import { $ as encodeStreamWriteBatch, A as MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS, B as MAX_STREAM_BATCH_BYTES, C as parseDeploymentUrls, G as MAX_STREAM_READ_CHUNKS, H as MAX_STREAM_ERROR_BYTES, J as STREAM_CHUNK_LIMIT_HEADER, K as MAX_STREAM_WRITE_CHUNKS, N as boundedIntegerOption, O as MAX_FLEET_RPC_TIMEOUT_MS, P as checkedQueueTimestampAdd, R as queueDelayDeadline, S as configuredDeploymentUrl, U as MAX_STREAM_LONG_POLL_MS, V as MAX_STREAM_CHUNK_BYTES, W as MAX_STREAM_READ_BYTES, Y as decodeStreamReadResult, Z as decodeStreamWriteResult, _ as rpcStringify, b as createWorkflowIndex, c as nativeQueueDelaySeconds, g as rpcParse, h as compact, k as MAX_QUEUE_DELIVERY_TIMEOUT_MS, l as queueClaimName, n as listRunsPage, nt as normalizeStreamError, q as STREAM_BATCH_CONTENT_TYPE, tt as isChunkLimitRejection, v as parse, w as validateDeploymentUrls, x as runIndexMetadata, y as stringify, z as strictIntegerSetting } from "./run-list-CHRaDRvU.js";
2
2
  import { CreateEventSchema, EventSchema, HookSchema, MessageId, QueuePayloadSchema, SPEC_VERSION_CURRENT, StepSchema, WaitSchema, WorkflowRunSchema, parseQueueName } from "@workflow/world";
3
3
  import { EntityConflictError, HookNotFoundError, RunExpiredError, RunNotSupportedError, TooEarlyError, WorkflowRunNotFoundError, WorkflowWorldError } from "@workflow/errors";
4
4
  import { monotonicFactory } from "ulid";
@@ -18,6 +18,7 @@ function resolveConfig(config) {
18
18
  env: config?.env,
19
19
  deploymentId: config?.deploymentId ?? process.env.CELLD_DEPLOYMENT_ID ?? "celld-default",
20
20
  baseUrl: config?.baseUrl,
21
+ deploymentUrls: config?.deploymentUrls === void 0 ? parseDeploymentUrls(process.env.WORKFLOW_DEPLOYMENT_URLS) : validateDeploymentUrls(config.deploymentUrls),
21
22
  runRetentionMs,
22
23
  streamLongPollMs,
23
24
  streamFlushIntervalMs,
@@ -609,7 +610,8 @@ function createTestPump(config) {
609
610
  });
610
611
  }
611
612
  function retry(envelope, pathname, reason) {
612
- if (envelope.attempt >= maxAttempts) {
613
+ const mappedRun = config.deploymentUrls !== void 0 && "runId" in envelope.message;
614
+ if (envelope.attempt >= maxAttempts && !mappedRun) {
613
615
  release(envelope);
614
616
  console.error(`[world-celld test pump] dropping ${envelope.messageId} after ${envelope.attempt} attempts: ${reason}`);
615
617
  return;
@@ -627,7 +629,7 @@ function createTestPump(config) {
627
629
  delayFor(backoff).then(() => enqueue(pathname, next));
628
630
  }
629
631
  async function dispatch(envelope, pathname) {
630
- const url = `${resolveBaseUrl(config)}/.well-known/workflow/v1/${pathname}`;
632
+ const url = `${envelope.targetBaseUrl}/.well-known/workflow/v1/${pathname}`;
631
633
  const response = await fetch(url, {
632
634
  method: "POST",
633
635
  headers: {
@@ -639,7 +641,7 @@ function createTestPump(config) {
639
641
  body: stringify(envelope.message),
640
642
  signal: AbortSignal.timeout(httpTimeoutMs)
641
643
  });
642
- if (response.ok || PERMANENT_ERROR_STATUSES.has(response.status)) {
644
+ if (response.ok || !config.deploymentUrls && PERMANENT_ERROR_STATUSES.has(response.status) || !("runId" in envelope.message) && PERMANENT_ERROR_STATUSES.has(response.status)) {
643
645
  try {
644
646
  await response.body?.cancel();
645
647
  } catch {}
@@ -701,6 +703,7 @@ function createTestPump(config) {
701
703
  }
702
704
  function createQueue(config) {
703
705
  const { env, deploymentId } = config;
706
+ const deploymentUrls = config.deploymentUrls === void 0 ? void 0 : validateDeploymentUrls(config.deploymentUrls);
704
707
  if (!env?.WORKFLOW_QUEUE) throw new Error("world-celld queue missing WORKFLOW_QUEUE binding");
705
708
  const generateMessageId = monotonicFactory();
706
709
  const testPump = createTestPump(config);
@@ -711,6 +714,17 @@ function createQueue(config) {
711
714
  if (!parsedMessage.success) throw new WorkflowWorldError("world-celld queue payload is invalid", { status: 422 });
712
715
  if (queueDelayDeadline(Date.now(), opts?.delaySeconds ?? 0, 0, 900001) === null) throw new Error("world-celld queue delaySeconds lacks required delivery headroom");
713
716
  const runId = "runId" in parsedMessage.data && typeof parsedMessage.data.runId === "string" ? parsedMessage.data.runId : void 0;
717
+ const targetIds = [
718
+ opts?.deploymentId,
719
+ "runInput" in parsedMessage.data ? parsedMessage.data.runInput?.deploymentId : void 0,
720
+ "runContext" in parsedMessage.data ? parsedMessage.data.runContext?.deploymentId : void 0,
721
+ "hookInput" in parsedMessage.data ? parsedMessage.data.hookInput?.deploymentId : void 0
722
+ ].filter((id) => typeof id === "string");
723
+ if (targetIds.some((id) => id !== targetIds[0])) throw new Error("world-celld: queue deployment hints disagree");
724
+ const targetId = targetIds[0] ?? deploymentId;
725
+ if (deploymentUrls && runId && targetIds.length === 0) throw new Error("world-celld: queued run has no deployment routing hint");
726
+ if (!deploymentUrls && opts?.deploymentId && targetId !== deploymentId) throw new Error(`world-celld: no callback URL configured for deployment ${targetId}`);
727
+ const targetBaseUrl = deploymentUrls ? configuredDeploymentUrl(deploymentUrls, targetId) : resolveBaseUrl(config).replace(/\/$/, "");
714
728
  if (isTestMode()) {
715
729
  const existing = testPump.inflight(queueName, opts?.idempotencyKey);
716
730
  if (existing) return { messageId: existing };
@@ -720,7 +734,8 @@ function createQueue(config) {
720
734
  queueName,
721
735
  attempt: 1,
722
736
  message: parsedMessage.data,
723
- idempotencyKey: opts?.idempotencyKey
737
+ idempotencyKey: opts?.idempotencyKey,
738
+ targetBaseUrl
724
739
  }, opts?.delaySeconds);
725
740
  return { messageId };
726
741
  }
@@ -731,7 +746,7 @@ function createQueue(config) {
731
746
  version: 1,
732
747
  messageId,
733
748
  queueName,
734
- targetBaseUrl: resolveBaseUrl(config),
749
+ targetBaseUrl,
735
750
  runId,
736
751
  idempotencyKey: opts?.idempotencyKey,
737
752
  body,
@@ -769,7 +784,7 @@ function createQueue(config) {
769
784
  queueName: reqQueueName,
770
785
  messageId: reqMessageId
771
786
  });
772
- if (result && typeof result.timeoutSeconds === "number") {
787
+ if (!("invoke" in parsedBody.data && parsedBody.data.invoke) && result !== null && typeof result === "object" && "timeoutSeconds" in result && typeof result.timeoutSeconds === "number") {
773
788
  if (queueDelayDeadline(Date.now(), result.timeoutSeconds, 1, 900001) === null) throw new Error("Queue handler timeoutSeconds is out of range");
774
789
  return Response.json({ timeoutSeconds: result.timeoutSeconds }, {
775
790
  status: 503,
@@ -1488,7 +1503,8 @@ function createCelldWorld(config) {
1488
1503
  const queue = createQueue({
1489
1504
  env: { WORKFLOW_QUEUE: env.WORKFLOW_QUEUE },
1490
1505
  deploymentId: resolved.deploymentId,
1491
- baseUrl: resolved.baseUrl
1506
+ baseUrl: resolved.baseUrl,
1507
+ deploymentUrls: resolved.deploymentUrls
1492
1508
  });
1493
1509
  const streamer = createStreamer({
1494
1510
  env: { WORKFLOW_STREAMS: env.WORKFLOW_STREAMS },