@substrat-run/adapter-cloudflare 0.98.1 → 0.102.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.
@@ -87,7 +87,8 @@ export interface PlatformSweeperDo {
87
87
  * sweep: (env) =>
88
88
  * runPlatformSweep(hostFor(env), {
89
89
  * actor: SWEEP_ACTOR,
90
- * fetch: globalThis.fetch as unknown as FetchLike,
90
+ * // bound: workerd refuses the bare global called as `opts.fetch(…)`
91
+ * fetch: globalThis.fetch.bind(globalThis) as unknown as FetchLike,
91
92
  * sweepers: { scrive: sweepScriveReconciliations },
92
93
  * }),
93
94
  * });
@@ -1 +1 @@
1
- {"version":3,"file":"platform-sweeper-do.d.ts","sourceRoot":"","sources":["../src/platform-sweeper-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,WAAW,uBAAuB,CAAC,GAAG;IAC1C;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;OASG;IACH,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,kFAAkF;IAClF,MAAM,CAAC,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;CACxD;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,WAAW,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,gEAAgE;IAChE,QAAQ,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EACzC,MAAM,EAAE,uBAAuB,CAAC,GAAG,CAAC,GACnC,KAAK,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,GAAG,KAAK,aAAa,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAqDnF"}
1
+ {"version":3,"file":"platform-sweeper-do.d.ts","sourceRoot":"","sources":["../src/platform-sweeper-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,WAAW,uBAAuB,CAAC,GAAG;IAC1C;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;OASG;IACH,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,kFAAkF;IAClF,MAAM,CAAC,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;CACxD;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,WAAW,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,gEAAgE;IAChE,QAAQ,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EACzC,MAAM,EAAE,uBAAuB,CAAC,GAAG,CAAC,GACnC,KAAK,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,GAAG,KAAK,aAAa,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAqDnF"}
@@ -50,7 +50,8 @@ export const PLATFORM_SWEEPER_NAME = 'platform-sweeper';
50
50
  * sweep: (env) =>
51
51
  * runPlatformSweep(hostFor(env), {
52
52
  * actor: SWEEP_ACTOR,
53
- * fetch: globalThis.fetch as unknown as FetchLike,
53
+ * // bound: workerd refuses the bare global called as `opts.fetch(…)`
54
+ * fetch: globalThis.fetch.bind(globalThis) as unknown as FetchLike,
54
55
  * sweepers: { scrive: sweepScriveReconciliations },
55
56
  * }),
56
57
  * });
