@githolon/testing 0.24.0 → 0.25.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/index.d.ts CHANGED
@@ -112,6 +112,9 @@ export interface TestHolon {
112
112
  */
113
113
  dispatch(domain: string, directiveId: string, payload: unknown, opts?: DispatchOptions): Promise<DispatchResult>;
114
114
 
115
+ /** Alias for dispatch: tests speak the same offer vocabulary as the client/cloud lane. */
116
+ offer(domain: string, directiveId: string, payload: unknown, opts?: DispatchOptions): Promise<DispatchResult>;
117
+
115
118
  /** All projected rows for one aggregate id. */
116
119
  byId<T = Record<string, unknown>>(aggregateId: string): Row<T>[];
117
120
  /** A declared query — an indexed probe, never a scan. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@githolon/testing",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "type": "module",
5
5
  "description": "@githolon/testing — law TDD for Nomos domains: boot the REAL engine plane in-process (the exact machinery every cloud DO, heavy container and web client runs), dispatch directives, assert rows, assert TYPED REFUSALS, fork for what-ifs — fully offline inside vitest.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -31,6 +31,7 @@
31
31
  "scripts": {
32
32
  "build": "node build.mjs",
33
33
  "prepare": "npm run build",
34
+ "pretest": "npm run build",
34
35
  "test": "vitest run"
35
36
  },
36
37
  "dependencies": {
package/src/index.mjs CHANGED
@@ -277,6 +277,15 @@ const randomReplica = () => {
277
277
  return v & MASK63;
278
278
  };
279
279
 
280
+ function fileCtorFrom(node) {
281
+ if (!node || !(node.contents instanceof Map)) return node?.constructor ?? null;
282
+ for (const child of node.contents.values()) {
283
+ const ctor = fileCtorFrom(child);
284
+ if (ctor !== null) return ctor;
285
+ }
286
+ return null;
287
+ }
288
+
280
289
  // ── the holon ─────────────────────────────────────────────────────────────────
281
290
 
282
291
  class TestHolon {
@@ -332,6 +341,11 @@ class TestHolon {
332
341
  return this._author(domain, directiveId, payload, this.lawHash, opts);
333
342
  }
334
343
 
344
+ /** Alias for dispatch: tests speak the same offer vocabulary as the client/cloud lane. */
345
+ async offer(domain, directiveId, payload, opts = {}) {
346
+ return this.dispatch(domain, directiveId, payload, opts);
347
+ }
348
+
335
349
  /** All projected rows for one aggregate id (`[{ id, data }]`; partial folds are normal). */
336
350
  byId(aggregateId) {
337
351
  return qById(this._eng, WS, aggregateId);
@@ -390,7 +404,8 @@ class TestHolon {
390
404
  const wsRoot = eng.preopen.dir.contents.get("ws");
391
405
  const template = wsRoot.contents.get(WS);
392
406
  const Directory = template.constructor;
393
- const File = template.contents.get("domain_manifests.json").constructor;
407
+ const File = fileCtorFrom(template);
408
+ if (File === null) throw new Error("fork() could not derive the WASI File constructor from the mounted workspace");
394
409
  wsRoot.contents.set(WS, new Directory(deserializeTree(bytes, { File, Directory })));
395
410
  return new TestHolon({
396
411
  eng,
@@ -1036,8 +1036,14 @@ export async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence
1036
1036
  let blob = offer?.blob instanceof Uint8Array ? offer.blob : null;
1037
1037
  try {
1038
1038
  if (!blob && typeof offer?.intentB64 === "string") blob = Uint8Array.from(atob(offer.intentB64), (c) => c.charCodeAt(0));
1039
- if (!blob || blob.byteLength === 0 || blob.byteLength > 256 * 1024) {
1040
- rec.rejected.push({ oid: String(offer?.oid || "").slice(0, 10), error: "intent offer must carry intentB64 <= 256 KiB" });
1039
+ // 8 MiB matches the worker's `/offer` + `/gw-offer` ceilings (worker.mjs) it must, or a SIGNED
1040
+ // DEPLOY (a nomos/installDomain offer carrying the whole package: the esbuild engine lump + USD-IR,
1041
+ // ~1.4 MiB for the guestbook, multi-MiB for co2-scale law) the worker relayed would be silently
1042
+ // rejected HERE, the one place the offer actually folds. The 256 KiB this used to be predated signed
1043
+ // deploy (every package embeds the engine lump, so EVERY real install exceeds it); a true DoS is the
1044
+ // transport rate-limit's job, not this fold-time bound.
1045
+ if (!blob || blob.byteLength === 0 || blob.byteLength > 8 * 1024 * 1024) {
1046
+ rec.rejected.push({ oid: String(offer?.oid || "").slice(0, 10), error: "intent offer must carry intentB64 <= 8 MiB" });
1041
1047
  continue;
1042
1048
  }
1043
1049
  let doc = null;