@nimbus-sh/platform 0.13.0 → 0.15.0

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/dist/limits.d.ts CHANGED
@@ -98,6 +98,7 @@ export declare const RESIDENT_KEEPALIVE_DETACHED_MS = 60000;
98
98
  */
99
99
  export declare const WS_ATTACHMENT_LIMIT_BYTES = 16384;
100
100
  export declare const MAX_RPC_SAFE_PAYLOAD_BYTES: number;
101
+ export declare const DO_DYNAMIC_WORKER_LIMIT = 10;
101
102
  export declare const ONE_SHOT_MODULE_MAP_MAX_BYTES: number;
102
103
  export declare const SUPERVISOR_HEAP_CEILING_BYTES: number;
103
104
  export declare const FACET_OWN_WRITE_MEMORY_BYTES: number;
@@ -1 +1 @@
1
- {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAAS,CAAC;AAEjC,eAAO,MAAM,iBAAiB,QAAkB,CAAC;AACjD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAI5C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,cAAiB,CAAC;AAMrD,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,UAAY,CAAC;AAI9C;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAIlD;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAIrD;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAOhD,eAAO,MAAM,0BAA0B,QAAmB,CAAC;AAmB3D,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AA6B9D,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAM9D,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAQ7D,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAM1D,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAM7C,eAAO,MAAM,yBAAyB,QAAoB,CAAC;AAQ3D,eAAO,MAAM,8BAA8B,OAAO,CAAC;AAOnD,eAAO,MAAM,4CAA4C,QAAmB,CAAC;AAS7E,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAY9C,eAAO,MAAM,6BAA6B,QAAc,CAAC;AAKzD,eAAO,MAAM,oCAAoC,QAAkB,CAAC;AAQpE,eAAO,MAAM,0BAA0B,QAA6B,CAAC;AACrE,eAAO,MAAM,sBAAsB,IAAI,CAAC"}
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAAS,CAAC;AAEjC,eAAO,MAAM,iBAAiB,QAAkB,CAAC;AACjD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAI5C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,cAAiB,CAAC;AAMrD,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,UAAY,CAAC;AAI9C;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAIlD;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAIrD;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAOhD,eAAO,MAAM,0BAA0B,QAAmB,CAAC;AAQ3D,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAmB1C,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AA6B9D,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAM9D,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAQ7D,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAM1D,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAM7C,eAAO,MAAM,yBAAyB,QAAoB,CAAC;AAQ3D,eAAO,MAAM,8BAA8B,OAAO,CAAC;AAOnD,eAAO,MAAM,4CAA4C,QAAmB,CAAC;AAS7E,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAY9C,eAAO,MAAM,6BAA6B,QAAc,CAAC;AAKzD,eAAO,MAAM,oCAAoC,QAAkB,CAAC;AAQpE,eAAO,MAAM,0BAA0B,QAA6B,CAAC;AACrE,eAAO,MAAM,sBAAsB,IAAI,CAAC"}
package/dist/limits.js CHANGED
@@ -116,6 +116,13 @@ export const WS_ATTACHMENT_LIMIT_BYTES = 16_384;
116
116
  // The platform limit is 32 MiB; 28 MiB leaves room for structured-clone
117
117
  // metadata and matches the proven on-demand facet transfer envelope.
118
118
  export const MAX_RPC_SAFE_PAYLOAD_BYTES = 28 * 1024 * 1024;
119
+ // ── Dynamic Workers in flight ───────────────────────────────────────────
120
+ //
121
+ // Distinct Dynamic Workers one Durable Object may have with in-flight
122
+ // requests at once, shared across all concurrent requests to that object;
123
+ // multiple in-flight requests to one Dynamic Worker count once.
124
+ // https://developers.cloudflare.com/changelog/post/2026-08-28-durable-objects-dynamic-workers-limit/
125
+ export const DO_DYNAMIC_WORKER_LIMIT = 10;
119
126
  // ── A one-shot's module map [#13] ───────────────────────────────────────
120
127
  //
121
128
  // The largest one-shot module map (its closure's raw bytes) the session DO
package/dist/utf8.d.ts CHANGED
@@ -8,6 +8,14 @@
8
8
  * TextEncoder would write: one to four per code point, and three for a
9
9
  * lone surrogate, which it writes as U+FFFD.
10
10
  */
11
+ /**
12
+ * From this many UTF-16 units, a string is counted natively (longUtf8Length),
13
+ * into a scratch buffer of SCRATCH_BYTES. The resident store's count on the
14
+ * launch's captures (worker vfs/resident/cell-cost.ts) keeps the same policy,
15
+ * and tests/unit/utf8-length.mjs holds both to TextEncoder.
16
+ */
17
+ export declare const UTF8_LONG_UNITS = 256;
18
+ export declare const UTF8_SCRATCH_BYTES: number;
11
19
  export declare function utf8Length(text: string): number;
12
20
  /**
13
21
  * `a` against `b` (negative, 0, positive) as their UTF-8 bytes order them,
@@ -1 +1 @@
1
- {"version":3,"file":"utf8.d.ts","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB/C;AA6BD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAUxD"}
1
+ {"version":3,"file":"utf8.d.ts","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAK7C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB/C;AA6BD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAUxD"}
package/dist/utf8.js CHANGED
@@ -8,13 +8,19 @@
8
8
  * TextEncoder would write: one to four per code point, and three for a
9
9
  * lone surrogate, which it writes as U+FFFD.
10
10
  */
11
- /** From this many UTF-16 units, a string is counted natively (longUtf8Length). */
12
- const LONG_UNITS = 256;
11
+ /**
12
+ * From this many UTF-16 units, a string is counted natively (longUtf8Length),
13
+ * into a scratch buffer of SCRATCH_BYTES. The resident store's count on the
14
+ * launch's captures (worker vfs/resident/cell-cost.ts) keeps the same policy,
15
+ * and tests/unit/utf8-length.mjs holds both to TextEncoder.
16
+ */
17
+ export const UTF8_LONG_UNITS = 256;
18
+ export const UTF8_SCRATCH_BYTES = 256 * 1024;
13
19
  const encoder = new TextEncoder();
14
20
  /** Where longUtf8Length's encodes land: written, never read. */
15
21
  let scratch;
16
22
  export function utf8Length(text) {
17
- if (text.length >= LONG_UNITS)
23
+ if (text.length >= UTF8_LONG_UNITS)
18
24
  return longUtf8Length(text);
19
25
  let bytes = text.length;
20
26
  for (let index = 0; index < text.length; index++) {
@@ -47,7 +53,7 @@ export function utf8Length(text) {
47
53
  * a surrogate pair, so each slice starts on a code point.
48
54
  */
49
55
  function longUtf8Length(text) {
50
- scratch ??= new Uint8Array(256 * 1024);
56
+ scratch ??= new Uint8Array(UTF8_SCRATCH_BYTES);
51
57
  let bytes = 0;
52
58
  for (let read = 0; read < text.length;) {
53
59
  const done = encoder.encodeInto(read === 0 ? text : text.slice(read), scratch);
@@ -70,14 +70,24 @@ export interface BatchWritePayload {
70
70
  * chmod, chown and utimes each make. An owner side that is null keeps what
71
71
  * the file has when the change lands (chown's -1).
72
72
  */
73
+ /**
74
+ * A time utimes and futimes set, as utimensat(2) takes it: ms since the
75
+ * epoch (explicit: only the owner may set it), 'now' (UTIME_NOW: the
76
+ * clock of the filesystem that commits the change, as it commits it) or
77
+ * 'omit' (UTIME_OMIT: left as it is then). 'now' and 'omit' need the owner or write
78
+ * permission. Carried as it is to the filesystem that commits the change,
79
+ * which alone resolves it (posix-access.ts, timeAt) and judges it
80
+ * (utimesRefusal, explicitTimes).
81
+ */
82
+ export type FsTime = number | 'now' | 'omit';
73
83
  export type W7Attrs = {
74
84
  mode: number;
75
85
  } | {
76
86
  uid: number | null;
77
87
  gid: number | null;
78
88
  } | {
79
- atime: number;
80
- mtime: number;
89
+ atime: FsTime;
90
+ mtime: FsTime;
81
91
  };
82
92
  /**
83
93
  * A process's filesystem call as a record (v4), applied by the session's own
@@ -100,6 +110,20 @@ export declare function openAccessMask(call: {
100
110
  access: W7OpenAccess;
101
111
  truncate?: true;
102
112
  }): number;
113
+ /**
114
+ * What a process decided a call on from its own view of the name: the file
115
+ * it expected there (its number on the session's filesystem), none (null),
116
+ * or the file its open of description `made` reached, for a file that open
117
+ * made and the process has no number of yet (it keeps that description
118
+ * open until it has). Where the name leads elsewhere now (a stale view: a
119
+ * peer replaced the name, or a link there leads to another file; or that
120
+ * open was refused), the session refuses the call before any effect:
121
+ * ENOENT where it expected a file, EEXIST where it expected none, EXDEV
122
+ * where the name leads to a mount.
123
+ */
124
+ export type W7Expected = number | null | {
125
+ readonly made: string;
126
+ };
103
127
  export type W7Call =
104
128
  /**
105
129
  * `ino`, on a call that makes a name (writeFile, appendFile, mkdir,
@@ -169,9 +193,11 @@ export type W7Call =
169
193
  } | {
170
194
  call: 'unlink';
171
195
  path: string;
196
+ expect?: W7Expected;
172
197
  } | {
173
198
  call: 'rmdir';
174
199
  path: string;
200
+ expect?: W7Expected;
175
201
  } | {
176
202
  call: 'symlink';
177
203
  path: string;
@@ -245,6 +271,7 @@ export type W7Call =
245
271
  nofollow?: true;
246
272
  description?: string;
247
273
  fchmod?: number;
274
+ expect?: W7Expected;
248
275
  }
249
276
  /** close(2) of the session's open description `description` (an `open` call's). */
250
277
  | {
@@ -275,18 +302,26 @@ export type W7Op = {
275
302
  type: 'file';
276
303
  inode: BatchInodeEntry;
277
304
  source: AsyncIterable<Uint8Array>;
278
- } | {
305
+ }
306
+ /** `expect`, `expectTo`: the files the process expected at `from` and at `to` (W7Expected). */
307
+ | {
279
308
  type: 'rename';
280
309
  from: string;
281
310
  to: string;
311
+ expect?: W7Expected;
312
+ expectTo?: W7Expected;
282
313
  } | {
283
314
  type: 'truncate';
284
315
  path: string;
285
316
  size: number;
286
- } | {
317
+ }
318
+ /** `description`: through the session's open description of that id (fchmod, fchown, futimens): its file, whatever names it now. */
319
+ | {
287
320
  type: 'setattr';
288
321
  path: string;
289
322
  attrs: W7Attrs;
323
+ description?: string;
324
+ expect?: W7Expected;
290
325
  } | {
291
326
  type: 'call';
292
327
  call: W7Call;
@@ -369,6 +404,8 @@ export type W7DecodedRecord = {
369
404
  type: 'rename';
370
405
  from: string;
371
406
  to: string;
407
+ expect?: W7Expected;
408
+ expectTo?: W7Expected;
372
409
  } | {
373
410
  type: 'truncate';
374
411
  path: string;
@@ -377,6 +414,8 @@ export type W7DecodedRecord = {
377
414
  type: 'setattr';
378
415
  path: string;
379
416
  attrs: W7Attrs;
417
+ description?: string;
418
+ expect?: W7Expected;
380
419
  } | {
381
420
  type: 'call';
382
421
  call: W7PathCall;
@@ -409,5 +448,7 @@ export declare function encodeWriteBatch(payload: BatchWritePayload): Promise<Ui
409
448
  * and before its payload bytes are read or copied.
410
449
  */
411
450
  export declare function decodeWriteBatchStream(stream: ReadableStream<Uint8Array>, options?: W7DecodeOptions): Promise<W7DecodedStream>;
451
+ /** `value` as an FsTime (a finite number of milliseconds, 'now' or 'omit'); else an error naming `label`. */
452
+ export declare function parseFsTime(value: unknown, label: string): FsTime;
412
453
  export {};
413
454
  //# sourceMappingURL=w7-frame.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"w7-frame.d.ts","sourceRoot":"","sources":["../src/w7-frame.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"w7-frame.d.ts","sourceRoot":"","sources":["../src/w7-frame.ts"],"names":[],"mappings":"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"}
package/dist/w7-frame.js CHANGED
@@ -385,7 +385,7 @@ v3) {
385
385
  throw new Error(`w7-frame: unknown record tag ${envelope.tag}`);
386
386
  summary.pathCount++;
387
387
  summary.opCount++;
388
- const value = parseObject(payload, 'call', ['call', 'path'], ['mode', 'target', 'from', 'ino', 'size', 'existing', 'recursive', 'force', 'uid', 'gid', 'atime', 'mtime', 'umask', 'access', 'create', 'truncate', 'exclusive', 'nofollow', 'description', 'fchmod']);
388
+ const value = parseObject(payload, 'call', ['call', 'path'], ['mode', 'target', 'from', 'ino', 'size', 'existing', 'recursive', 'force', 'uid', 'gid', 'atime', 'mtime', 'umask', 'access', 'create', 'truncate', 'exclusive', 'nofollow', 'description', 'fchmod', 'expect']);
389
389
  yield { type: 'call', call: parsePathCall(value, (path, label) => ownedPaths.claim(canonicalPath(path, label))) };
390
390
  break;
391
391
  }
@@ -397,20 +397,23 @@ v3) {
397
397
  summary.pathCount++;
398
398
  summary.opCount++;
399
399
  if (envelope.tag === RecordTag.Rename) {
400
- const value = parseObject(payload, 'rename', ['from', 'to']);
400
+ const value = parseObject(payload, 'rename', ['from', 'to'], ['expect', 'expectTo']);
401
401
  const from = ownedPaths.claim(canonicalPath(value.from, 'rename source'));
402
402
  const to = ownedPaths.claim(canonicalPath(value.to, 'rename target'));
403
- yield { type: 'rename', from, to };
403
+ yield { type: 'rename', from, to, ...expectations(value, 'rename') };
404
404
  }
405
405
  else if (envelope.tag === RecordTag.Truncate) {
406
406
  const value = parseObject(payload, 'truncate', ['path', 'size']);
407
407
  yield { type: 'truncate', path: ownedPaths.claim(canonicalPath(value.path, 'truncate path')), size: safeInteger(value.size, 'truncate size') };
408
408
  }
409
409
  else {
410
- const value = parseObject(payload, 'setattr', ['path'], ['mode', 'uid', 'gid', 'atime', 'mtime']);
410
+ const value = parseObject(payload, 'setattr', ['path'], ['mode', 'uid', 'gid', 'atime', 'mtime', 'description', 'expect']);
411
411
  const path = ownedPaths.claim(canonicalPath(value.path, 'setattr path'));
412
- const { path: _path, ...attrs } = value;
413
- yield { type: 'setattr', path, attrs: parseAttrs(attrs, 'setattr') };
412
+ const { path: _path, description, expect: _expect, ...attrs } = value;
413
+ yield {
414
+ type: 'setattr', path, attrs: parseAttrs(attrs, 'setattr'),
415
+ ...(description === undefined ? {} : { description: descriptionId(description, 'setattr description') }), ...expectations(value, 'setattr'),
416
+ };
414
417
  }
415
418
  break;
416
419
  }
@@ -483,7 +486,7 @@ async function* encodeRecords(batchId, ops) {
483
486
  case 'rename':
484
487
  state.summary.pathCount++;
485
488
  state.summary.opCount++;
486
- yield encodeMetadataRecord(RecordTag.Rename, { from: op.from, to: op.to }, state);
489
+ yield encodeMetadataRecord(RecordTag.Rename, { from: op.from, to: op.to, ...expectations(op, 'rename') }, state);
487
490
  break;
488
491
  case 'truncate':
489
492
  state.summary.pathCount++;
@@ -493,7 +496,7 @@ async function* encodeRecords(batchId, ops) {
493
496
  case 'setattr':
494
497
  state.summary.pathCount++;
495
498
  state.summary.opCount++;
496
- yield encodeMetadataRecord(RecordTag.SetAttr, { path: op.path, ...op.attrs }, state);
499
+ yield encodeMetadataRecord(RecordTag.SetAttr, { path: op.path, ...op.attrs, ...(op.description === undefined ? {} : { description: op.description }), ...expectations(op, 'setattr') }, state);
497
500
  break;
498
501
  case 'call':
499
502
  state.summary.pathCount++;
@@ -702,11 +705,16 @@ function prepareOps(payload, batchId) {
702
705
  kind: 'rename',
703
706
  from: ownedPaths.claim(canonicalPath(op.from, 'rename source')),
704
707
  to: ownedPaths.claim(canonicalPath(op.to, 'rename target')),
708
+ ...expectations(op, 'rename'),
705
709
  };
706
710
  case 'truncate':
707
711
  return { kind: 'truncate', path: ownedPaths.claim(canonicalPath(op.path, 'truncate path')), size: safeInteger(op.size, 'truncate size') };
708
712
  case 'setattr':
709
- return { kind: 'setattr', path: ownedPaths.claim(canonicalPath(op.path, 'setattr path')), attrs: parseAttrs(op.attrs, 'setattr') };
713
+ return {
714
+ kind: 'setattr', path: ownedPaths.claim(canonicalPath(op.path, 'setattr path')), attrs: parseAttrs(op.attrs, 'setattr'),
715
+ ...(op.description === undefined ? {} : { description: descriptionId(op.description, 'setattr description') }),
716
+ ...expectations(op, 'setattr'),
717
+ };
710
718
  case 'call': {
711
719
  const call = op.call;
712
720
  if ('data' in call) {
@@ -747,9 +755,17 @@ function parseAttrs(value, label) {
747
755
  if (keys === 'gid,uid')
748
756
  return { uid: ownerId(value.uid, `${label} uid`), gid: ownerId(value.gid, `${label} gid`) };
749
757
  if (keys === 'atime,mtime')
750
- return { atime: safeInteger(value.atime, `${label} atime`), mtime: safeInteger(value.mtime, `${label} mtime`) };
758
+ return { atime: parseFsTime(value.atime, `w7-frame: ${label} atime`), mtime: parseFsTime(value.mtime, `w7-frame: ${label} mtime`) };
751
759
  throw new Error(`w7-frame: ${label} changes the mode, the owner or the times, one of them: got ${keys || 'nothing'}`);
752
760
  }
761
+ /** `value` as an FsTime (a finite number of milliseconds, 'now' or 'omit'); else an error naming `label`. */
762
+ export function parseFsTime(value, label) {
763
+ if (value === 'now' || value === 'omit')
764
+ return value;
765
+ if (typeof value === 'number' && Number.isFinite(value))
766
+ return value;
767
+ throw new Error(`${label} must be a time: milliseconds, 'now' or 'omit'`);
768
+ }
753
769
  function parseDelete(bytes) {
754
770
  const value = parseObject(bytes, 'delete', ['path']);
755
771
  return { path: canonicalPath(value.path, 'delete path') };
@@ -822,9 +838,9 @@ function parsePathCall(value, path) {
822
838
  }
823
839
  case 'unlink':
824
840
  case 'rmdir':
825
- if (keys !== 'call,path')
841
+ if (keys !== 'call,path' && keys !== 'call,expect,path')
826
842
  break;
827
- return { call: value.call, path: path(value.path, `${value.call} path`) };
843
+ return { call: value.call, path: path(value.path, `${value.call} path`), ...expectations(value, value.call) };
828
844
  case 'symlink':
829
845
  if (keys !== 'call,path,target' && keys !== 'call,ino,path,target')
830
846
  break;
@@ -868,7 +884,7 @@ function parsePathCall(value, path) {
868
884
  case 'open': {
869
885
  const flags = ['create', 'exclusive', 'nofollow', 'truncate'];
870
886
  let required = keys;
871
- for (const flag of ['create', 'description', 'exclusive', 'fchmod', 'ino', 'nofollow', 'truncate', 'umask'])
887
+ for (const flag of ['create', 'description', 'exclusive', 'expect', 'fchmod', 'ino', 'nofollow', 'truncate', 'umask'])
872
888
  required = required.replace(`,${flag}`, '');
873
889
  if (required !== 'access,call,mode,path')
874
890
  break;
@@ -889,6 +905,7 @@ function parsePathCall(value, path) {
889
905
  ...(value.nofollow === true ? { nofollow: true } : {}),
890
906
  ...(value.description === undefined ? {} : { description: descriptionId(value.description, 'open description') }),
891
907
  ...(value.fchmod === undefined ? {} : { fchmod: u32(value.fchmod, 'open fchmod') }),
908
+ ...expectations(value, 'open'),
892
909
  };
893
910
  }
894
911
  case 'lutimes':
@@ -960,6 +977,23 @@ function inodeNumber(value, label) {
960
977
  throw new Error(`w7-frame: ${label} must be at least 2`);
961
978
  return ino;
962
979
  }
980
+ /** A record's expectations (W7Expected), checked: `expect`, and a rename's `expectTo`. */
981
+ function expectations(value, label) {
982
+ const expected = (field, name) => {
983
+ if (field === null)
984
+ return null;
985
+ if (isObject(field) && !Array.isArray(field)) {
986
+ if (Object.keys(field).join(',') !== 'made')
987
+ throw new Error(`w7-frame: ${label} ${name} is a number, null or { made }`);
988
+ return { made: descriptionId(field.made, `${label} ${name} made`) };
989
+ }
990
+ return inodeNumber(field, `${label} ${name}`);
991
+ };
992
+ return {
993
+ ...(value.expect === undefined ? {} : { expect: expected(value.expect, 'expect') }),
994
+ ...(value.expectTo === undefined ? {} : { expectTo: expected(value.expectTo, 'expectTo') }),
995
+ };
996
+ }
963
997
  function parseObject(bytes, label, required, optional = []) {
964
998
  let value;
965
999
  try {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nimbus-sh/platform",
3
- "version": "0.13.0",
4
- "description": "The measured Cloudflare platform truths Nimbus is built on \u2014 error taxonomy, limits tables, budget coordination, and wire-format primitives, with zero runtime dependencies.",
3
+ "version": "0.15.0",
4
+ "description": "The measured Cloudflare platform truths Nimbus is built on — error taxonomy, limits tables, budget coordination, and wire-format primitives, with zero runtime dependencies.",
5
5
  "keywords": [
6
6
  "cloudflare",
7
7
  "workers",
package/src/limits.ts CHANGED
@@ -135,6 +135,14 @@ export const WS_ATTACHMENT_LIMIT_BYTES = 16_384;
135
135
  // metadata and matches the proven on-demand facet transfer envelope.
136
136
  export const MAX_RPC_SAFE_PAYLOAD_BYTES = 28 * 1024 * 1024;
137
137
 
138
+ // ── Dynamic Workers in flight ───────────────────────────────────────────
139
+ //
140
+ // Distinct Dynamic Workers one Durable Object may have with in-flight
141
+ // requests at once, shared across all concurrent requests to that object;
142
+ // multiple in-flight requests to one Dynamic Worker count once.
143
+ // https://developers.cloudflare.com/changelog/post/2026-08-28-durable-objects-dynamic-workers-limit/
144
+ export const DO_DYNAMIC_WORKER_LIMIT = 10;
145
+
138
146
  // ── A one-shot's module map [#13] ───────────────────────────────────────
139
147
  //
140
148
  // The largest one-shot module map (its closure's raw bytes) the session DO
package/src/utf8.ts CHANGED
@@ -9,14 +9,20 @@
9
9
  * lone surrogate, which it writes as U+FFFD.
10
10
  */
11
11
 
12
- /** From this many UTF-16 units, a string is counted natively (longUtf8Length). */
13
- const LONG_UNITS = 256;
12
+ /**
13
+ * From this many UTF-16 units, a string is counted natively (longUtf8Length),
14
+ * into a scratch buffer of SCRATCH_BYTES. The resident store's count on the
15
+ * launch's captures (worker vfs/resident/cell-cost.ts) keeps the same policy,
16
+ * and tests/unit/utf8-length.mjs holds both to TextEncoder.
17
+ */
18
+ export const UTF8_LONG_UNITS = 256;
19
+ export const UTF8_SCRATCH_BYTES = 256 * 1024;
14
20
  const encoder = new TextEncoder();
15
21
  /** Where longUtf8Length's encodes land: written, never read. */
16
22
  let scratch: Uint8Array | undefined;
17
23
 
18
24
  export function utf8Length(text: string): number {
19
- if (text.length >= LONG_UNITS) return longUtf8Length(text);
25
+ if (text.length >= UTF8_LONG_UNITS) return longUtf8Length(text);
20
26
  let bytes = text.length;
21
27
  for (let index = 0; index < text.length; index++) {
22
28
  const unit = text.charCodeAt(index);
@@ -45,7 +51,7 @@ export function utf8Length(text: string): number {
45
51
  * a surrogate pair, so each slice starts on a code point.
46
52
  */
47
53
  function longUtf8Length(text: string): number {
48
- scratch ??= new Uint8Array(256 * 1024);
54
+ scratch ??= new Uint8Array(UTF8_SCRATCH_BYTES);
49
55
  let bytes = 0;
50
56
  for (let read = 0; read < text.length;) {
51
57
  const done = encoder.encodeInto(read === 0 ? text : text.slice(read), scratch);
package/src/w7-frame.ts CHANGED
@@ -85,10 +85,21 @@ export interface BatchWritePayload {
85
85
  * chmod, chown and utimes each make. An owner side that is null keeps what
86
86
  * the file has when the change lands (chown's -1).
87
87
  */
88
+ /**
89
+ * A time utimes and futimes set, as utimensat(2) takes it: ms since the
90
+ * epoch (explicit: only the owner may set it), 'now' (UTIME_NOW: the
91
+ * clock of the filesystem that commits the change, as it commits it) or
92
+ * 'omit' (UTIME_OMIT: left as it is then). 'now' and 'omit' need the owner or write
93
+ * permission. Carried as it is to the filesystem that commits the change,
94
+ * which alone resolves it (posix-access.ts, timeAt) and judges it
95
+ * (utimesRefusal, explicitTimes).
96
+ */
97
+ export type FsTime = number | 'now' | 'omit';
98
+
88
99
  export type W7Attrs =
89
100
  | { mode: number }
90
101
  | { uid: number | null; gid: number | null }
91
- | { atime: number; mtime: number };
102
+ | { atime: FsTime; mtime: FsTime };
92
103
 
93
104
  /**
94
105
  * A process's filesystem call as a record (v4), applied by the session's own
@@ -116,6 +127,19 @@ export function openAccessMask(call: { access: W7OpenAccess; truncate?: true }):
116
127
  return (rights.read ? 4 : 0) | (rights.write || call.truncate === true ? 2 : 0);
117
128
  }
118
129
 
130
+ /**
131
+ * What a process decided a call on from its own view of the name: the file
132
+ * it expected there (its number on the session's filesystem), none (null),
133
+ * or the file its open of description `made` reached, for a file that open
134
+ * made and the process has no number of yet (it keeps that description
135
+ * open until it has). Where the name leads elsewhere now (a stale view: a
136
+ * peer replaced the name, or a link there leads to another file; or that
137
+ * open was refused), the session refuses the call before any effect:
138
+ * ENOENT where it expected a file, EEXIST where it expected none, EXDEV
139
+ * where the name leads to a mount.
140
+ */
141
+ export type W7Expected = number | null | { readonly made: string };
142
+
119
143
  export type W7Call =
120
144
  /**
121
145
  * `ino`, on a call that makes a name (writeFile, appendFile, mkdir,
@@ -144,8 +168,8 @@ export type W7Call =
144
168
  | { call: 'ftruncate'; path: string; ino?: number; description?: string; size: number }
145
169
  /** `existing: 'ok'`: a directory already there answers success, as `mkdir -p` takes it (anything else there is still EEXIST). */
146
170
  | { call: 'mkdir'; path: string; mode: number; ino?: number; umask?: number; existing?: 'ok' }
147
- | { call: 'unlink'; path: string }
148
- | { call: 'rmdir'; path: string }
171
+ | { call: 'unlink'; path: string; expect?: W7Expected }
172
+ | { call: 'rmdir'; path: string; expect?: W7Expected }
149
173
  | { call: 'symlink'; path: string; target: string; ino?: number }
150
174
  /**
151
175
  * copyfile as the session copies a file: the file \`from\` names (a link
@@ -182,7 +206,7 @@ export type W7Call =
182
206
  * open: refused (EPERM: another's file), the open is refused and keeps no
183
207
  * description, so a write through it is EBADF.
184
208
  */
185
- | { call: 'open'; path: string; mode: number; access: W7OpenAccess; ino?: number; umask?: number; create?: true; truncate?: true; exclusive?: true; nofollow?: true; description?: string; fchmod?: number }
209
+ | { call: 'open'; path: string; mode: number; access: W7OpenAccess; ino?: number; umask?: number; create?: true; truncate?: true; exclusive?: true; nofollow?: true; description?: string; fchmod?: number; expect?: W7Expected }
186
210
  /** close(2) of the session's open description `description` (an `open` call's). */
187
211
  | { call: 'close'; path: string; description: string };
188
212
 
@@ -197,9 +221,11 @@ export type W7Op =
197
221
  | { type: 'directory'; inode: BatchInodeEntry }
198
222
  | { type: 'file'; inode: BatchInodeEntry; data: Uint8Array }
199
223
  | { type: 'file'; inode: BatchInodeEntry; source: AsyncIterable<Uint8Array> }
200
- | { type: 'rename'; from: string; to: string }
224
+ /** `expect`, `expectTo`: the files the process expected at `from` and at `to` (W7Expected). */
225
+ | { type: 'rename'; from: string; to: string; expect?: W7Expected; expectTo?: W7Expected }
201
226
  | { type: 'truncate'; path: string; size: number }
202
- | { type: 'setattr'; path: string; attrs: W7Attrs }
227
+ /** `description`: through the session's open description of that id (fchmod, fchown, futimens): its file, whatever names it now. */
228
+ | { type: 'setattr'; path: string; attrs: W7Attrs; description?: string; expect?: W7Expected }
203
229
  | { type: 'call'; call: W7Call };
204
230
 
205
231
  export const W7_MAGIC = new Uint8Array([0x4e, 0x57, 0x37, 0x04]);
@@ -350,9 +376,9 @@ export type W7DecodedRecord =
350
376
  chunkCount: number;
351
377
  check: number;
352
378
  }
353
- | { type: 'rename'; from: string; to: string }
379
+ | { type: 'rename'; from: string; to: string; expect?: W7Expected; expectTo?: W7Expected }
354
380
  | { type: 'truncate'; path: string; size: number }
355
- | { type: 'setattr'; path: string; attrs: W7Attrs }
381
+ | { type: 'setattr'; path: string; attrs: W7Attrs; description?: string; expect?: W7Expected }
356
382
  | { type: 'call'; call: W7PathCall }
357
383
  | { type: 'batch-end'; summary: W7BatchSummary };
358
384
 
@@ -367,9 +393,9 @@ type EncoderOp =
367
393
  | { kind: 'delete'; path: string }
368
394
  | { kind: 'directory'; inode: W7DirectoryInode }
369
395
  | { kind: 'file'; file: EncoderFile }
370
- | { kind: 'rename'; from: string; to: string }
396
+ | { kind: 'rename'; from: string; to: string; expect?: W7Expected; expectTo?: W7Expected }
371
397
  | { kind: 'truncate'; path: string; size: number }
372
- | { kind: 'setattr'; path: string; attrs: W7Attrs }
398
+ | { kind: 'setattr'; path: string; attrs: W7Attrs; description?: string; expect?: W7Expected }
373
399
  | { kind: 'call'; call: W7PathCall };
374
400
 
375
401
  interface EncoderFile {
@@ -712,7 +738,7 @@ async function* decodeRecords(
712
738
  if (v3) throw new Error(`w7-frame: unknown record tag ${envelope.tag}`);
713
739
  summary.pathCount++;
714
740
  summary.opCount++;
715
- const value = parseObject(payload, 'call', ['call', 'path'], ['mode', 'target', 'from', 'ino', 'size', 'existing', 'recursive', 'force', 'uid', 'gid', 'atime', 'mtime', 'umask', 'access', 'create', 'truncate', 'exclusive', 'nofollow', 'description', 'fchmod']);
741
+ const value = parseObject(payload, 'call', ['call', 'path'], ['mode', 'target', 'from', 'ino', 'size', 'existing', 'recursive', 'force', 'uid', 'gid', 'atime', 'mtime', 'umask', 'access', 'create', 'truncate', 'exclusive', 'nofollow', 'description', 'fchmod', 'expect']);
716
742
  yield { type: 'call', call: parsePathCall(value, (path, label) => ownedPaths.claim(canonicalPath(path, label))) };
717
743
  break;
718
744
  }
@@ -723,18 +749,21 @@ async function* decodeRecords(
723
749
  summary.pathCount++;
724
750
  summary.opCount++;
725
751
  if (envelope.tag === RecordTag.Rename) {
726
- const value = parseObject(payload, 'rename', ['from', 'to']);
752
+ const value = parseObject(payload, 'rename', ['from', 'to'], ['expect', 'expectTo']);
727
753
  const from = ownedPaths.claim(canonicalPath(value.from, 'rename source'));
728
754
  const to = ownedPaths.claim(canonicalPath(value.to, 'rename target'));
729
- yield { type: 'rename', from, to };
755
+ yield { type: 'rename', from, to, ...expectations(value, 'rename') };
730
756
  } else if (envelope.tag === RecordTag.Truncate) {
731
757
  const value = parseObject(payload, 'truncate', ['path', 'size']);
732
758
  yield { type: 'truncate', path: ownedPaths.claim(canonicalPath(value.path, 'truncate path')), size: safeInteger(value.size, 'truncate size') };
733
759
  } else {
734
- const value = parseObject(payload, 'setattr', ['path'], ['mode', 'uid', 'gid', 'atime', 'mtime']);
760
+ const value = parseObject(payload, 'setattr', ['path'], ['mode', 'uid', 'gid', 'atime', 'mtime', 'description', 'expect']);
735
761
  const path = ownedPaths.claim(canonicalPath(value.path, 'setattr path'));
736
- const { path: _path, ...attrs } = value;
737
- yield { type: 'setattr', path, attrs: parseAttrs(attrs, 'setattr') };
762
+ const { path: _path, description, expect: _expect, ...attrs } = value;
763
+ yield {
764
+ type: 'setattr', path, attrs: parseAttrs(attrs, 'setattr'),
765
+ ...(description === undefined ? {} : { description: descriptionId(description, 'setattr description') }), ...expectations(value, 'setattr'),
766
+ };
738
767
  }
739
768
  break;
740
769
  }
@@ -803,7 +832,7 @@ async function* encodeRecords(batchId: string, ops: readonly EncoderOp[]): Async
803
832
  case 'rename':
804
833
  state.summary.pathCount++;
805
834
  state.summary.opCount++;
806
- yield encodeMetadataRecord(RecordTag.Rename, { from: op.from, to: op.to }, state);
835
+ yield encodeMetadataRecord(RecordTag.Rename, { from: op.from, to: op.to, ...expectations(op, 'rename') }, state);
807
836
  break;
808
837
  case 'truncate':
809
838
  state.summary.pathCount++;
@@ -813,7 +842,7 @@ async function* encodeRecords(batchId: string, ops: readonly EncoderOp[]): Async
813
842
  case 'setattr':
814
843
  state.summary.pathCount++;
815
844
  state.summary.opCount++;
816
- yield encodeMetadataRecord(RecordTag.SetAttr, { path: op.path, ...op.attrs }, state);
845
+ yield encodeMetadataRecord(RecordTag.SetAttr, { path: op.path, ...op.attrs, ...(op.description === undefined ? {} : { description: op.description }), ...expectations(op, 'setattr') }, state);
817
846
  break;
818
847
  case 'call':
819
848
  state.summary.pathCount++;
@@ -1020,11 +1049,16 @@ function prepareOps(payload: BatchWritePayload, batchId: string): EncoderOp[] {
1020
1049
  kind: 'rename',
1021
1050
  from: ownedPaths.claim(canonicalPath(op.from, 'rename source')),
1022
1051
  to: ownedPaths.claim(canonicalPath(op.to, 'rename target')),
1052
+ ...expectations(op, 'rename'),
1023
1053
  };
1024
1054
  case 'truncate':
1025
1055
  return { kind: 'truncate', path: ownedPaths.claim(canonicalPath(op.path, 'truncate path')), size: safeInteger(op.size, 'truncate size') };
1026
1056
  case 'setattr':
1027
- return { kind: 'setattr', path: ownedPaths.claim(canonicalPath(op.path, 'setattr path')), attrs: parseAttrs(op.attrs as Record<string, unknown>, 'setattr') };
1057
+ return {
1058
+ kind: 'setattr', path: ownedPaths.claim(canonicalPath(op.path, 'setattr path')), attrs: parseAttrs(op.attrs as Record<string, unknown>, 'setattr'),
1059
+ ...(op.description === undefined ? {} : { description: descriptionId(op.description, 'setattr description') }),
1060
+ ...expectations(op, 'setattr'),
1061
+ };
1028
1062
  case 'call': {
1029
1063
  const call = op.call;
1030
1064
  if ('data' in call) {
@@ -1060,10 +1094,17 @@ function parseAttrs(value: Record<string, unknown>, label: string): W7Attrs {
1060
1094
  const keys = Object.keys(value).sort().join(',');
1061
1095
  if (keys === 'mode') return { mode: u32(value.mode, `${label} mode`) };
1062
1096
  if (keys === 'gid,uid') return { uid: ownerId(value.uid, `${label} uid`), gid: ownerId(value.gid, `${label} gid`) };
1063
- if (keys === 'atime,mtime') return { atime: safeInteger(value.atime, `${label} atime`), mtime: safeInteger(value.mtime, `${label} mtime`) };
1097
+ if (keys === 'atime,mtime') return { atime: parseFsTime(value.atime, `w7-frame: ${label} atime`), mtime: parseFsTime(value.mtime, `w7-frame: ${label} mtime`) };
1064
1098
  throw new Error(`w7-frame: ${label} changes the mode, the owner or the times, one of them: got ${keys || 'nothing'}`);
1065
1099
  }
1066
1100
 
1101
+ /** `value` as an FsTime (a finite number of milliseconds, 'now' or 'omit'); else an error naming `label`. */
1102
+ export function parseFsTime(value: unknown, label: string): FsTime {
1103
+ if (value === 'now' || value === 'omit') return value;
1104
+ if (typeof value === 'number' && Number.isFinite(value)) return value;
1105
+ throw new Error(`${label} must be a time: milliseconds, 'now' or 'omit'`);
1106
+ }
1107
+
1067
1108
  function parseDelete(bytes: Uint8Array): DeleteMetadata {
1068
1109
  const value = parseObject(bytes, 'delete', ['path']);
1069
1110
  return { path: canonicalPath(value.path, 'delete path') };
@@ -1139,8 +1180,8 @@ function parsePathCall(value: Record<string, unknown>, path: (value: unknown, la
1139
1180
  }
1140
1181
  case 'unlink':
1141
1182
  case 'rmdir':
1142
- if (keys !== 'call,path') break;
1143
- return { call: value.call, path: path(value.path, `${value.call} path`) };
1183
+ if (keys !== 'call,path' && keys !== 'call,expect,path') break;
1184
+ return { call: value.call, path: path(value.path, `${value.call} path`), ...expectations(value, value.call) };
1144
1185
  case 'symlink':
1145
1186
  if (keys !== 'call,path,target' && keys !== 'call,ino,path,target') break;
1146
1187
  return {
@@ -1177,7 +1218,7 @@ function parsePathCall(value: Record<string, unknown>, path: (value: unknown, la
1177
1218
  case 'open': {
1178
1219
  const flags = ['create', 'exclusive', 'nofollow', 'truncate'] as const;
1179
1220
  let required = keys;
1180
- for (const flag of ['create', 'description', 'exclusive', 'fchmod', 'ino', 'nofollow', 'truncate', 'umask']) required = required.replace(`,${flag}`, '');
1221
+ for (const flag of ['create', 'description', 'exclusive', 'expect', 'fchmod', 'ino', 'nofollow', 'truncate', 'umask']) required = required.replace(`,${flag}`, '');
1181
1222
  if (required !== 'access,call,mode,path') break;
1182
1223
  for (const flag of flags) {
1183
1224
  if (value[flag] !== undefined && value[flag] !== true) throw new Error(`w7-frame: open ${flag} is true or absent`);
@@ -1194,6 +1235,7 @@ function parsePathCall(value: Record<string, unknown>, path: (value: unknown, la
1194
1235
  ...(value.nofollow === true ? { nofollow: true as const } : {}),
1195
1236
  ...(value.description === undefined ? {} : { description: descriptionId(value.description, 'open description') }),
1196
1237
  ...(value.fchmod === undefined ? {} : { fchmod: u32(value.fchmod, 'open fchmod') }),
1238
+ ...expectations(value, 'open'),
1197
1239
  };
1198
1240
  }
1199
1241
  case 'lutimes':
@@ -1268,6 +1310,22 @@ function inodeNumber(value: unknown, label: string): number {
1268
1310
  return ino;
1269
1311
  }
1270
1312
 
1313
+ /** A record's expectations (W7Expected), checked: `expect`, and a rename's `expectTo`. */
1314
+ function expectations(value: { expect?: unknown; expectTo?: unknown }, label: string): { expect?: W7Expected; expectTo?: W7Expected } {
1315
+ const expected = (field: unknown, name: string): W7Expected => {
1316
+ if (field === null) return null;
1317
+ if (isObject(field) && !Array.isArray(field)) {
1318
+ if (Object.keys(field).join(',') !== 'made') throw new Error(`w7-frame: ${label} ${name} is a number, null or { made }`);
1319
+ return { made: descriptionId(field.made, `${label} ${name} made`) };
1320
+ }
1321
+ return inodeNumber(field, `${label} ${name}`);
1322
+ };
1323
+ return {
1324
+ ...(value.expect === undefined ? {} : { expect: expected(value.expect, 'expect') }),
1325
+ ...(value.expectTo === undefined ? {} : { expectTo: expected(value.expectTo, 'expectTo') }),
1326
+ };
1327
+ }
1328
+
1271
1329
  function parseObject(
1272
1330
  bytes: Uint8Array,
1273
1331
  label: string,