@@ -1 +1 @@
1
- {"version":3,"file":"platform-sweeper-do.js","sourceRoot":"","sources":["../src/platform-sweeper-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAoCxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAoC;IAEpC,OAAO,MAAM,iBAAkB,SAAQ,aAAkB;QACvD,mEAAmE;QACnE,KAAK,GAAyC,IAAI,CAAC;QAEnD;;;WAGG;QACH,KAAK,CAAC,WAAW;YACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnD,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;YAClE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;YAC/C,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACzC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAClC,CAAC;QAED;;;;WAIG;QACH,KAAK,CAAC,QAAQ;YACZ,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;QAED,yEAAyE;QACzE,KAAK,CAAC,KAAK;YACT,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;QAED,KAAK,CAAC,IAAI;YACR,IAAI,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAC;YAClC,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,IAAmC,EAAE;gBACtD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBAC5C,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;oBAClC,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC5E,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;oBACnC,OAAO,OAAO,CAAC;gBACjB,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;YACL,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC;YAC1B,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;gBAClB,yEAAyE;gBACzE,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"platform-sweeper-do.js","sourceRoot":"","sources":["../src/platform-sweeper-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAoCxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAoC;IAEpC,OAAO,MAAM,iBAAkB,SAAQ,aAAkB;QACvD,mEAAmE;QACnE,KAAK,GAAyC,IAAI,CAAC;QAEnD;;;WAGG;QACH,KAAK,CAAC,WAAW;YACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnD,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;YAClE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;YAC/C,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACzC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAClC,CAAC;QAED;;;;WAIG;QACH,KAAK,CAAC,QAAQ;YACZ,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;QAED,yEAAyE;QACzE,KAAK,CAAC,KAAK;YACT,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;QAED,KAAK,CAAC,IAAI;YACR,IAAI,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAC;YAClC,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,IAAmC,EAAE;gBACtD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBAC5C,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;oBAClC,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC5E,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;oBACnC,OAAO,OAAO,CAAC;gBACjB,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;YACL,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC;YAC1B,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;gBAClB,yEAAyE;gBACzE,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/r2.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { FetchLike, TenantBlobStore } from '@substrat-run/kernel';
1
+ import { type FetchLike, type TenantBlobStore } from '@substrat-run/kernel';
2
2
  /**
3
3
  * The live R2 side of per-tenant blob stores (#473): a minimal client over Cloudflare's
4
4
  * R2 REST API — create and delete buckets. Pure web-standard `fetch`, injected for tests,
package/dist/r2.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../src/r2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE1F;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,8EAA8E;IAC9E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,0FAA0F;IAC1F,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAaD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,YAAY,CA4D1E;AAqBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CA2BlE"}
1
+ {"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../src/r2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEjH;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,8EAA8E;IAC9E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,0FAA0F;IAC1F,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAaD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,YAAY,CA2D1E;AAqBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CA2BlE"}
package/dist/r2.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { globalFetch } from '@substrat-run/kernel';
1
2
  /** Bound an untrusted upstream body for an error message, marking the cut (#307). */
2
3
  function bounded(body, max = 2000) {
3
4
  return body.length <= max ? body : `${body.slice(0, max)} … [truncated, ${body.length - max} chars omitted]`;
@@ -24,7 +25,7 @@ export async function blobStoreBucketName(tenantId, vertical, binding) {
24
25
  return `${raw.slice(0, 46)}-${tail}`;
25
26
  }
26
27
  export function createR2BlobStores(opts) {
27
- const fetchImpl = opts.fetch ?? ((input, init) => globalThis.fetch(input, init));
28
+ const fetchImpl = opts.fetch ?? globalFetch;
28
29
  const base = `https://api.cloudflare.com/client/v4/accounts/${opts.accountId}/r2/buckets`;
29
30
  const auth = { authorization: `Bearer ${opts.apiToken}` };
30
31
  const readEnvelope = async (res, what) => {
package/dist/r2.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"r2.js","sourceRoot":"","sources":["../src/r2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"r2.js","sourceRoot":"","sources":["../src/r2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAgE,MAAM,sBAAsB,CAAC;AAmCjH,qFAAqF;AACrF,SAAS,OAAO,CAAC,IAAY,EAAE,GAAG,GAAG,IAAI;IACvC,OAAO,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,kBAAkB,IAAI,CAAC,MAAM,GAAG,GAAG,iBAAiB,CAAC;AAC/G,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,QAAgB,EAChB,OAAe;IAEf,MAAM,GAAG,GAAG,QAAQ,QAAQ,IAAI,OAAO,IAAI,QAAQ,EAAE;SAClD,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvB,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,GAAG,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACpF,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;SACrC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAyB;IAC1D,MAAM,SAAS,GAAc,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC;IACvD,MAAM,IAAI,GAAG,iDAAiD,IAAI,CAAC,SAAS,aAAa,CAAC;IAC1F,MAAM,IAAI,GAAG,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;IAE1D,MAAM,YAAY,GAAG,KAAK,EAAK,GAAsB,EAAE,IAAY,EAA0B,EAAE;QAC7F,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,IAAI,GAA8B,CAAC;QACnC,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/D,CAAC;QAAC,MAAM,CAAC;YACP,yEAAyE;QAC3E,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;YAC3F,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,cAAc,IAAI,YAAY,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC,CAAC;YAC7F,GAA2B,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YACjD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,IAAI;YACf,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBACxD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;aAC/B,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,kFAAkF;gBAClF,+EAA+E;gBAC/E,yDAAyD;gBACzD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBACvB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;oBACxF,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;wBACb,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;wBACnC,OAAO,IAAI,CAAC;oBACd,CAAC;gBACH,CAAC;gBACD,MAAM,YAAY,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAC,kCAAkC;YACjF,CAAC;iBAAM,CAAC;gBACN,MAAM,YAAY,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,kBAAkB,CAAC,GAAG,CAAC,EAAE,EAAE;gBAChE,MAAM,EAAE,QAAQ;gBAChB,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YACH,mDAAmD;YACnD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACjC,OAAO;YACT,CAAC;YACD,MAAM,YAAY,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QAC9C,CAAC;KACF,CAAC;AACJ,CAAC;AAqBD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAe;IAC/C,MAAM,EAAE,GAAG,MAAsB,CAAC;IAClC,OAAO;QACL,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;YAC7B,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC/G,CAAC;QACD,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACjB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,CAAC;YACtB,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;YACrD,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC;YAClD,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACtE,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACpB,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;QACD,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACrB,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,IAAI,MAA0B,CAAC;YAC/B,GAAG,CAAC;gBACF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACtE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC7C,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;YACpD,CAAC,QAAQ,MAAM,EAAE;YACjB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -22,6 +22,14 @@ export interface ScopeDoEnv {
22
22
  * permissions.md) evaluates permissions locally and needs no binding.
23
23
  */
24
24
  CONTROL_PLANE?: DurableObjectNamespace;
25
+ /**
26
+ * The version REGISTRY id of the vertical version this script serves (#1242) —
27
+ * injected at deploy as a `plain_text` binding, refreshed by every in-place serve,
28
+ * and stamped into the outbox `version` column at emit (the signals dimension,
29
+ * #1231). Optional: a script deployed before the binding existed, or a test
30
+ * worker, stamps NULL.
31
+ */
32
+ SUBSTRAT_VERSION_ID?: string;
25
33
  }
26
34
  /** A raw `_substrat_platform_requests` row as stored — snake_case, JSON columns still strings.
27
35
  * The coordinator maps it to the `PlatformRequest` contract shape. */
@@ -1 +1 @@
1
- {"version":3,"file":"scope-do.d.ts","sourceRoot":"","sources":["../src/scope-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA8CnD,OAAO,EAwBL,KAAK,kBAAkB,EAEvB,KAAK,gBAAgB,EAsCtB,MAAM,sBAAsB,CAAC;AAM9B;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,sBAAsB,CAAC;CACxC;AA0UD;uEACuE;AACvE,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AA6DD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAwDxD;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,kBAAkB,EAAE,EAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,GACxD,KAAK,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,UAAU,KAAK,aAAa,CAqhFjE"}
1
+ {"version":3,"file":"scope-do.d.ts","sourceRoot":"","sources":["../src/scope-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAgDnD,OAAO,EAwBL,KAAK,kBAAkB,EAEvB,KAAK,gBAAgB,EAsCtB,MAAM,sBAAsB,CAAC;AAM9B;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AA2VD;uEACuE;AACvE,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AA6DD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAwDxD;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,kBAAkB,EAAE,EAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,GACxD,KAAK,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,UAAU,KAAK,aAAa,CA8oFjE"}
package/dist/scope-do.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DurableObject } from 'cloudflare:workers';
2
- import { ATTACHMENT_ADDED, ATTACHMENT_REMOVED, attachmentRecord, domainEvent, domainEventInput, eventId, instant, objectRef, toWireFailure, grantRefFromProof, principalId, platformRequestInput, platformRequestId, MAX_PENDING_PLATFORM_REQUESTS, platformRequest, SCOPE_TABLE_PAGE_MAX, SCOPE_QUERY_ROW_MAX, listLimitOf, requestFingerprint, substratError, assertReplayableDump, } from '@substrat-run/contracts';
2
+ import { ATTACHMENT_ADDED, ATTACHMENT_REMOVED, attachmentRecord, domainEvent, domainEventInput, eventId, instant, objectRef, toWireFailure, grantRefFromProof, principalId, platformRequestInput, platformRequestId, MAX_PENDING_PLATFORM_REQUESTS, MAX_PENDING_SWEEP_RUNS, SWEEP_RUNS_KIND, platformRequest, SCOPE_TABLE_PAGE_MAX, SCOPE_QUERY_ROW_MAX, listLimitOf, requestFingerprint, substratError, assertReplayableDump, } from '@substrat-run/contracts';
3
3
  import { ulid, assertAllowed, ConnectionSealingKeyUnavailableError, noSealingKeyMessage, sealTo, assertReadOnlyQuery, entitlementDenial, platformRequestHistoryQuery, PLATFORM_REQUEST_COLUMNS, denialListQuery, denialSummaryQuery, denialTotalsQuery, DENIAL_WINDOW_QUERY, mapDenialRow, mapDenialBucketRow, PermissionDenied, assertImpersonationWrites, impersonationStampOf, createAtomic, NotSearchable, isSearchIndexTable, searchIndexDdl, searchIndexMigrations, searchIndexPlans, NotListable, listIndexMigrations, listIndexPlans, listQuery, cursorOf, searchLimit, searchMatchExpression, searchQuery, IDEMPOTENCY_DDL, assertIdempotencyKey, idempotencyLookupQuery, idempotencyPruneStatement, idempotencyRecordStatement, idempotencyOptedOutMessage, replayFor, entityVersionQuery, entityVersionOf, assertIfMatch, OUTBOX_ENTITY_INDEX, } from '@substrat-run/kernel';
4
4
  import { OperationQueue } from './serialization.js';
5
5
  import { doScopedSql } from './sql.js';
@@ -27,8 +27,19 @@ const KERNEL_DDL = `
27
27
  -- session/by). NULL is the ordinary case -- nobody was impersonating -- and the
28
28
  -- actor column above stays the principal the permission model answered about.
29
29
  impersonation TEXT,
30
+ -- #1231: the invoke() string this event was emitted from. NULL is two facts the
31
+ -- spine cannot tell apart afterwards: a consumer emit (no operation ran), and a
32
+ -- row written before the column.
33
+ operation TEXT,
34
+ -- #1242: the version REGISTRY id of the vertical version the script served when
35
+ -- this event was emitted (the signals version dimension, #1231). NULL = the
36
+ -- script was deployed without the binding, or the row predates the column.
37
+ version TEXT,
30
38
  drained_at TEXT
31
39
  );
40
+ -- #1232: the freshness evaluator's read - MAX(occurred_at) per type, every pass,
41
+ -- over a table that is never pruned. Unindexed, that is a full history scan.
42
+ CREATE INDEX IF NOT EXISTS _substrat_outbox_type_at ON _substrat_outbox (type, occurred_at);
32
43
  -- platform-intents.md: durable intents a vertical enqueues (ctx.requestPlatform) for the platform
33
44
  -- to drain and execute with HostAdmin authority -- the sandbox-clean way a vertical asks for a
34
45
  -- privileged action. Written by the kernel (spine), settled by the platform drain.
@@ -445,41 +456,7 @@ export function defineScopeDO(modules, bareOps) {
445
456
  for (const stmt of splitSqlStatements(KERNEL_DDL)) {
446
457
  this.sql.exec(stmt);
447
458
  }
448
- // KERNEL_DDL is all IF NOT EXISTS, so a scope DO created before K-21 keeps
449
- // the old shape. Attempt-and-tolerate: DO SQLite restricts PRAGMA, so there
450
- // is no column probe, and a duplicate is the steady state after the first
451
- // cold start (same argument as ControlPlaneDO.addColumn).
452
- for (const alter of [
453
- 'ALTER TABLE _substrat_tuples ADD COLUMN revoked_at TEXT',
454
- // Executor retry state (#100). The defaults read as "terminal", which is
455
- // right for every row already there: each is a completed delivery or a
456
- // consumer dead-letter.
457
- 'ALTER TABLE _substrat_deliveries ADD COLUMN attempts INTEGER NOT NULL DEFAULT 0',
458
- 'ALTER TABLE _substrat_deliveries ADD COLUMN next_attempt_at TEXT',
459
- // K-34: the authorization column on a scope DO created before it existed. Nullable,
460
- // so legacy outbox rows read as "unrecorded". (_substrat_denials is a new table,
461
- // covered by KERNEL_DDL's IF NOT EXISTS with no ALTER.)
462
- 'ALTER TABLE _substrat_outbox ADD COLUMN authorization TEXT',
463
- // #841: refusal attribution on a scope DO that predates it. Nullable, so an
464
- // intent settled before this column reads as "nobody classified this" rather
465
- // than claiming an origin the drain never decided.
466
- 'ALTER TABLE _substrat_platform_requests ADD COLUMN last_failure TEXT',
467
- // K-42: the two-actor stamp on the three spine tables that record who did
468
- // what, for a scope DO created before impersonation existed. Nullable
469
- // everywhere, and the null means "nobody was impersonating" rather than
470
- // "unrecorded" — every one of those rows predates the possibility.
471
- 'ALTER TABLE _substrat_outbox ADD COLUMN impersonation TEXT',
472
- 'ALTER TABLE _substrat_platform_requests ADD COLUMN impersonation TEXT',
473
- 'ALTER TABLE _substrat_denials ADD COLUMN impersonation TEXT',
474
- ]) {
475
- try {
476
- this.sql.exec(alter);
477
- }
478
- catch (err) {
479
- if (!/duplicate column name/i.test(err.message))
480
- throw err;
481
- }
482
- }
459
+ this.applySpineColumnAdditions();
483
460
  for (const registration of modules)
484
461
  this.registerModule(registration);
485
462
  for (const [name, handler] of Object.entries(bareOps))
@@ -972,7 +949,7 @@ export function defineScopeDO(modules, bareOps) {
972
949
  // emitted events back as one — verified across `await` in workerd.
973
950
  try {
974
951
  await this.ctx.storage.transaction(async () => {
975
- const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId, systemModuleId, signals, impersonation);
952
+ const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId, systemModuleId, signals, impersonation, operation);
976
953
  // #116: a retry is answered from the recording, and nothing else runs
977
954
  // — not the guards, not the handler, not the permission check inside
978
955
  // it. Keyed by SUBJECT, so a caller only ever reaches its own
@@ -1135,7 +1112,7 @@ export function defineScopeDO(modules, bareOps) {
1135
1112
  return this.queue.enqueue(async () => {
1136
1113
  try {
1137
1114
  await this.ctx.storage.transaction(async () => {
1138
- const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId);
1115
+ const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId, undefined, undefined, undefined, 'attachments.upload');
1139
1116
  assertAllowed(await ctx.check(gate.write, parsed.entity));
1140
1117
  this.sql.exec(`INSERT INTO _substrat_attachments
1141
1118
  (id, entity_type, entity_id, filename, content_type, size, sha256,
@@ -1165,7 +1142,7 @@ export function defineScopeDO(modules, bareOps) {
1165
1142
  await this.ensureMigrations();
1166
1143
  const gate = this.attachmentGate(entity.entityType);
1167
1144
  try {
1168
- const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId);
1145
+ const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId, undefined, undefined, undefined, 'attachments.list');
1169
1146
  assertAllowed(await ctx.check(gate.read, entity));
1170
1147
  }
1171
1148
  catch (err) {
@@ -1209,7 +1186,7 @@ export function defineScopeDO(modules, bareOps) {
1209
1186
  }
1210
1187
  const gate = this.attachmentGate(record.entity.entityType);
1211
1188
  try {
1212
- const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId);
1189
+ const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId, undefined, undefined, undefined, 'attachments.open');
1213
1190
  assertAllowed(await ctx.check(mode === 'read' ? gate.read : gate.write, record.entity));
1214
1191
  }
1215
1192
  catch (err) {
@@ -1230,7 +1207,7 @@ export function defineScopeDO(modules, bareOps) {
1230
1207
  const gate = this.attachmentGate(record.entity.entityType);
1231
1208
  try {
1232
1209
  await this.ctx.storage.transaction(async () => {
1233
- const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId);
1210
+ const ctx = this.operationContext(principal, tenantId, scopeId, undefined, connectionId, undefined, undefined, undefined, 'attachments.remove');
1234
1211
  assertAllowed(await ctx.check(gate.write, record.entity));
1235
1212
  this.sql.exec('DELETE FROM _substrat_attachments WHERE id = ?', attachmentId);
1236
1213
  ctx.emit({
@@ -1273,6 +1250,38 @@ export function defineScopeDO(modules, bareOps) {
1273
1250
  .toArray()[0];
1274
1251
  return row?.last_run_at ?? null;
1275
1252
  }
1253
+ /**
1254
+ * #1232: everything the freshness evaluator needs about this scope, one round
1255
+ * trip regardless of how many types are declared — the newest matching event
1256
+ * per type, plus each type's recorded evaluator state (last recorded at +
1257
+ * outcome, kept in `_substrat_schedule_state` under a `freshness:` prefix that
1258
+ * cannot collide with operation names).
1259
+ */
1260
+ async freshnessProbe(types) {
1261
+ const out = {};
1262
+ for (const t of types)
1263
+ out[t] = { observedAt: null, stateAt: null, stateOutcome: null };
1264
+ if (types.length === 0)
1265
+ return out;
1266
+ const marks = types.map(() => '?').join(', ');
1267
+ for (const row of this.sql
1268
+ .exec(`SELECT type, MAX(occurred_at) AS at FROM _substrat_outbox WHERE type IN (${marks}) GROUP BY type`, ...types)
1269
+ .toArray()) {
1270
+ if (row.at !== null)
1271
+ out[row.type].observedAt = row.at;
1272
+ }
1273
+ const keys = types.map((t) => `freshness:${t}`);
1274
+ for (const row of this.sql
1275
+ .exec(`SELECT schedule_op, last_run_at, last_status FROM _substrat_schedule_state WHERE schedule_op IN (${marks})`, ...keys)
1276
+ .toArray()) {
1277
+ const t = row.schedule_op.slice('freshness:'.length);
1278
+ if (out[t]) {
1279
+ out[t].stateAt = row.last_run_at;
1280
+ out[t].stateOutcome = row.last_status;
1281
+ }
1282
+ }
1283
+ return out;
1284
+ }
1276
1285
  /** Record a schedule run's timestamp + outcome (#383). Spine, kernel-written. */
1277
1286
  async recordScheduleRun(operation, at, status) {
1278
1287
  this.sql.exec(`INSERT INTO _substrat_schedule_state (schedule_op, last_run_at, last_status)
@@ -1496,6 +1505,27 @@ export function defineScopeDO(modules, bareOps) {
1496
1505
  this.recordExecutorAttempt(eventId, deliveryId, null, null);
1497
1506
  return id;
1498
1507
  }
1508
+ /**
1509
+ * #1232: a CP-less pass's ONLY exit for its schedule outcomes — `admin.recordSweepRun`
1510
+ * is a control-plane write the null-CP proxy refuses. One batched intent per pass,
1511
+ * under its own low sub-cap, and a full journal DROPS the report (null) instead of
1512
+ * throwing: telemetry must never sink a pass, and must never starve the shared
1513
+ * 32-slot budget a provision-sibling needs. The next drained pass reports again.
1514
+ */
1515
+ enqueueSweepRuns(payload, requestedBy) {
1516
+ const counts = this.sql
1517
+ .exec(`SELECT COUNT(*) AS c, SUM(CASE WHEN kind = ? THEN 1 ELSE 0 END) AS k
1518
+ FROM _substrat_platform_requests WHERE status = 'pending'`, SWEEP_RUNS_KIND)
1519
+ .toArray()[0];
1520
+ if (counts.c >= MAX_PENDING_PLATFORM_REQUESTS || (counts.k ?? 0) >= MAX_PENDING_SWEEP_RUNS) {
1521
+ return null;
1522
+ }
1523
+ const id = platformRequestId.parse(ulid());
1524
+ this.sql.exec(`INSERT INTO _substrat_platform_requests
1525
+ (id, kind, payload, requested_by, impersonation, status, attempts, requested_at)
1526
+ VALUES (?, ?, ?, ?, NULL, 'pending', 0, ?)`, id, SWEEP_RUNS_KIND, payload, requestedBy, instant.parse(new Date().toISOString()));
1527
+ return id;
1528
+ }
1499
1529
  /** Executor deliveries that exhausted their attempts. */
1500
1530
  executorDeadLetters() {
1501
1531
  const rows = this.sql
@@ -1646,6 +1676,54 @@ export function defineScopeDO(modules, bareOps) {
1646
1676
  * naming the scope it was captured from, so restoring one anywhere else needs them
1647
1677
  * re-pointed — see `rewriteScopeTuples`.
1648
1678
  */
1679
+ /**
1680
+ * The additive spine-column migrations. KERNEL_DDL is all IF NOT EXISTS, so a
1681
+ * scope DO created before a column keeps the old shape — and so does a table a
1682
+ * DUMP replay just recreated from legacy DDL, which is why `importDump` re-runs
1683
+ * this after the replay: without it, the next INSERT naming the column fails in
1684
+ * this very instance. Attempt-and-tolerate: DO SQLite restricts PRAGMA, so there
1685
+ * is no column probe, and a duplicate is the steady state after the first cold
1686
+ * start (same argument as ControlPlaneDO.addColumn).
1687
+ */
1688
+ applySpineColumnAdditions() {
1689
+ for (const alter of [
1690
+ 'ALTER TABLE _substrat_tuples ADD COLUMN revoked_at TEXT',
1691
+ // Executor retry state (#100). The defaults read as "terminal", which is
1692
+ // right for every row already there: each is a completed delivery or a
1693
+ // consumer dead-letter.
1694
+ 'ALTER TABLE _substrat_deliveries ADD COLUMN attempts INTEGER NOT NULL DEFAULT 0',
1695
+ 'ALTER TABLE _substrat_deliveries ADD COLUMN next_attempt_at TEXT',
1696
+ // K-34: the authorization column on a scope DO created before it existed. Nullable,
1697
+ // so legacy outbox rows read as "unrecorded". (_substrat_denials is a new table,
1698
+ // covered by KERNEL_DDL's IF NOT EXISTS with no ALTER.)
1699
+ 'ALTER TABLE _substrat_outbox ADD COLUMN authorization TEXT',
1700
+ // #841: refusal attribution on a scope DO that predates it. Nullable, so an
1701
+ // intent settled before this column reads as "nobody classified this" rather
1702
+ // than claiming an origin the drain never decided.
1703
+ 'ALTER TABLE _substrat_platform_requests ADD COLUMN last_failure TEXT',
1704
+ // K-42: the two-actor stamp on the three spine tables that record who did
1705
+ // what, for a scope DO created before impersonation existed. Nullable
1706
+ // everywhere, and the null means "nobody was impersonating" rather than
1707
+ // "unrecorded" — every one of those rows predates the possibility.
1708
+ 'ALTER TABLE _substrat_outbox ADD COLUMN impersonation TEXT',
1709
+ 'ALTER TABLE _substrat_platform_requests ADD COLUMN impersonation TEXT',
1710
+ 'ALTER TABLE _substrat_denials ADD COLUMN impersonation TEXT',
1711
+ // #1231: the emitting operation, on a scope DO created before the column.
1712
+ // Nullable so every legacy row reads as unrecorded rather than named.
1713
+ 'ALTER TABLE _substrat_outbox ADD COLUMN operation TEXT',
1714
+ // #1242: the signals `version` dimension on the outbox, for a scope DO
1715
+ // created before the column. NULL stays honest — unstamped.
1716
+ 'ALTER TABLE _substrat_outbox ADD COLUMN version TEXT',
1717
+ ]) {
1718
+ try {
1719
+ this.sql.exec(alter);
1720
+ }
1721
+ catch (err) {
1722
+ if (!/duplicate column name/i.test(err.message))
1723
+ throw err;
1724
+ }
1725
+ }
1726
+ }
1649
1727
  async importDump(tables, destScopeId) {
1650
1728
  // The WHOLE drop-then-replay runs under deferred foreign keys, in one transaction.
1651
1729
  //
@@ -1712,6 +1790,12 @@ export function defineScopeDO(modules, bareOps) {
1712
1790
  // exist so the checker can read it.
1713
1791
  for (const stmt of splitSqlStatements(KERNEL_DDL))
1714
1792
  this.sql.exec(stmt);
1793
+ // …and the additive columns, for the same reason KERNEL_DDL is re-asserted: a
1794
+ // dump captured before a column existed replays DDL WITHOUT it, and IF NOT
1795
+ // EXISTS cannot widen a table the dump did bring. Without this, the next emit
1796
+ // in this instance fails with `no such column` until a cold start re-runs the
1797
+ // constructor's pass.
1798
+ this.applySpineColumnAdditions();
1715
1799
  // Rebuild the derived search indexes over the rows just loaded (#827). Drop-then-
1716
1800
  // create, so it also repairs an index a dump left stale, and the triggers it
1717
1801
  // recreates are what keep the restored scope in step from here. Skipped for a plan
@@ -1879,6 +1963,8 @@ export function defineScopeDO(modules, bareOps) {
1879
1963
  // was impersonating, because `DomainEvent.impersonation` is optional — the
1880
1964
  // shape module code never sees is also the shape it cannot branch on.
1881
1965
  ...(row.impersonation ? { impersonation: JSON.parse(row.impersonation) } : {}),
1966
+ // #1231: absent rather than null, the same shape rule as the stamp above.
1967
+ ...(row.operation ? { operation: row.operation } : {}),
1882
1968
  payload: row.payload === null ? undefined : JSON.parse(row.payload),
1883
1969
  });
1884
1970
  }
@@ -1893,7 +1979,13 @@ export function defineScopeDO(modules, bareOps) {
1893
1979
  * when support is looking" is the one behaviour this feature must make
1894
1980
  * impossible.
1895
1981
  */
1896
- impersonation) {
1982
+ impersonation,
1983
+ /**
1984
+ * #1231: the exact `invoke()` string this context runs on behalf of — stamped
1985
+ * onto every event it emits. Absent for consumer dispatch: a consumer runs on
1986
+ * behalf of no operation, and the emitted row's NULL says so.
1987
+ */
1988
+ operation) {
1897
1989
  const checker = this.checker;
1898
1990
  const relations = this.relations;
1899
1991
  const searchPlans = this.searchPlans;
@@ -2001,12 +2093,19 @@ export function defineScopeDO(modules, bareOps) {
2001
2093
  actor: systemActor ?? derivedActor,
2002
2094
  ...(passed.length ? { authorization: passed.map((p) => ({ ...p })) } : {}),
2003
2095
  ...(stamp ? { impersonation: stamp } : {}),
2096
+ // #1231: kernel-stamped like the two above — `domainEventInput.parse`
2097
+ // already stripped anything module code tried to smuggle under this key.
2098
+ ...(operation ? { operation } : {}),
2004
2099
  });
2005
2100
  sql.exec(`INSERT INTO _substrat_outbox
2006
2101
  (id, type, schema_version, occurred_at, tenant_id, scope_id, actor,
2007
2102
  entity_type, entity_id, pii_class, subject_id, authorization,
2008
- impersonation, payload)
2009
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, full.id, full.type, full.schemaVersion, full.occurredAt, full.tenantId, full.scopeId, JSON.stringify(full.actor), full.entity.entityType, full.entity.entityId, full.piiClass, full.subjectId ?? null, full.authorization ? JSON.stringify(full.authorization) : null, full.impersonation ? JSON.stringify(full.impersonation) : null, full.payload === undefined ? null : JSON.stringify(full.payload));
2103
+ impersonation, operation, version, payload)
2104
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, full.id, full.type, full.schemaVersion, full.occurredAt, full.tenantId, full.scopeId, JSON.stringify(full.actor), full.entity.entityType, full.entity.entityId, full.piiClass, full.subjectId ?? null, full.authorization ? JSON.stringify(full.authorization) : null, full.impersonation ? JSON.stringify(full.impersonation) : null, full.operation ?? null,
2105
+ // #1242: script configuration, not envelope data — the version is a fact
2106
+ // about the deploy, so it never rides `DomainEvent` for module code to
2107
+ // branch on; it exists for the observability joins the column serves.
2108
+ this.env.SUBSTRAT_VERSION_ID ?? null, full.payload === undefined ? null : JSON.stringify(full.payload));
2010
2109
  },
2011
2110
  requestPlatform: (request) => {
2012
2111
  assertImpersonationWrites(impersonation, 'ctx.requestPlatform');