@githolon/testing 0.4.0 → 0.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@githolon/testing",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
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",
@@ -53,7 +53,7 @@ function seedManifests(m, strings) {
53
53
  m.set("identity-manifests.json", new File(enc.encode(strings.identity)));
54
54
  }
55
55
 
56
- export const installPayload = (hash, usda, installedBy) => ({ domainHash: hash, packageUsda: usda, installedBy, authorityScope: "workspace/root", dependencies: [], finalizers: [] });
56
+ export const installPayload = (hash, usda, installedBy, dispositions) => ({ domainHash: hash, packageUsda: usda, installedBy, authorityScope: "workspace/root", dependencies: [], finalizers: [], ...(dispositions ? { dispositions } : {}) });
57
57
 
58
58
  /**
59
59
  * Boot the resident wasm + /work tree. `wasmModule` is a PRECOMPILED WebAssembly.Module
@@ -1149,6 +1149,31 @@ export function unmount(eng, ws) {
1149
1149
 
1150
1150
  function writeWork(eng, name, bytes) { eng.preopen.dir.contents.set(name, new File(bytes)); }
1151
1151
 
1152
+ /** THE CURRENT LAW PER DOMAIN KEY — the holon's OWN resolution (`refresh_key_map`,
1153
+ * the map the verify walk and every dispatch use: latest Active install per key
1154
+ * by install stamp). Returns `{ "<domainKey>": "<currentHash>", … }`. status uses
1155
+ * THIS instead of re-deriving recency host-side from deploy order. */
1156
+ export function currentLaw(eng, ws) {
1157
+ const out = JSON.parse(call(eng.ex, "current_law", { repoArg: repoArgOf(ws), branch: BRANCH }, eng.STDERR));
1158
+ return out.keyMap || {};
1159
+ }
1160
+
1161
+ /** THE EVOLVE DRY-RUN (managed_rollout.md slice 1 — "would this upgrade admit?"):
1162
+ * the evolve gate's pure judgment over the mounted workspace's folded state and a
1163
+ * CANDIDATE package, without installing. Returns {admits} or {admits:false,
1164
+ * domain, detail} — byte-identical to the refusal the real install would meet. */
1165
+ export function evolveDryRun(eng, ws, usda, domainHash, dispositions = null) {
1166
+ return JSON.parse(call(eng.ex, "evolve_dryrun", { repoArg: repoArgOf(ws), branch: BRANCH, bundle: usda, hash: domainHash, ...(dispositions ? { dispositions } : {}) }, eng.STDERR));
1167
+ }
1168
+
1169
+ /** THE FRONT-DOOR MINT (engine plane): reserve a kernel-minted typed id
1170
+ * (`<TypeTag>_<uuidv7>`) via the wasm `mint` arm — the same mint the web client
1171
+ * and the generated clients call. The minted id rides IN the payload, so replay
1172
+ * reads the captured id and never re-mints (determinism via capture). */
1173
+ export function mintId(eng, typeTag) {
1174
+ return JSON.parse(call(eng.ex, "mint", { typeTag, nowMillis: Date.now() }, eng.STDERR)).id;
1175
+ }
1176
+
1152
1177
  export function author(eng, ws, domain, directiveId, payload, controllerHash, opts = {}) {
1153
1178
  const seq = eng.seq++;
1154
1179
  // rngDraws: the captured-entropy budget this intent's plan may consume (each minted id
@@ -1238,7 +1263,7 @@ async function mainIntentIds(eng, ws) {
1238
1263
  * engine has no durable store), obvious attacks drop. Admitted intents merge to main,
1239
1264
  * durably push, the branch is consumed.
1240
1265
  */
1241
- export async function admitAll(eng, ws, ledger, { refuseDomains = [], shardRouting = null } = {}) {
1266
+ export async function admitAll(eng, ws, ledger, { refuseDomains = [], receiptFence = null, shardRouting = null } = {}) {
1242
1267
  const refuse = new Set(refuseDomains);
1243
1268
  const routes = shardRouting ? directiveRoutes(eng) : null;
1244
1269
  const gitdir = gitdirOf(ws);
@@ -1305,6 +1330,20 @@ export async function admitAll(eng, ws, ledger, { refuseDomains = [], shardRouti
1305
1330
  deadLetters.push({ intentId, oid: oid.slice(0, 10), session: cid, error, blob, domain: dom, directiveId: dirId });
1306
1331
  continue;
1307
1332
  }
1333
+ // THE RECEIPT FENCE (capability_marketplace.md slice 1.5 — the ratified
1334
+ // authz condition): a capability RECEIPT (complete/fail/block/deadLetter)
1335
+ // is an EXECUTOR/OWNER write — the open session lane never folds one, so
1336
+ // a hostile peer cannot terminally close orders it didn't fulfill, and a
1337
+ // forged "result" never reaches any watcher. PARKED, not dropped: an
1338
+ // honest-but-misconfigured self-hosted executor sees its receipt in the
1339
+ // DLQ, and the OWNER-GATED retry is the owner-sanctioned unjam (the
1340
+ // lawful lane for a credential-holding self-hoster is /author).
1341
+ if (receiptFence && dirId && Array.isArray(receiptFence[dom]) && receiptFence[dom].includes(dirId)) {
1342
+ const error = `'${dom}/${dirId}' is a capability RECEIPT — receipts are executor/owner writes, never open-session writes. Author it via POST /v1/workspaces/${ws}/author (owner Bearer), or — if this parked receipt is sanctioned — the owner unjams it: POST /v1/workspaces/${ws}/dead-letters/retry`;
1343
+ rejected.push({ oid: oid.slice(0, 10), error, deadLettered: true });
1344
+ deadLetters.push({ intentId, oid: oid.slice(0, 10), session: cid, error, blob, domain: dom, directiveId: dirId });
1345
+ continue;
1346
+ }
1308
1347
  // THE WRONG-HOME GATE (sharding slice 2): a routed directive's home must be
1309
1348
  // assigned to THIS workspace by the coordinator's law-state shard map.
1310
1349
  // Misrouted → the typed `wrong-home` refusal naming the correct workspace
@@ -1517,8 +1556,12 @@ export async function boot(eng, ws, ledger) {
1517
1556
  }
1518
1557
 
1519
1558
  /** Install a tenant package under the nomos controller (validation is the HOST's job). */
1520
- export async function deploy(eng, ws, ledger, usda, domainHash) {
1521
- const result = author(eng, ws, "nomos", "installDomain", installPayload(domainHash, usda, eng.installedBy), eng.hashes.nomos);
1559
+ export async function deploy(eng, ws, ledger, usda, domainHash, dispositions) {
1560
+ // THE EVOLVE-GATE ANSWER LANE (#58): `dispositions` ({retired, retyped, rebinds,
1561
+ // ackBy}) ride the committed installDomain payload — IN-HISTORY facts the one gate
1562
+ // adjudicates the stable-id diff against. Absent for the common (non-destructive)
1563
+ // upgrade; the gate's typed refusal names the remedy when one is needed.
1564
+ const result = author(eng, ws, "nomos", "installDomain", installPayload(domainHash, usda, eng.installedBy, dispositions), eng.hashes.nomos);
1522
1565
  // THE SHARD-IDENTITY ENSURE (#41 — slice 3a): a taxonomy-bearing law carries the
1523
1566
  // homing invariant, which judges against the workspace's OWN declared identity
1524
1567
  // (`NomosShardIdentity`, law-state in the shard's own chain). The worker is the