githolon 0.102.5 → 0.103.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/cli.mjs +7 -27235
- package/dist/compile-entry.mjs +94 -0
- package/dist/compile_mountability_entry.js +4146 -0
- package/dist/dev-server.mjs +971 -550
- package/dist/framework/bootstrap.law.usdz +0 -0
- package/dist/framework/nomos.law.usdz +0 -0
- package/dist/full-cli.mjs +21560 -0
- package/package.json +5 -4
- package/dist/framework/domain_bootstrap.package.usda +0 -11796
- package/dist/framework/domain_nomos.package.usda +0 -18384
|
@@ -0,0 +1,4146 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/cloud.ts
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
function cloudBase(flag) {
|
|
15
|
+
return (flag ?? process.env["NOMOS_CLOUD"] ?? DEFAULT_CLOUD).replace(/\/+$/, "");
|
|
16
|
+
}
|
|
17
|
+
function configDir() {
|
|
18
|
+
return process.env["HOLON_CONFIG_DIR"] ?? join(homedir(), ".holon");
|
|
19
|
+
}
|
|
20
|
+
var DEFAULT_CLOUD;
|
|
21
|
+
var init_cloud = __esm({
|
|
22
|
+
"src/cloud.ts"() {
|
|
23
|
+
"use strict";
|
|
24
|
+
DEFAULT_CLOUD = "https://nomos.cafe";
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// vendor/engine/git-fs.ts
|
|
29
|
+
function fsErr(code, p) {
|
|
30
|
+
const e = new Error(`${code}: ${p}`);
|
|
31
|
+
e.code = code;
|
|
32
|
+
return e;
|
|
33
|
+
}
|
|
34
|
+
function makeGitFs(preopen, mount, { File: File3, Directory: Directory3 }) {
|
|
35
|
+
const root = preopen.dir;
|
|
36
|
+
const isDir = (n) => !!n && n.contents instanceof Map;
|
|
37
|
+
function parts(p) {
|
|
38
|
+
if (p === mount) return [];
|
|
39
|
+
if (!p.startsWith(mount + "/")) throw fsErr("ENOENT", p);
|
|
40
|
+
const rel = p.slice(mount.length + 1).replace(/\/+$/, "");
|
|
41
|
+
return rel === "" ? [] : rel.split("/");
|
|
42
|
+
}
|
|
43
|
+
function resolve2(ps) {
|
|
44
|
+
let cur = root;
|
|
45
|
+
for (const part of ps) {
|
|
46
|
+
if (!isDir(cur)) return null;
|
|
47
|
+
const next = cur.contents.get(part);
|
|
48
|
+
if (next === void 0) return null;
|
|
49
|
+
cur = next;
|
|
50
|
+
}
|
|
51
|
+
return cur;
|
|
52
|
+
}
|
|
53
|
+
const parent = (ps) => resolve2(ps.slice(0, -1));
|
|
54
|
+
const leaf = (ps) => ps[ps.length - 1];
|
|
55
|
+
const promises = {
|
|
56
|
+
async readFile(p, opts) {
|
|
57
|
+
const n = resolve2(parts(p));
|
|
58
|
+
if (n === null) throw fsErr("ENOENT", p);
|
|
59
|
+
if (isDir(n)) throw fsErr("EISDIR", p);
|
|
60
|
+
const data = n.data ?? new Uint8Array(0);
|
|
61
|
+
const encoding = typeof opts === "string" ? opts : opts && opts.encoding;
|
|
62
|
+
return encoding ? new TextDecoder().decode(data) : new Uint8Array(data);
|
|
63
|
+
},
|
|
64
|
+
async writeFile(p, data) {
|
|
65
|
+
const ps = parts(p);
|
|
66
|
+
const par = parent(ps);
|
|
67
|
+
if (!isDir(par)) throw fsErr("ENOENT", p);
|
|
68
|
+
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
|
|
69
|
+
par.contents.set(leaf(ps), new File3(bytes));
|
|
70
|
+
},
|
|
71
|
+
async unlink(p) {
|
|
72
|
+
const ps = parts(p), par = parent(ps);
|
|
73
|
+
if (!isDir(par) || !par.contents.delete(leaf(ps))) throw fsErr("ENOENT", p);
|
|
74
|
+
},
|
|
75
|
+
async readdir(p) {
|
|
76
|
+
const n = resolve2(parts(p));
|
|
77
|
+
if (n === null) throw fsErr("ENOENT", p);
|
|
78
|
+
if (!isDir(n)) throw fsErr("ENOTDIR", p);
|
|
79
|
+
return [...n.contents.keys()];
|
|
80
|
+
},
|
|
81
|
+
async mkdir(p) {
|
|
82
|
+
const ps = parts(p), par = parent(ps);
|
|
83
|
+
if (!isDir(par)) throw fsErr("ENOENT", p);
|
|
84
|
+
if (par.contents.has(leaf(ps))) throw fsErr("EEXIST", p);
|
|
85
|
+
par.contents.set(leaf(ps), new Directory3(/* @__PURE__ */ new Map()));
|
|
86
|
+
},
|
|
87
|
+
async rmdir(p) {
|
|
88
|
+
const ps = parts(p), par = parent(ps);
|
|
89
|
+
if (!isDir(par)) throw fsErr("ENOENT", p);
|
|
90
|
+
par.contents.delete(leaf(ps));
|
|
91
|
+
},
|
|
92
|
+
async stat(p) {
|
|
93
|
+
return promises.lstat(p);
|
|
94
|
+
},
|
|
95
|
+
async lstat(p) {
|
|
96
|
+
const n = resolve2(parts(p));
|
|
97
|
+
if (n === null) throw fsErr("ENOENT", p);
|
|
98
|
+
const dir = isDir(n);
|
|
99
|
+
return {
|
|
100
|
+
type: dir ? "dir" : "file",
|
|
101
|
+
mode: dir ? 16384 : 33188,
|
|
102
|
+
size: dir ? 0 : n.data ? n.data.length : 0,
|
|
103
|
+
ino: 0,
|
|
104
|
+
mtimeMs: 0,
|
|
105
|
+
ctimeMs: 0,
|
|
106
|
+
uid: 1,
|
|
107
|
+
gid: 1,
|
|
108
|
+
dev: 1,
|
|
109
|
+
isFile: () => !dir,
|
|
110
|
+
isDirectory: () => dir,
|
|
111
|
+
isSymbolicLink: () => false
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
async readlink(p) {
|
|
115
|
+
throw fsErr("EINVAL", p);
|
|
116
|
+
},
|
|
117
|
+
async symlink() {
|
|
118
|
+
throw fsErr("EPERM", "symlink unsupported");
|
|
119
|
+
},
|
|
120
|
+
async chmod() {
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
return { promises };
|
|
124
|
+
}
|
|
125
|
+
var init_git_fs = __esm({
|
|
126
|
+
"vendor/engine/git-fs.ts"() {
|
|
127
|
+
"use strict";
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// vendor/engine/tree.ts
|
|
132
|
+
function flatten(dir, prefix, out2) {
|
|
133
|
+
const children = [...(dir.contents ?? /* @__PURE__ */ new Map()).entries()].sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);
|
|
134
|
+
for (const [name, inode] of children) {
|
|
135
|
+
const path = prefix ? prefix + "/" + name : name;
|
|
136
|
+
if (inode.contents instanceof Map) {
|
|
137
|
+
out2.push({ path, dir: true });
|
|
138
|
+
flatten(inode, path, out2);
|
|
139
|
+
} else {
|
|
140
|
+
out2.push({ path, dir: false, bytes: inode.data ?? new Uint8Array(0) });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function serializeTree(workTree) {
|
|
145
|
+
const entries = [];
|
|
146
|
+
flatten(workTree, "", entries);
|
|
147
|
+
const chunks = [];
|
|
148
|
+
const header = new Uint8Array(4);
|
|
149
|
+
new DataView(header.buffer).setUint32(0, entries.length, true);
|
|
150
|
+
chunks.push(header);
|
|
151
|
+
for (const e of entries) {
|
|
152
|
+
const pathBytes = enc.encode(e.path);
|
|
153
|
+
const body = e.dir ? new Uint8Array(0) : e.bytes ?? new Uint8Array(0);
|
|
154
|
+
const meta = new Uint8Array(9);
|
|
155
|
+
const dv = new DataView(meta.buffer);
|
|
156
|
+
dv.setUint8(0, e.dir ? 1 : 0);
|
|
157
|
+
dv.setUint32(1, pathBytes.length, true);
|
|
158
|
+
dv.setUint32(5, body.length, true);
|
|
159
|
+
chunks.push(meta, pathBytes, body);
|
|
160
|
+
}
|
|
161
|
+
let total = 0;
|
|
162
|
+
for (const c of chunks) total += c.length;
|
|
163
|
+
const out2 = new Uint8Array(total);
|
|
164
|
+
let off = 0;
|
|
165
|
+
for (const c of chunks) {
|
|
166
|
+
out2.set(c, off);
|
|
167
|
+
off += c.length;
|
|
168
|
+
}
|
|
169
|
+
return out2;
|
|
170
|
+
}
|
|
171
|
+
var enc, dec;
|
|
172
|
+
var init_tree = __esm({
|
|
173
|
+
"vendor/engine/tree.ts"() {
|
|
174
|
+
"use strict";
|
|
175
|
+
enc = new TextEncoder();
|
|
176
|
+
dec = new TextDecoder();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// vendor/engine/custody-transport.ts
|
|
181
|
+
function concatBytes(chunks) {
|
|
182
|
+
let n = 0;
|
|
183
|
+
for (const c of chunks) n += c.length;
|
|
184
|
+
const out2 = new Uint8Array(n);
|
|
185
|
+
let o = 0;
|
|
186
|
+
for (const c of chunks) {
|
|
187
|
+
out2.set(c, o);
|
|
188
|
+
o += c.length;
|
|
189
|
+
}
|
|
190
|
+
return out2;
|
|
191
|
+
}
|
|
192
|
+
function pkt(payload) {
|
|
193
|
+
const body = typeof payload === "string" ? enc2.encode(payload) : payload;
|
|
194
|
+
const len = (body.length + 4).toString(16).padStart(4, "0");
|
|
195
|
+
return concatBytes([enc2.encode(len), body]);
|
|
196
|
+
}
|
|
197
|
+
function readPktLines(buf, off = 0) {
|
|
198
|
+
const lines = [];
|
|
199
|
+
while (off + 4 <= buf.length) {
|
|
200
|
+
const hex = dec2.decode(buf.subarray(off, off + 4));
|
|
201
|
+
if (!/^[0-9a-f]{4}$/.test(hex)) break;
|
|
202
|
+
const len = parseInt(hex, 16);
|
|
203
|
+
if (len === 0) {
|
|
204
|
+
off += 4;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
if (len < 4 || off + len > buf.length) break;
|
|
208
|
+
lines.push(buf.subarray(off + 4, off + len));
|
|
209
|
+
off += len;
|
|
210
|
+
}
|
|
211
|
+
return { lines, rest: off };
|
|
212
|
+
}
|
|
213
|
+
async function lsRefs(remote, headers = {}, { service = "git-upload-pack", prefix = null } = {}, fetchImpl = fetch) {
|
|
214
|
+
const r = await fetchImpl(`${remote}/info/refs?service=${service}`, { headers });
|
|
215
|
+
if (!r.ok) {
|
|
216
|
+
if (r.status === 404) return {};
|
|
217
|
+
throw new Error(`info/refs ${r.status}: ${(await r.text()).slice(0, 180)}`);
|
|
218
|
+
}
|
|
219
|
+
const buf = new Uint8Array(await r.arrayBuffer());
|
|
220
|
+
const banner = readPktLines(buf, 0);
|
|
221
|
+
const { lines } = readPktLines(buf, banner.rest);
|
|
222
|
+
const refs = {};
|
|
223
|
+
for (const line of lines) {
|
|
224
|
+
let s = dec2.decode(line).replace(/\n$/, "");
|
|
225
|
+
if (s.startsWith("#")) continue;
|
|
226
|
+
const nul = s.indexOf("\0");
|
|
227
|
+
if (nul >= 0) s = s.slice(0, nul);
|
|
228
|
+
const sp = s.indexOf(" ");
|
|
229
|
+
if (sp !== 40) continue;
|
|
230
|
+
const oid = s.slice(0, 40), name = s.slice(41);
|
|
231
|
+
if (!/^[0-9a-f]{40}$/.test(oid)) continue;
|
|
232
|
+
if (prefix && !name.startsWith(prefix)) continue;
|
|
233
|
+
refs[name] = oid;
|
|
234
|
+
}
|
|
235
|
+
return refs;
|
|
236
|
+
}
|
|
237
|
+
async function fetchPack(remote, headers = {}, { wants = [], haves = [] } = {}) {
|
|
238
|
+
wants = wants.filter((w) => /^[0-9a-f]{40}$/.test(w) && w !== ZERO_OID);
|
|
239
|
+
if (!wants.length) return null;
|
|
240
|
+
const caps = "ofs-delta agent=nomos-cloud";
|
|
241
|
+
const parts = [];
|
|
242
|
+
wants.forEach((w, i) => parts.push(pkt(`want ${w}${i === 0 ? " " + caps : ""}
|
|
243
|
+
`)));
|
|
244
|
+
parts.push(FLUSH);
|
|
245
|
+
for (const h of haves) if (/^[0-9a-f]{40}$/.test(h) && h !== ZERO_OID) parts.push(pkt(`have ${h}
|
|
246
|
+
`));
|
|
247
|
+
parts.push(pkt("done\n"));
|
|
248
|
+
const r = await fetch(`${remote}/git-upload-pack`, {
|
|
249
|
+
method: "POST",
|
|
250
|
+
headers: { "content-type": "application/x-git-upload-pack-request", "accept": "application/x-git-upload-pack-result", ...headers },
|
|
251
|
+
body: concatBytes(parts)
|
|
252
|
+
});
|
|
253
|
+
if (!r.ok) throw new Error(`upload-pack ${r.status}: ${(await r.text()).slice(0, 180)}`);
|
|
254
|
+
const buf = new Uint8Array(await r.arrayBuffer());
|
|
255
|
+
const { lines, rest } = readPktLines(buf, 0);
|
|
256
|
+
const packChunks = [];
|
|
257
|
+
let sideband = false;
|
|
258
|
+
for (const line of lines) {
|
|
259
|
+
if (line.length === 0) continue;
|
|
260
|
+
const head = dec2.decode(line.subarray(0, Math.min(line.length, 3)));
|
|
261
|
+
if (head === "NAK" || head === "ACK" || head === "ERR" || head.startsWith("sha")) continue;
|
|
262
|
+
const band = line[0];
|
|
263
|
+
if (band === 1) {
|
|
264
|
+
packChunks.push(line.subarray(1));
|
|
265
|
+
sideband = true;
|
|
266
|
+
} else if (band === 2) {
|
|
267
|
+
} else if (band === 3) {
|
|
268
|
+
throw new Error("upload-pack fatal: " + dec2.decode(line.subarray(1)).slice(0, 180));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const pack = sideband ? concatBytes(packChunks) : buf.subarray(rest);
|
|
272
|
+
if (pack.length < 12 || dec2.decode(pack.subarray(0, 4)) !== "PACK") {
|
|
273
|
+
throw new Error(`upload-pack: no pack in response (${pack.length}B, sideband=${sideband})`);
|
|
274
|
+
}
|
|
275
|
+
return pack;
|
|
276
|
+
}
|
|
277
|
+
async function pushPack(remote, headers = {}, { updates = [], pack = null } = {}, fetchImpl = fetch) {
|
|
278
|
+
if (!updates.length) return { ok: true, noop: true };
|
|
279
|
+
const cmds = [];
|
|
280
|
+
updates.forEach((u, i) => {
|
|
281
|
+
const old = u.oldOid || ZERO_OID;
|
|
282
|
+
const neu = u.newOid || ZERO_OID;
|
|
283
|
+
const caps = i === 0 ? "\0report-status" : "";
|
|
284
|
+
cmds.push(pkt(`${old} ${neu} ${u.ref}${caps}
|
|
285
|
+
`));
|
|
286
|
+
});
|
|
287
|
+
cmds.push(FLUSH);
|
|
288
|
+
const body = concatBytes([...cmds, pack && pack.length ? pack : EMPTY_PACK]);
|
|
289
|
+
let r;
|
|
290
|
+
try {
|
|
291
|
+
r = await fetchImpl(`${remote}/git-receive-pack`, {
|
|
292
|
+
method: "POST",
|
|
293
|
+
headers: { "content-type": "application/x-git-receive-pack-request", ...headers },
|
|
294
|
+
body
|
|
295
|
+
});
|
|
296
|
+
} catch (error) {
|
|
297
|
+
throw new Error(`receive-pack transport failed (${body.byteLength} bytes): ${String(error)}`, { cause: error });
|
|
298
|
+
}
|
|
299
|
+
const txt = dec2.decode(new Uint8Array(await r.arrayBuffer()));
|
|
300
|
+
const unpacked = /unpack ok/.test(txt);
|
|
301
|
+
const everyRefOk = updates.every((u) => new RegExp(`ok ${u.ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`).test(txt));
|
|
302
|
+
if (!(r.ok && unpacked && everyRefOk && !/\bng /.test(txt))) {
|
|
303
|
+
throw new Error(`receive-pack ${r.status}: ${txt.replace(/[^\x20-\x7e]/g, " ").trim().slice(0, 200)}`);
|
|
304
|
+
}
|
|
305
|
+
return { ok: true };
|
|
306
|
+
}
|
|
307
|
+
var enc2, dec2, ZERO_OID, EMPTY_PACK, FLUSH;
|
|
308
|
+
var init_custody_transport = __esm({
|
|
309
|
+
"vendor/engine/custody-transport.ts"() {
|
|
310
|
+
"use strict";
|
|
311
|
+
enc2 = new TextEncoder();
|
|
312
|
+
dec2 = new TextDecoder();
|
|
313
|
+
ZERO_OID = "0".repeat(40);
|
|
314
|
+
EMPTY_PACK = new Uint8Array([
|
|
315
|
+
80,
|
|
316
|
+
65,
|
|
317
|
+
67,
|
|
318
|
+
75,
|
|
319
|
+
0,
|
|
320
|
+
0,
|
|
321
|
+
0,
|
|
322
|
+
2,
|
|
323
|
+
0,
|
|
324
|
+
0,
|
|
325
|
+
0,
|
|
326
|
+
0,
|
|
327
|
+
// "PACK", ver 2, 0 objects
|
|
328
|
+
2,
|
|
329
|
+
157,
|
|
330
|
+
8,
|
|
331
|
+
130,
|
|
332
|
+
59,
|
|
333
|
+
216,
|
|
334
|
+
168,
|
|
335
|
+
234,
|
|
336
|
+
181,
|
|
337
|
+
16,
|
|
338
|
+
173,
|
|
339
|
+
106,
|
|
340
|
+
// sha1(the 12 header bytes)
|
|
341
|
+
199,
|
|
342
|
+
92,
|
|
343
|
+
130,
|
|
344
|
+
60,
|
|
345
|
+
253,
|
|
346
|
+
62,
|
|
347
|
+
211,
|
|
348
|
+
30
|
|
349
|
+
]);
|
|
350
|
+
FLUSH = enc2.encode("0000");
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// vendor/engine/managed-promotion.ts
|
|
355
|
+
function prepareManagedPromotion(report, candidateHash, domain, opts = {}) {
|
|
356
|
+
if (!report.sourceVerified || !report.complete || !report.evolve?.ok) {
|
|
357
|
+
const reason = !report.sourceVerified ? "the source ledger did not verify" : !report.complete ? "some historical premises could not be re-derived" : "the candidate fails deterministic schema evolution";
|
|
358
|
+
return { ok: false, stage: "preflight", report, error: `promotion refused: ${reason}` };
|
|
359
|
+
}
|
|
360
|
+
const acceptanceReason = opts.acceptanceReason?.trim();
|
|
361
|
+
if (!report.promotable && !acceptanceReason) {
|
|
362
|
+
return {
|
|
363
|
+
ok: false,
|
|
364
|
+
stage: "acceptance",
|
|
365
|
+
report,
|
|
366
|
+
error: "exact history changes under the candidate; provide an acceptanceReason to make that business decision accountable"
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
if (!report.atStateRoot || !report.historyHash || !report.reportHash || !report.projection) {
|
|
370
|
+
return {
|
|
371
|
+
ok: false,
|
|
372
|
+
stage: "preflight",
|
|
373
|
+
report,
|
|
374
|
+
error: "the complete pre-flight report is missing its state, projection, or content proof"
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
const provedDomains = report.domains?.length ? report.domains : [report.domain];
|
|
378
|
+
if (!provedDomains.includes(domain)) {
|
|
379
|
+
return {
|
|
380
|
+
ok: false,
|
|
381
|
+
stage: "preflight",
|
|
382
|
+
report,
|
|
383
|
+
error: `the package-wide report does not cover the generated business area '${domain}'`
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
const reportEvidence = JSON.parse(JSON.stringify(report));
|
|
387
|
+
if (Array.isArray(reportEvidence.divergences)) {
|
|
388
|
+
for (const divergence of reportEvidence.divergences) {
|
|
389
|
+
if (divergence && typeof divergence === "object") {
|
|
390
|
+
delete divergence.atCommit;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const preflight = {
|
|
395
|
+
candidateHash,
|
|
396
|
+
// A package may be reached through any one of its generated domain clients. The
|
|
397
|
+
// kernel chooses one canonical domain for the private receipt so the exact same
|
|
398
|
+
// package/history proof has one identity regardless of that entry point.
|
|
399
|
+
domain: report.domain,
|
|
400
|
+
atHash: report.atHash,
|
|
401
|
+
atStateRoot: report.atStateRoot,
|
|
402
|
+
historyHash: report.historyHash,
|
|
403
|
+
reportHash: report.reportHash,
|
|
404
|
+
reportJson: JSON.stringify(reportEvidence),
|
|
405
|
+
complete: true,
|
|
406
|
+
evolveOk: true,
|
|
407
|
+
rawPromotable: report.promotable,
|
|
408
|
+
projectionEqual: report.projection.equal,
|
|
409
|
+
replayedIntents: report.replayedIntents,
|
|
410
|
+
candidateIntents: report.candidateIntents,
|
|
411
|
+
divergenceCount: report.divergences.length,
|
|
412
|
+
baselineRoot: report.projection.baselineRoot,
|
|
413
|
+
candidateRoot: report.projection.candidateRoot,
|
|
414
|
+
...!report.promotable && acceptanceReason ? { acceptanceReason } : {}
|
|
415
|
+
};
|
|
416
|
+
return {
|
|
417
|
+
ok: true,
|
|
418
|
+
stage: "ready",
|
|
419
|
+
report,
|
|
420
|
+
receiptId: `${RELEASE_RECEIPT_PREFIX}${report.reportHash}`,
|
|
421
|
+
payload: {
|
|
422
|
+
domainHash: candidateHash,
|
|
423
|
+
...opts.replaces ? { replaces: opts.replaces } : {},
|
|
424
|
+
retireReplaced: opts.retireReplaced ?? false,
|
|
425
|
+
...opts.dispositions ? { dispositions: opts.dispositions } : {},
|
|
426
|
+
preflight
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
function prepareManagedRestoration(report, currentHash, priorHash, domain, opts = {}) {
|
|
431
|
+
if (!report.dispositions || typeof report.dispositions !== "object") {
|
|
432
|
+
return {
|
|
433
|
+
ok: false,
|
|
434
|
+
stage: "preflight",
|
|
435
|
+
report,
|
|
436
|
+
error: "restoration refused: the exact-history proof did not derive its predecessor dispositions"
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
const acceptanceReason = opts.acceptanceReason?.trim();
|
|
440
|
+
const prepared = prepareManagedPromotion(report, priorHash, domain, {
|
|
441
|
+
dispositions: report.dispositions,
|
|
442
|
+
...acceptanceReason ? { acceptanceReason } : {}
|
|
443
|
+
});
|
|
444
|
+
if (!prepared.ok) {
|
|
445
|
+
return {
|
|
446
|
+
...prepared,
|
|
447
|
+
stage: prepared.stage === "acceptance" ? "acceptance" : "preflight"
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
if (!acceptanceReason) {
|
|
451
|
+
return {
|
|
452
|
+
ok: false,
|
|
453
|
+
stage: "acceptance",
|
|
454
|
+
report,
|
|
455
|
+
error: "restoring previous law needs a business reason even when historical outcomes are unchanged"
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
return {
|
|
459
|
+
ok: true,
|
|
460
|
+
stage: "ready",
|
|
461
|
+
report,
|
|
462
|
+
receiptId: prepared.receiptId,
|
|
463
|
+
payload: {
|
|
464
|
+
candidateHash: currentHash,
|
|
465
|
+
priorHash,
|
|
466
|
+
dispositions: report.dispositions,
|
|
467
|
+
preflight: prepared.payload.preflight
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
var RELEASE_RECEIPT_PREFIX;
|
|
472
|
+
var init_managed_promotion = __esm({
|
|
473
|
+
"vendor/engine/managed-promotion.ts"() {
|
|
474
|
+
"use strict";
|
|
475
|
+
RELEASE_RECEIPT_PREFIX = "nomos-release-receipt:";
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
// vendor/engine/proto/nomos/kernel/v1/kernel_pb.js
|
|
480
|
+
import { enumDesc, fileDesc, messageDesc, serviceDesc, tsEnum } from "@bufbuild/protobuf/codegenv2";
|
|
481
|
+
var file_nomos_kernel_v1_kernel, CallRequestSchema, CallResponseSchema, WorkspaceTargetSchema, DirectiveCallSchema, AuthoringOptionsSchema, CapturedClockSchema, OfferRequestSchema, QueryRequestSchema, QueryAuthoritySchema, InjectedKeySchema, RowsQuerySchema, PageQuerySchema, ByIdQuerySchema, TallyQuerySchema, SpatialQuerySchema, NamedQuerySchema, AuthorizationObjectSchema, AuthorizationSubjectSchema, AuthorizationConsistencySchema, AuthorizationCheckRequestSchema, AuthorizationExpandRequestSchema, OutboxRequestSchema, SyncRequestSchema, TestRequestSchema, SetTestRootRequestSchema, CustodyRequestSchema, PackDeltaRequestSchema, ApplyPackRequestSchema, RepoStatsRequestSchema, IntentsAboveRequestSchema, InspectChangeRequestSchema, EncodeDocumentRequestSchema, InspectDocumentRequestSchema, ReadBlobRequestSchema, ResolveRefRequestSchema, ListRefsRequestSchema, WriteRefRequestSchema, DeleteRefRequestSchema, WriteMetaCommitRequestSchema, LawClosureInfoRequestSchema, CheckpointExportRequestSchema, CheckpointImportRequestSchema, CapacityReserveRequestSchema, RestoreMainRequestSchema, NomosValueSchema, NomosStructSchema, QueryOperationSchema, QueryOperation;
|
|
482
|
+
var init_kernel_pb = __esm({
|
|
483
|
+
"vendor/engine/proto/nomos/kernel/v1/kernel_pb.js"() {
|
|
484
|
+
"use strict";
|
|
485
|
+
file_nomos_kernel_v1_kernel = /* @__PURE__ */ fileDesc("Chxub21vcy9rZXJuZWwvdjEva2VybmVsLnByb3RvEg9ub21vcy5rZXJuZWwudjEimAMKC0NhbGxSZXF1ZXN0EhgKEHByb3RvY29sX3ZlcnNpb24YASABKA0SEgoKcmVxdWVzdF9pZBgCIAEoCRIsCgRvcGVuGAogASgLMhwubm9tb3Mua2VybmVsLnYxLk9wZW5SZXF1ZXN0SAASLgoFb2ZmZXIYCyABKAsyHS5ub21vcy5rZXJuZWwudjEuT2ZmZXJSZXF1ZXN0SAASLgoFcXVlcnkYDCABKAsyHS5ub21vcy5rZXJuZWwudjEuUXVlcnlSZXF1ZXN0SAASMAoGb3V0Ym94GA0gASgLMh4ubm9tb3Mua2VybmVsLnYxLk91dGJveFJlcXVlc3RIABIsCgRzeW5jGA4gASgLMhwubm9tb3Mua2VybmVsLnYxLlN5bmNSZXF1ZXN0SAASMgoHY3VzdG9keRgPIAEoCzIfLm5vbW9zLmtlcm5lbC52MS5DdXN0b2R5UmVxdWVzdEgAEiwKBHRlc3QYECABKAsyHC5ub21vcy5rZXJuZWwudjEuVGVzdFJlcXVlc3RIAEILCglvcGVyYXRpb24iywMKDENhbGxSZXNwb25zZRIYChBwcm90b2NvbF92ZXJzaW9uGAEgASgNEhIKCnJlcXVlc3RfaWQYAiABKAkSKwoHZmFpbHVyZRgKIAEoCzIYLm5vbW9zLmtlcm5lbC52MS5GYWlsdXJlSAASLQoEb3BlbhgLIAEoCzIdLm5vbW9zLmtlcm5lbC52MS5PcGVuUmVzcG9uc2VIABIvCgVvZmZlchgMIAEoCzIeLm5vbW9zLmtlcm5lbC52MS5PZmZlclJlc3BvbnNlSAASLwoFcXVlcnkYDSABKAsyHi5ub21vcy5rZXJuZWwudjEuUXVlcnlSZXNwb25zZUgAEjEKBm91dGJveBgOIAEoCzIfLm5vbW9zLmtlcm5lbC52MS5PdXRib3hSZXNwb25zZUgAEi0KBHN5bmMYDyABKAsyHS5ub21vcy5rZXJuZWwudjEuU3luY1Jlc3BvbnNlSAASMwoHY3VzdG9keRgQIAEoCzIgLm5vbW9zLmtlcm5lbC52MS5DdXN0b2R5UmVzcG9uc2VIABItCgR0ZXN0GBEgASgLMh0ubm9tb3Mua2VybmVsLnYxLlRlc3RSZXNwb25zZUgAQgkKB291dGNvbWUiVwoHRmFpbHVyZRIMCgRjb2RlGAEgASgJEg8KB21lc3NhZ2UYAiABKAkSLQoHZGV0YWlscxgDIAEoCzIcLm5vbW9zLmtlcm5lbC52MS5Ob21vc1N0cnVjdCI8CgxPcGVuUmVzcG9uc2USLAoGcmVzdWx0GAEgASgLMhwubm9tb3Mua2VybmVsLnYxLk5vbW9zU3RydWN0IsMCCg1PZmZlclJlc3BvbnNlEjIKCGFkbWl0dGVkGAEgASgLMh4ubm9tb3Mua2VybmVsLnYxLk9mZmVyQWRtaXR0ZWRIABIwCgdyZWZ1c2VkGAIgASgLMh0ubm9tb3Mua2VybmVsLnYxLk9mZmVyUmVmdXNlZEgAEjsKDWRlYWRfbGV0dGVyZWQYAyABKAsyIi5ub21vcy5rZXJuZWwudjEuT2ZmZXJEZWFkTGV0dGVyZWRIABI4CgtxdWFyYW50aW5lZBgEIAEoCzIhLm5vbW9zLmtlcm5lbC52MS5PZmZlclF1YXJhbnRpbmVkSAASSgoVYmxvY2tlZF9vbl9kZXBlbmRlbmN5GAUgASgLMikubm9tb3Mua2VybmVsLnYxLk9mZmVyQmxvY2tlZE9uRGVwZW5kZW5jeUgAQgkKB291dGNvbWUiPQoNT2ZmZXJBZG1pdHRlZBIsCgZyZXN1bHQYASABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3QilgEKDE9mZmVyUmVmdXNlZBIVCghvZmZlcl9pZBgBIAEoCUgAiAEBEi8KB3JlZnVzYWwYAiABKAsyHi5ub21vcy5rZXJuZWwudjEuS2VybmVsUmVmdXNhbBIxCgtkaWFnbm9zdGljcxgDIAEoCzIcLm5vbW9zLmtlcm5lbC52MS5Ob21vc1N0cnVjdEILCglfb2ZmZXJfaWQiegoRT2ZmZXJEZWFkTGV0dGVyZWQSFQoIb2ZmZXJfaWQYASABKAlIAIgBARIOCgZyZWFzb24YAiABKAkSMQoLZGlhZ25vc3RpY3MYAyABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3RCCwoJX29mZmVyX2lkIq4BChBPZmZlclF1YXJhbnRpbmVkEhUKCG9mZmVyX2lkGAEgASgJSACIAQESGQoRYXV0aG9yZWRfbGF3X2hhc2gYAiABKAkSGAoQY3VycmVudF9sYXdfaGFzaBgDIAEoCRIOCgZyZWFzb24YBCABKAkSMQoLZGlhZ25vc3RpY3MYBSABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3RCCwoJX29mZmVyX2lkIoEBChhPZmZlckJsb2NrZWRPbkRlcGVuZGVuY3kSFQoIb2ZmZXJfaWQYASABKAlIAIgBARIOCgZkZXRhaWwYAiABKAkSMQoLZGlhZ25vc3RpY3MYAyABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3RCCwoJX29mZmVyX2lkIoEBCg1LZXJuZWxSZWZ1c2FsEjAKBGNvZGUYASABKA4yIi5ub21vcy5rZXJuZWwudjEuS2VybmVsUmVmdXNhbENvZGUSDwoHbWVzc2FnZRgCIAEoCRItCgdkZXRhaWxzGAMgASgLMhwubm9tb3Mua2VybmVsLnYxLk5vbW9zU3RydWN0IqQCCg1RdWVyeVJlc3BvbnNlEiwKBXZhbHVlGAEgASgLMhsubm9tb3Mua2VybmVsLnYxLk5vbW9zVmFsdWVIABJBChBhcHBsaWNhdGlvbl9qc29uGAIgASgLMiUubm9tb3Mua2VybmVsLnYxLkFwcGxpY2F0aW9uSnNvblZhbHVlSAASSgoTYXV0aG9yaXphdGlvbl9jaGVjaxgKIAEoCzIrLm5vbW9zLmtlcm5lbC52MS5BdXRob3JpemF0aW9uQ2hlY2tSZXNwb25zZUgAEkwKFGF1dGhvcml6YXRpb25fZXhwYW5kGAsgASgLMiwubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25FeHBhbmRSZXNwb25zZUgAQggKBnJlc3VsdCIkChRBcHBsaWNhdGlvbkpzb25WYWx1ZRIMCgR1dGY4GAEgASgMIj4KDk91dGJveFJlc3BvbnNlEiwKBnJlc3VsdBgBIAEoCzIcLm5vbW9zLmtlcm5lbC52MS5Ob21vc1N0cnVjdCI8CgxTeW5jUmVzcG9uc2USLAoGcmVzdWx0GAEgASgLMhwubm9tb3Mua2VybmVsLnYxLk5vbW9zU3RydWN0IkIKD1dvcmtzcGFjZVRhcmdldBIMCgRyZXBvGAEgASgJEhEKCXdvcmtzcGFjZRgCIAEoCRIOCgZicmFuY2gYAyABKAkiTgoLT3BlblJlcXVlc3QSMAoGdGFyZ2V0GAEgASgLMiAubm9tb3Mua2VybmVsLnYxLldvcmtzcGFjZVRhcmdldBINCgVzcGFucxgCIAEoCCJhCg1EaXJlY3RpdmVDYWxsEg4KBmRvbWFpbhgBIAEoCRIRCglkaXJlY3RpdmUYAiABKAkSLQoHcGF5bG9hZBgDIAEoCzIcLm5vbW9zLmtlcm5lbC52MS5Ob21vc1N0cnVjdCLAAgoQQXV0aG9yaW5nT3B0aW9ucxINCgVhY3RvchgBIAEoCRISCgphdXRoX3Rva2VuGAIgASgMEhUKDWF1dGhvcl9zZWNyZXQYAyABKAwSHQoQdmFsaWRfZnJvbV9lcG9jaBgEIAEoBEgAiAEBEh8KEnByaW5jaXBhbF92ZXJpZmllZBgFIAEoCEgBiAEBEgsKA3JuZxgGIAMoARIYChBkZWZlcl9wcm9qZWN0aW9uGAcgASgIEg0KBXNwYW5zGAggASgIEg8KB2RyeV9ydW4YCSABKAgSEAoIc2VxdWVuY2UYCiABKAQSLQoFY2xvY2sYCyABKAsyHi5ub21vcy5rZXJuZWwudjEuQ2FwdHVyZWRDbG9ja0ITChFfdmFsaWRfZnJvbV9lcG9jaEIVChNfcHJpbmNpcGFsX3ZlcmlmaWVkIkoKDUNhcHR1cmVkQ2xvY2sSFwoPcGh5c2ljYWxfbWlsbGlzGAEgASgEEg8KB2xvZ2ljYWwYAiABKA0SDwoHcmVwbGljYRgDIAEoBCLeAwoMT2ZmZXJSZXF1ZXN0EjAKBnRhcmdldBgBIAEoCzIgLm5vbW9zLmtlcm5lbC52MS5Xb3Jrc3BhY2VUYXJnZXQSLgoEY2FsbBgCIAEoCzIeLm5vbW9zLmtlcm5lbC52MS5EaXJlY3RpdmVDYWxsSAASHAoSc2VhbGVkX2NoYW5nZV91c2RhGAcgASgMSAASNAoJYXV0aG9yaW5nGAMgASgLMiEubm9tb3Mua2VybmVsLnYxLkF1dGhvcmluZ09wdGlvbnMSEAoIbGF3X3VzZHoYBCABKAwSMwoMYXR0ZXN0YXRpb25zGAUgAygLMh0ubm9tb3Mua2VybmVsLnYxLkF0dGVzdGVkUmVhZBI9ChJjb25mbGljdF9zbmFwc2hvdHMYBiADKAsyIS5ub21vcy5rZXJuZWwudjEuQ29uZmxpY3RTbmFwc2hvdBIaChJleGVjdXRpb25fbGF3X3VzZHoYCCABKAwSIAoTY29udHJvbGxlcl9sYXdfaGFzaBgJIAEoCUgBiAEBEh0KEGNhbmRpZGF0ZV9jb21taXQYCiABKAlIAogBAUIICgZpbnRlbnRCFgoUX2NvbnRyb2xsZXJfbGF3X2hhc2hCEwoRX2NhbmRpZGF0ZV9jb21taXQikwEKDEF0dGVzdGVkUmVhZBIQCghxdWVyeV9pZBgBIAEoCRIvCglhcmd1bWVudHMYAiABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3QSKwoGcmVzdWx0GAMgASgLMhsubm9tb3Mua2VybmVsLnYxLk5vbW9zVmFsdWUSEwoLYXR0ZXN0YXRpb24YBCABKAwidQoQQ29uZmxpY3RTbmFwc2hvdBIWCg5hZ2dyZWdhdGVfdHlwZRgBIAEoCRIUCgxhZ2dyZWdhdGVfaWQYAiABKAkSDQoFZmllbGQYAyABKAkSFQoNdGFyZ2V0X3NjaGVtYRgEIAEoCRINCgV0b2tlbhgFIAEoCSLbBQoMUXVlcnlSZXF1ZXN0EjAKBnRhcmdldBgBIAEoCzIgLm5vbW9zLmtlcm5lbC52MS5Xb3Jrc3BhY2VUYXJnZXQSMgoJYXV0aG9yaXR5GAIgASgLMh8ubm9tb3Mua2VybmVsLnYxLlF1ZXJ5QXV0aG9yaXR5Eg0KBXNwYW5zGAMgASgIEioKBHJvd3MYCiABKAsyGi5ub21vcy5rZXJuZWwudjEuUm93c1F1ZXJ5SAASKgoEcGFnZRgLIAEoCzIaLm5vbW9zLmtlcm5lbC52MS5QYWdlUXVlcnlIABIrCgVieV9pZBgMIAEoCzIaLm5vbW9zLmtlcm5lbC52MS5CeUlkUXVlcnlIABI5CgxyZXNvbHZlX3JlZnMYDSABKAsyIS5ub21vcy5rZXJuZWwudjEuUmVzb2x2ZVJlZnNRdWVyeUgAEjsKDXJlZl9mcmVzaG5lc3MYDiABKAsyIi5ub21vcy5rZXJuZWwudjEuUmVmRnJlc2huZXNzUXVlcnlIABIsCgVjb3VudBgPIAEoCzIbLm5vbW9zLmtlcm5lbC52MS5UYWxseVF1ZXJ5SAASKgoDc3VtGBAgASgLMhsubm9tb3Mua2VybmVsLnYxLlRhbGx5UXVlcnlIABIwCgdzcGF0aWFsGBEgASgLMh0ubm9tb3Mua2VybmVsLnYxLlNwYXRpYWxRdWVyeUgAEiwKBW5hbWVkGBIgASgLMhsubm9tb3Mua2VybmVsLnYxLk5hbWVkUXVlcnlIABJJChNhdXRob3JpemF0aW9uX2NoZWNrGBMgASgLMioubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25DaGVja1JlcXVlc3RIABJLChRhdXRob3JpemF0aW9uX2V4cGFuZBgUIAEoCzIrLm5vbW9zLmtlcm5lbC52MS5BdXRob3JpemF0aW9uRXhwYW5kUmVxdWVzdEgAQgcKBXF1ZXJ5IpIBCg5RdWVyeUF1dGhvcml0eRIXCg9wcmluY2lwYWxfY2xhaW0YASABKAkSEgoKYXV0aF90b2tlbhgCIAEoDBIQCghub3dfdW5peBgDIAEoBBIVCg1hdXRob3Jfc2VjcmV0GAQgASgMEioKBGtleXMYBSADKAsyHC5ub21vcy5rZXJuZWwudjEuSW5qZWN0ZWRLZXkiOAoLSW5qZWN0ZWRLZXkSDQoFc2NvcGUYASABKAkSDQoFZXBvY2gYAiABKAQSCwoDa2V5GAMgASgMIlsKCVJvd3NRdWVyeRIKCgJpZBgBIAEoCRIvCglhcmd1bWVudHMYAiABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3QSEQoJcHJpbmNpcGFsGAMgASgJInkKCVBhZ2VRdWVyeRIKCgJpZBgBIAEoCRIvCglhcmd1bWVudHMYAiABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3QSDQoFbGltaXQYAyABKA0SDQoFYWZ0ZXIYBCABKAkSEQoJcHJpbmNpcGFsGAUgASgJIkwKCUJ5SWRRdWVyeRIWCg5hZ2dyZWdhdGVfdHlwZRgBIAEoCRIUCgxhZ2dyZWdhdGVfaWQYAiABKAkSEQoJcHJpbmNpcGFsGAMgASgJIlwKCE5vbW9zUmVmEhEKCXdvcmtzcGFjZRgBIAEoCRIWCg5hZ2dyZWdhdGVfdHlwZRgCIAEoCRIUCgxhZ2dyZWdhdGVfaWQYAyABKAkSDwoHdmVyc2lvbhgEIAEoCSJOChBSZXNvbHZlUmVmc1F1ZXJ5EicKBHJlZnMYASADKAsyGS5ub21vcy5rZXJuZWwudjEuTm9tb3NSZWYSEQoJcHJpbmNpcGFsGAIgASgJIkUKEVJlZkZyZXNobmVzc1F1ZXJ5EjAKBHJlZnMYASADKAsyIi5ub21vcy5rZXJuZWwudjEuUmVmRnJlc2huZXNzQ2hlY2sigAEKEVJlZkZyZXNobmVzc0NoZWNrEikKBnBpbm5lZBgBIAEoCzIZLm5vbW9zLmtlcm5lbC52MS5Ob21vc1JlZhIpCgZzZXJpZXMYAiABKAsyGS5ub21vcy5rZXJuZWwudjEuTm9tb3NSZWYSFQoNY3VycmVudF9maWVsZBgDIAEoCSJcCgpUYWxseVF1ZXJ5EgoKAmlkGAEgASgJEi8KCWFyZ3VtZW50cxgCIAEoCzIcLm5vbW9zLmtlcm5lbC52MS5Ob21vc1N0cnVjdBIRCglwcmluY2lwYWwYAyABKAkiXgoMU3BhdGlhbFF1ZXJ5EgoKAmlkGAEgASgJEi8KCWFyZ3VtZW50cxgCIAEoCzIcLm5vbW9zLmtlcm5lbC52MS5Ob21vc1N0cnVjdBIRCglwcmluY2lwYWwYAyABKAkicQoKTmFtZWRRdWVyeRIyCglvcGVyYXRpb24YASABKA4yHy5ub21vcy5rZXJuZWwudjEuUXVlcnlPcGVyYXRpb24SLwoJYXJndW1lbnRzGAIgASgLMhwubm9tb3Mua2VybmVsLnYxLk5vbW9zU3RydWN0Ii8KE0F1dGhvcml6YXRpb25PYmplY3QSDAoEdHlwZRgBIAEoCRIKCgJpZBgCIAEoCSJUChRBdXRob3JpemF0aW9uU3ViamVjdBIMCgR0eXBlGAEgASgJEgoKAmlkGAIgASgJEhUKCHJlbGF0aW9uGAMgASgJSACIAQFCCwoJX3JlbGF0aW9uIpwBChhSZWxhdGlvbnNoaXBUdXBsZUFkZHJlc3MSNgoIcmVzb3VyY2UYASABKAsyJC5ub21vcy5rZXJuZWwudjEuQXV0aG9yaXphdGlvbk9iamVjdBIQCghyZWxhdGlvbhgCIAEoCRI2CgdzdWJqZWN0GAMgASgLMiUubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25TdWJqZWN0IoEBChhBdXRob3JpemF0aW9uQ29uc2lzdGVuY3kSIwoZY3VycmVudF92ZXJpZmllZF9mcm9udGllchgBIAEoCEgAEhkKD2F0X2xlYXN0X2NvbW1pdBgCIAEoCUgAEhYKDGV4YWN0X2NvbW1pdBgDIAEoCUgAQg0KC3JlcXVpcmVtZW50ImYKHUF1dGhvcml6YXRpb25Db25kaXRpb25Db250ZXh0EhQKDGNvbmRpdGlvbl9pZBgBIAEoCRIvCglhcmd1bWVudHMYAiABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3Qi9wIKGUF1dGhvcml6YXRpb25DaGVja1JlcXVlc3QSNgoIcmVzb3VyY2UYASABKAsyJC5ub21vcy5rZXJuZWwudjEuQXV0aG9yaXphdGlvbk9iamVjdBISCgpwZXJtaXNzaW9uGAIgASgJEjYKB3N1YmplY3QYAyABKAsyJS5ub21vcy5rZXJuZWwudjEuQXV0aG9yaXphdGlvblN1YmplY3QSPgoLY29uc2lzdGVuY3kYBCABKAsyKS5ub21vcy5rZXJuZWwudjEuQXV0aG9yaXphdGlvbkNvbnNpc3RlbmN5Ej8KB2NvbnRleHQYBSADKAsyLi5ub21vcy5rZXJuZWwudjEuQXV0aG9yaXphdGlvbkNvbmRpdGlvbkNvbnRleHQSIAoTZXhwZWN0ZWRfbW9kZWxfaGFzaBgGIAEoCUgAiAEBEhsKE2luY2x1ZGVfZXhwbGFuYXRpb24YByABKAhCFgoUX2V4cGVjdGVkX21vZGVsX2hhc2gi7QIKGkF1dGhvcml6YXRpb25FeHBhbmRSZXF1ZXN0EjYKCHJlc291cmNlGAEgASgLMiQubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25PYmplY3QSEgoKcGVybWlzc2lvbhgCIAEoCRI+Cgtjb25zaXN0ZW5jeRgDIAEoCzIpLm5vbW9zLmtlcm5lbC52MS5BdXRob3JpemF0aW9uQ29uc2lzdGVuY3kSPwoHY29udGV4dBgEIAMoCzIuLm5vbW9zLmtlcm5lbC52MS5BdXRob3JpemF0aW9uQ29uZGl0aW9uQ29udGV4dBIgChNleHBlY3RlZF9tb2RlbF9oYXNoGAUgASgJSACIAQESDQoFbGltaXQYBiABKA0SEgoFYWZ0ZXIYByABKAlIAYgBARIbChNpbmNsdWRlX2V4cGxhbmF0aW9uGAggASgIQhYKFF9leHBlY3RlZF9tb2RlbF9oYXNoQggKBl9hZnRlciK9AQoZUmVsYXRpb25zaGlwVHVwbGVFdmlkZW5jZRI4CgV0dXBsZRgBIAEoCzIpLm5vbW9zLmtlcm5lbC52MS5SZWxhdGlvbnNoaXBUdXBsZUFkZHJlc3MSEAoIdHVwbGVfaWQYAiABKAkSGgoSYXNzZXJ0aW9uX2V2ZW50X2lkGAMgASgJEiAKE3Jldm9jYXRpb25fZXZlbnRfaWQYBCABKAlIAIgBAUIWChRfcmV2b2NhdGlvbl9ldmVudF9pZCLhAwoYQXV0aG9yaXphdGlvbkV4cGxhbmF0aW9uEkYKCW9wZXJhdGlvbhgBIAEoDjIzLm5vbW9zLmtlcm5lbC52MS5BdXRob3JpemF0aW9uRXhwbGFuYXRpb24uT3BlcmF0aW9uEhAKCHJlbGF0aW9uGAIgASgJEg4KBnJlc3VsdBgDIAEoCBI8CghldmlkZW5jZRgEIAMoCzIqLm5vbW9zLmtlcm5lbC52MS5SZWxhdGlvbnNoaXBUdXBsZUV2aWRlbmNlEjsKCGNoaWxkcmVuGAUgAygLMikubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25FeHBsYW5hdGlvbiLfAQoJT3BlcmF0aW9uEhkKFU9QRVJBVElPTl9VTlNQRUNJRklFRBAAEhQKEE9QRVJBVElPTl9ESVJFQ1QQARIeChpPUEVSQVRJT05fQ09NUFVURURfVVNFUlNFVBACEh4KGk9QRVJBVElPTl9UVVBMRV9UT19VU0VSU0VUEAMSEwoPT1BFUkFUSU9OX1VOSU9OEAQSGgoWT1BFUkFUSU9OX0lOVEVSU0VDVElPThAFEhcKE09QRVJBVElPTl9FWENMVVNJT04QBhIXChNPUEVSQVRJT05fQ09ORElUSU9OEAcidwoaQXV0aG9yaXphdGlvbkRlY2lzaW9uQmFzaXMSIAoYYXV0aG9yaXphdGlvbl9tb2RlbF9oYXNoGAEgASgJEiEKGXJlbGF0aW9uc2hpcF9zdGF0ZV9jb21taXQYAiABKAkSFAoMY29udGV4dF9oYXNoGAMgASgMIr4BChpBdXRob3JpemF0aW9uQ2hlY2tSZXNwb25zZRIPCgdhbGxvd2VkGAEgASgIEjoKBWJhc2lzGAIgASgLMisubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25EZWNpc2lvbkJhc2lzEkMKC2V4cGxhbmF0aW9uGAMgASgLMikubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25FeHBsYW5hdGlvbkgAiAEBQg4KDF9leHBsYW5hdGlvbiKDAgobQXV0aG9yaXphdGlvbkV4cGFuZFJlc3BvbnNlEjcKCHN1YmplY3RzGAEgAygLMiUubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25TdWJqZWN0EjoKBWJhc2lzGAIgASgLMisubm9tb3Mua2VybmVsLnYxLkF1dGhvcml6YXRpb25EZWNpc2lvbkJhc2lzEhEKBG5leHQYAyABKAlIAIgBARJDCgtleHBsYW5hdGlvbhgEIAEoCzIpLm5vbW9zLmtlcm5lbC52MS5BdXRob3JpemF0aW9uRXhwbGFuYXRpb25IAYgBAUIHCgVfbmV4dEIOCgxfZXhwbGFuYXRpb24iQQoNT3V0Ym94UmVxdWVzdBIwCgZ0YXJnZXQYASABKAsyIC5ub21vcy5rZXJuZWwudjEuV29ya3NwYWNlVGFyZ2V0ImMKC1N5bmNSZXF1ZXN0EjAKBnRhcmdldBgBIAEoCzIgLm5vbW9zLmtlcm5lbC52MS5Xb3Jrc3BhY2VUYXJnZXQSEQoJZnJvbV9iYXNlGAIgASgJEg8KB3RvX2hlYWQYAyABKAkiUwoLVGVzdFJlcXVlc3QSNwoIc2V0X3Jvb3QYASABKAsyIy5ub21vcy5rZXJuZWwudjEuU2V0VGVzdFJvb3RSZXF1ZXN0SABCCwoJb3BlcmF0aW9uIigKElNldFRlc3RSb290UmVxdWVzdBISCgpwdWJsaWNfa2V5GAEgASgMIj0KDFRlc3RSZXNwb25zZRItCgZyZXN1bHQYASABKAsyHS5ub21vcy5rZXJuZWwudjEuQWNrbm93bGVkZ2VkIoMJCg5DdXN0b2R5UmVxdWVzdBI3CgpwYWNrX2RlbHRhGAogASgLMiEubm9tb3Mua2VybmVsLnYxLlBhY2tEZWx0YVJlcXVlc3RIABI3CgphcHBseV9wYWNrGAsgASgLMiEubm9tb3Mua2VybmVsLnYxLkFwcGx5UGFja1JlcXVlc3RIABI3CgpyZXBvX3N0YXRzGAwgASgLMiEubm9tb3Mua2VybmVsLnYxLlJlcG9TdGF0c1JlcXVlc3RIABI9Cg1pbnRlbnRzX2Fib3ZlGA0gASgLMiQubm9tb3Mua2VybmVsLnYxLkludGVudHNBYm92ZVJlcXVlc3RIABI/Cg5pbnNwZWN0X2NoYW5nZRgOIAEoCzIlLm5vbW9zLmtlcm5lbC52MS5JbnNwZWN0Q2hhbmdlUmVxdWVzdEgAEkEKD2VuY29kZV9kb2N1bWVudBgPIAEoCzImLm5vbW9zLmtlcm5lbC52MS5FbmNvZGVEb2N1bWVudFJlcXVlc3RIABJDChBpbnNwZWN0X2RvY3VtZW50GBAgASgLMicubm9tb3Mua2VybmVsLnYxLkluc3BlY3REb2N1bWVudFJlcXVlc3RIABI1CglyZWFkX2Jsb2IYESABKAsyIC5ub21vcy5rZXJuZWwudjEuUmVhZEJsb2JSZXF1ZXN0SAASOQoLcmVzb2x2ZV9yZWYYEiABKAsyIi5ub21vcy5rZXJuZWwudjEuUmVzb2x2ZVJlZlJlcXVlc3RIABI1CglsaXN0X3JlZnMYEyABKAsyIC5ub21vcy5rZXJuZWwudjEuTGlzdFJlZnNSZXF1ZXN0SAASNQoJd3JpdGVfcmVmGBQgASgLMiAubm9tb3Mua2VybmVsLnYxLldyaXRlUmVmUmVxdWVzdEgAEjcKCmRlbGV0ZV9yZWYYFSABKAsyIS5ub21vcy5rZXJuZWwudjEuRGVsZXRlUmVmUmVxdWVzdEgAEkQKEXdyaXRlX21ldGFfY29tbWl0GBYgASgLMicubm9tb3Mua2VybmVsLnYxLldyaXRlTWV0YUNvbW1pdFJlcXVlc3RIABJCChBsYXdfY2xvc3VyZV9pbmZvGBcgASgLMiYubm9tb3Mua2VybmVsLnYxLkxhd0Nsb3N1cmVJbmZvUmVxdWVzdEgAEkUKEWNoZWNrcG9pbnRfZXhwb3J0GBggASgLMigubm9tb3Mua2VybmVsLnYxLkNoZWNrcG9pbnRFeHBvcnRSZXF1ZXN0SAASRQoRY2hlY2twb2ludF9pbXBvcnQYGSABKAsyKC5ub21vcy5rZXJuZWwudjEuQ2hlY2twb2ludEltcG9ydFJlcXVlc3RIABJDChBjYXBhY2l0eV9yZXNlcnZlGBogASgLMicubm9tb3Mua2VybmVsLnYxLkNhcGFjaXR5UmVzZXJ2ZVJlcXVlc3RIABI7CgxyZXN0b3JlX21haW4YGyABKAsyIy5ub21vcy5rZXJuZWwudjEuUmVzdG9yZU1haW5SZXF1ZXN0SABCCwoJb3BlcmF0aW9uImgKEFBhY2tEZWx0YVJlcXVlc3QSDAoEcmVwbxgBIAEoCRIRCgRoZWFkGAIgASgJSACIAQESEQoEYmFzZRgDIAEoCUgBiAEBEg4KBmJyYW5jaBgEIAEoCUIHCgVfaGVhZEIHCgVfYmFzZSJyChBBcHBseVBhY2tSZXF1ZXN0EgwKBHJlcG8YASABKAkSDgoEcGFjaxgCIAEoDEgAEhoKEHN0YWdlZF9wYWNrX2ZpbGUYBCABKAlIABIRCgRoZWFkGAMgASgJSAGIAQFCCAoGc291cmNlQgcKBV9oZWFkIiAKEFJlcG9TdGF0c1JlcXVlc3QSDAoEcmVwbxgBIAEoCSKsAQoTSW50ZW50c0Fib3ZlUmVxdWVzdBIMCgRyZXBvGAEgASgJEhEKBGhlYWQYAiABKAlIAIgBARIRCgRiYXNlGAMgASgJSAGIAQESDgoGYnJhbmNoGAQgASgJEg0KBWxpbWl0GAUgASgEEhgKEGNvbXBsZXRlX2xvZ2ljYWwYBiABKAgSFgoOY29tcGFjdF9zdG9yZWQYByABKAhCBwoFX2hlYWRCBwoFX2Jhc2UiKwoUSW5zcGVjdENoYW5nZVJlcXVlc3QSEwoLY2hhbmdlX3VzZGEYASABKAwiRgoVRW5jb2RlRG9jdW1lbnRSZXF1ZXN0Ei0KCGRvY3VtZW50GAEgASgLMhsubm9tb3Mua2VybmVsLnYxLk5vbW9zVmFsdWUiLwoWSW5zcGVjdERvY3VtZW50UmVxdWVzdBIVCg1kb2N1bWVudF91c2RhGAEgASgMIjoKD1JlYWRCbG9iUmVxdWVzdBIMCgRyZXBvGAEgASgJEgsKA29pZBgCIAEoCRIMCgRwYXRoGAMgASgJIjQKEVJlc29sdmVSZWZSZXF1ZXN0EgwKBHJlcG8YASABKAkSEQoJcmVmZXJlbmNlGAIgASgJIi8KD0xpc3RSZWZzUmVxdWVzdBIMCgRyZXBvGAEgASgJEg4KBnByZWZpeBgCIAEoCSJCCg9Xcml0ZVJlZlJlcXVlc3QSDAoEcmVwbxgBIAEoCRIRCglyZWZlcmVuY2UYAiABKAkSDgoGdGFyZ2V0GAMgASgJIjMKEERlbGV0ZVJlZlJlcXVlc3QSDAoEcmVwbxgBIAEoCRIRCglyZWZlcmVuY2UYAiABKAkiKQoITWV0YUZpbGUSDAoEcGF0aBgBIAEoCRIPCgdjb250ZW50GAIgASgMIq4BChZXcml0ZU1ldGFDb21taXRSZXF1ZXN0EgwKBHJlcG8YASABKAkSDwoHcGFyZW50cxgCIAMoCRIoCgVmaWxlcxgDIAMoCzIZLm5vbW9zLmtlcm5lbC52MS5NZXRhRmlsZRIPCgdtZXNzYWdlGAQgASgJEhQKDHRpbWVfc2Vjb25kcxgFIAEoEhIWCglyZWZlcmVuY2UYBiABKAlIAIgBAUIMCgpfcmVmZXJlbmNlIi0KFUxhd0Nsb3N1cmVJbmZvUmVxdWVzdBIUCgxjbG9zdXJlX2ZpbGUYASABKAkihwEKF0NoZWNrcG9pbnRFeHBvcnRSZXF1ZXN0EjAKBnRhcmdldBgBIAEoCzIgLm5vbW9zLmtlcm5lbC52MS5Xb3Jrc3BhY2VUYXJnZXQSIQoUc3RhZ2VkX2Zyb250aWVyX2ZpbGUYAiABKAlIAIgBAUIXChVfc3RhZ2VkX2Zyb250aWVyX2ZpbGUi6QEKF0NoZWNrcG9pbnRJbXBvcnRSZXF1ZXN0EjAKBnRhcmdldBgBIAEoCzIgLm5vbW9zLmtlcm5lbC52MS5Xb3Jrc3BhY2VUYXJnZXQSEgoIZnJvbnRpZXIYAiABKAxIABIeChRzdGFnZWRfZnJvbnRpZXJfZmlsZRgGIAEoCUgAEhMKBmN1cnNvchgDIAEoCUgBiAEBEhcKCnN0YXRlX3Jvb3QYBCABKAlIAogBARINCgVzcGFucxgFIAEoCEIRCg9mcm9udGllcl9zb3VyY2VCCQoHX2N1cnNvckINCgtfc3RhdGVfcm9vdCIxChZDYXBhY2l0eVJlc2VydmVSZXF1ZXN0EhcKD2FnZ3JlZ2F0ZV9jb3VudBgBIAEoBCJUChJSZXN0b3JlTWFpblJlcXVlc3QSMAoGdGFyZ2V0GAEgASgLMiAubm9tb3Mua2VybmVsLnYxLldvcmtzcGFjZVRhcmdldBIMCgRoZWFkGAIgASgJIo0JCg9DdXN0b2R5UmVzcG9uc2USOAoKcGFja19kZWx0YRgKIAEoCzIiLm5vbW9zLmtlcm5lbC52MS5QYWNrRGVsdGFSZXNwb25zZUgAEjgKCmFwcGx5X3BhY2sYCyABKAsyIi5ub21vcy5rZXJuZWwudjEuQXBwbHlQYWNrUmVzcG9uc2VIABI4CgpyZXBvX3N0YXRzGAwgASgLMiIubm9tb3Mua2VybmVsLnYxLlJlcG9TdGF0c1Jlc3BvbnNlSAASPgoNaW50ZW50c19hYm92ZRgNIAEoCzIlLm5vbW9zLmtlcm5lbC52MS5JbnRlbnRzQWJvdmVSZXNwb25zZUgAEkAKDmluc3BlY3RfY2hhbmdlGA4gASgLMiYubm9tb3Mua2VybmVsLnYxLkluc3BlY3RDaGFuZ2VSZXNwb25zZUgAEkIKD2VuY29kZV9kb2N1bWVudBgPIAEoCzInLm5vbW9zLmtlcm5lbC52MS5FbmNvZGVEb2N1bWVudFJlc3BvbnNlSAASRAoQaW5zcGVjdF9kb2N1bWVudBgQIAEoCzIoLm5vbW9zLmtlcm5lbC52MS5JbnNwZWN0RG9jdW1lbnRSZXNwb25zZUgAEjYKCXJlYWRfYmxvYhgRIAEoCzIhLm5vbW9zLmtlcm5lbC52MS5SZWFkQmxvYlJlc3BvbnNlSAASOgoLcmVzb2x2ZV9yZWYYEiABKAsyIy5ub21vcy5rZXJuZWwudjEuUmVzb2x2ZVJlZlJlc3BvbnNlSAASNgoJbGlzdF9yZWZzGBMgASgLMiEubm9tb3Mua2VybmVsLnYxLkxpc3RSZWZzUmVzcG9uc2VIABIyCgl3cml0ZV9yZWYYFCABKAsyHS5ub21vcy5rZXJuZWwudjEuQWNrbm93bGVkZ2VkSAASMwoKZGVsZXRlX3JlZhgVIAEoCzIdLm5vbW9zLmtlcm5lbC52MS5BY2tub3dsZWRnZWRIABJFChF3cml0ZV9tZXRhX2NvbW1pdBgWIAEoCzIoLm5vbW9zLmtlcm5lbC52MS5Xcml0ZU1ldGFDb21taXRSZXNwb25zZUgAEkMKEGxhd19jbG9zdXJlX2luZm8YFyABKAsyJy5ub21vcy5rZXJuZWwudjEuTGF3Q2xvc3VyZUluZm9SZXNwb25zZUgAEkYKEWNoZWNrcG9pbnRfZXhwb3J0GBggASgLMikubm9tb3Mua2VybmVsLnYxLkNoZWNrcG9pbnRFeHBvcnRSZXNwb25zZUgAEkYKEWNoZWNrcG9pbnRfaW1wb3J0GBkgASgLMikubm9tb3Mua2VybmVsLnYxLkNoZWNrcG9pbnRJbXBvcnRSZXNwb25zZUgAEkQKEGNhcGFjaXR5X3Jlc2VydmUYGiABKAsyKC5ub21vcy5rZXJuZWwudjEuQ2FwYWNpdHlSZXNlcnZlUmVzcG9uc2VIABI8CgxyZXN0b3JlX21haW4YGyABKAsyJC5ub21vcy5rZXJuZWwudjEuUmVzdG9yZU1haW5SZXNwb25zZUgAQgsKCW9wZXJhdGlvbiIhChFQYWNrRGVsdGFSZXNwb25zZRIMCgRwYWNrGAEgASgMIjwKEUFwcGx5UGFja1Jlc3BvbnNlEhQKDG9iamVjdF9jb3VudBgBIAEoBBIRCglwYWNrX2hhc2gYAiABKAkipwEKEVJlcG9TdGF0c1Jlc3BvbnNlEhMKC3RvdGFsX2J5dGVzGAEgASgEEhQKDG9iamVjdF9ieXRlcxgCIAEoBBIVCg1sb29zZV9vYmplY3RzGAMgASgEEhMKC2xvb3NlX2J5dGVzGAQgASgEEhIKCnBhY2tfZmlsZXMYBSABKAQSEgoKcGFja19ieXRlcxgGIAEoBBITCgtpbmRleF9ieXRlcxgHIAEoBCKWAQoMSW50ZW50UmVjb3JkEgsKA29pZBgBIAEoCRIRCglpbnRlbnRfaWQYAiABKAkSDgoGZG9tYWluGAMgASgJEhEKCWRpcmVjdGl2ZRgEIAEoCRITCgtjaGFuZ2VfdXNkYRgFIAEoDBIuCghzZW1hbnRpYxgGIAEoCzIcLm5vbW9zLmtlcm5lbC52MS5Ob21vc1N0cnVjdCJGChRJbnRlbnRzQWJvdmVSZXNwb25zZRIuCgdpbnRlbnRzGAEgAygLMh0ubm9tb3Mua2VybmVsLnYxLkludGVudFJlY29yZCJHChVJbnNwZWN0Q2hhbmdlUmVzcG9uc2USLgoIc2VtYW50aWMYASABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3QiLwoWRW5jb2RlRG9jdW1lbnRSZXNwb25zZRIVCg1kb2N1bWVudF91c2RhGAEgASgMIkgKF0luc3BlY3REb2N1bWVudFJlc3BvbnNlEi0KCGRvY3VtZW50GAEgASgLMhsubm9tb3Mua2VybmVsLnYxLk5vbW9zVmFsdWUiLwoQUmVhZEJsb2JSZXNwb25zZRINCgVmb3VuZBgBIAEoCBIMCgRibG9iGAIgASgMIi4KElJlc29sdmVSZWZSZXNwb25zZRIQCgNvaWQYASABKAlIAIgBAUIGCgRfb2lkIisKCVJlZlJlY29yZBIRCglyZWZlcmVuY2UYASABKAkSCwoDb2lkGAIgASgJIjwKEExpc3RSZWZzUmVzcG9uc2USKAoEcmVmcxgBIAMoCzIaLm5vbW9zLmtlcm5lbC52MS5SZWZSZWNvcmQiDgoMQWNrbm93bGVkZ2VkIiYKF1dyaXRlTWV0YUNvbW1pdFJlc3BvbnNlEgsKA29pZBgBIAEoCSKDAQoWTGF3Q2xvc3VyZUluZm9SZXNwb25zZRIQCghpZGVudGl0eRgBIAEoCRIZChFyb290X2xvZ2ljYWxfcGF0aBgCIAEoCRITCgthc3NldF9jb3VudBgDIAEoBBISCgpwcmltX2NvdW50GAQgASgEEhMKC2RvbWFpbl9rZXlzGAUgAygJIu8CChhDaGVja3BvaW50RXhwb3J0UmVzcG9uc2USDQoFZW1wdHkYASABKAgSEwoGY3Vyc29yGAIgASgJSACIAQESEAoIZnJvbnRpZXIYAyABKAwSFwoKc3RhdGVfcm9vdBgEIAEoCUgBiAEBEhIKCnN0YXRlX3RyZWUYBSABKAgSDgoGcGlubmVkGAYgASgIEhsKE3JlYWRfaW5kZXhfc25hcHNob3QYByABKAgSIwobcmVhZF9pbmRleF9zbmFwc2hvdF9wZW5kaW5nGAggASgIEiQKF3JlYWRfaW5kZXhfc3FsaXRlX2J5dGVzGAkgASgESAKIAQESJQoYcmVhZF9pbmRleF9jdXN0b2R5X2J5dGVzGAogASgESAOIAQFCCQoHX2N1cnNvckINCgtfc3RhdGVfcm9vdEIaChhfcmVhZF9pbmRleF9zcWxpdGVfYnl0ZXNCGwoZX3JlYWRfaW5kZXhfY3VzdG9keV9ieXRlcyKeAgoYQ2hlY2twb2ludEltcG9ydFJlc3BvbnNlEhAKCHJlc3RvcmVkGAEgASgIEhMKBnJlYXNvbhgCIAEoCUgAiAEBEhcKD2Zyb250aWVyX3NlZWRlZBgDIAEoCBIlCh1mcm9udGllcl92ZXJpZmljYXRpb25fcGVuZGluZxgEIAEoCBIXCg9hZ2dyZWdhdGVfY291bnQYBSABKAQSKwoFc3BhbnMYBiABKAsyHC5ub21vcy5rZXJuZWwudjEuTm9tb3NTdHJ1Y3QSEwoGY3Vyc29yGAcgASgJSAGIAQESEQoJcmVhZF9vbmx5GAggASgIEhcKD2xhenlfcmVhZF9pbmRleBgJIAEoCEIJCgdfcmVhc29uQgkKB19jdXJzb3IiSgoXQ2FwYWNpdHlSZXNlcnZlUmVzcG9uc2USFwoPYWdncmVnYXRlX2NvdW50GAEgASgEEhYKDnJlc2VydmVkX2J5dGVzGAIgASgEIkMKE1Jlc3RvcmVNYWluUmVzcG9uc2USDAoEaGVhZBgBIAEoCRIQCgh2ZXJpZmllZBgCIAEoCBIMCgR3YWxrGAMgASgJIpsCCgpOb21vc1ZhbHVlEiUKBG51bGwYASABKAsyFS5ub21vcy5rZXJuZWwudjEuTnVsbEgAEhEKB2Jvb2xlYW4YAiABKAhIABIYCg5zaWduZWRfaW50ZWdlchgDIAEoEkgAEhoKEHVuc2lnbmVkX2ludGVnZXIYBCABKARIABIYCg5mbG9hdGluZ19wb2ludBgFIAEoAUgAEg4KBHRleHQYBiABKAlIABIPCgVieXRlcxgHIAEoDEgAEioKBGxpc3QYCCABKAsyGi5ub21vcy5rZXJuZWwudjEuTm9tb3NMaXN0SAASLgoGb2JqZWN0GAkgASgLMhwubm9tb3Mua2VybmVsLnYxLk5vbW9zU3RydWN0SABCBgoEa2luZCIGCgROdWxsIjgKCU5vbW9zTGlzdBIrCgZ2YWx1ZXMYASADKAsyGy5ub21vcy5rZXJuZWwudjEuTm9tb3NWYWx1ZSKTAQoLTm9tb3NTdHJ1Y3QSOAoGZmllbGRzGAEgAygLMigubm9tb3Mua2VybmVsLnYxLk5vbW9zU3RydWN0LkZpZWxkc0VudHJ5GkoKC0ZpZWxkc0VudHJ5EgsKA2tleRgBIAEoCRIqCgV2YWx1ZRgCIAEoCzIbLm5vbW9zLmtlcm5lbC52MS5Ob21vc1ZhbHVlOgI4ASrpEgoRS2VybmVsUmVmdXNhbENvZGUSIwofS0VSTkVMX1JFRlVTQUxfQ09ERV9VTlNQRUNJRklFRBAAEiUKIUtFUk5FTF9SRUZVU0FMX0NPREVfQkFEX1NJR05BVFVSRRABEiQKIEtFUk5FTF9SRUZVU0FMX0NPREVfVU5BVVRIT1JJWkVEEAISJwojS0VSTkVMX1JFRlVTQUxfQ09ERV9QT0xJQ1lfRElTQUJMRUQQAxIqCiZLRVJORUxfUkVGVVNBTF9DT0RFX1VOQ0VSVElGSUVEX1BPTElDWRAEEiMKH0tFUk5FTF9SRUZVU0FMX0NPREVfUkVGRVJFTlRJQUwQBRIvCitLRVJORUxfUkVGVVNBTF9DT0RFX1BPSU5UX1NUQVRFX1VOQVZBSUxBQkxFEAYSJAogS0VSTkVMX1JFRlVTQUxfQ09ERV9DQVBfRVhDRUVERUQQBxItCilLRVJORUxfUkVGVVNBTF9DT0RFX0NBUF9DT1VOVF9VTkFWQUlMQUJMRRAIEikKJUtFUk5FTF9SRUZVU0FMX0NPREVfRVZJREVOQ0VfVU5CQUNLRUQQCRImCiJLRVJORUxfUkVGVVNBTF9DT0RFX09SUEhBTl9SRUNFSVBUEAoSNgoyS0VSTkVMX1JFRlVTQUxfQ09ERV9SRUNFSVBUX09OX1RFUk1JTkFMX09CTElHQVRJT04QCxIiCh5LRVJORUxfUkVGVVNBTF9DT0RFX05PVF9NSU5URUQQDBIoCiRLRVJORUxfUkVGVVNBTF9DT0RFX0RPTUFJTl9MSUZFQ1lDTEUQDRIpCiVLRVJORUxfUkVGVVNBTF9DT0RFX1RZUEVfVEFHX01JU01BVENIEA4SLAooS0VSTkVMX1JFRlVTQUxfQ09ERV9SRVRJUkVEX1JFQURfU1VSRkFDRRAPEjAKLEtFUk5FTF9SRUZVU0FMX0NPREVfQ1JPU1NfV09SS1NQQUNFX0RFQ0xJTkVEEBASKwonS0VSTkVMX1JFRlVTQUxfQ09ERV9BR0dSRUdBVEVfSU5WQVJJQU5UEBESKwonS0VSTkVMX1JFRlVTQUxfQ09ERV9XT1JLU1BBQ0VfSU5WQVJJQU5UEBISLgoqS0VSTkVMX1JFRlVTQUxfQ09ERV9DQVBUVVJFRF9SRUFEX0NPTkZMSUNUEBMSMgouS0VSTkVMX1JFRlVTQUxfQ09ERV9DT05GTElDVF9TTkFQU0hPVF9SRVFVSVJFRBAUEjQKMEtFUk5FTF9SRUZVU0FMX0NPREVfQ09ORkxJQ1RfU05BUFNIT1RfVU5ERUNMQVJFRBAVEjEKLUtFUk5FTF9SRUZVU0FMX0NPREVfQ09ORkxJQ1RfU05BUFNIT1RfSU5WQUxJRBAWEi8KK0tFUk5FTF9SRUZVU0FMX0NPREVfQ09ORkxJQ1RfU05BUFNIT1RfU1RBTEUQFxIwCixLRVJORUxfUkVGVVNBTF9DT0RFX0NBUFRVUkVEX1JFQURfVU5ERUNMQVJFRBAYEi0KKUtFUk5FTF9SRUZVU0FMX0NPREVfQ0FQVFVSRURfUkVBRF9QUklWQVRFEBkSMAosS0VSTkVMX1JFRlVTQUxfQ09ERV9BVFRFU1RFRF9SRUFEX1VOREVDTEFSRUQQGhIzCi9LRVJORUxfUkVGVVNBTF9DT0RFX0FUVEVTVEVEX1JFQURfVU5UUlVTVEVEX0tFWRAbEjYKMktFUk5FTF9SRUZVU0FMX0NPREVfQVRURVNURURfUkVBRF9VTlRSVVNURURfU09VUkNFEBwSLAooS0VSTkVMX1JFRlVTQUxfQ09ERV9BVFRFU1RFRF9SRUFEX0ZPUkdFRBAdEisKJ0tFUk5FTF9SRUZVU0FMX0NPREVfQVRURVNURURfUkVBRF9TVEFMRRAeEi4KKktFUk5FTF9SRUZVU0FMX0NPREVfQVRURVNURURfUkVBRF9PVkVSU0laRRAfEjcKM0tFUk5FTF9SRUZVU0FMX0NPREVfQVRURVNURURfUkVBRF9ESVNIT05PUkVEX1NPVVJDRRAgEjUKMUtFUk5FTF9SRUZVU0FMX0NPREVfRVFVSVZPQ0FUSU9OX0VWSURFTkNFX0lOVkFMSUQQIRIzCi9LRVJORUxfUkVGVVNBTF9DT0RFX0FUVEVTVEFUSU9OX1JFQ0VJUFRfSU5WQUxJRBAiEisKJ0tFUk5FTF9SRUZVU0FMX0NPREVfS0VZX1JPU1RFUl9NSVNNQVRDSBAjEi8KK0tFUk5FTF9SRUZVU0FMX0NPREVfS0VZX0VQT0NIX05PVF9NT05PVE9OSUMQJBIpCiVLRVJORUxfUkVGVVNBTF9DT0RFX1dSSVRFX0VQT0NIX1NUQUxFECUSLQopS0VSTkVMX1JFRlVTQUxfQ09ERV9FTlZFTE9QRV9TSURfTUlTTUFUQ0gQJhIyCi5LRVJORUxfUkVGVVNBTF9DT0RFX1JFVk9LRURfTUVNQkVSX1JFU1VSUkVDVEVEECcSKAokS0VSTkVMX1JFRlVTQUxfQ09ERV9GT1JHRURfUFJJTkNJUEFMECgSKAokS0VSTkVMX1JFRlVTQUxfQ09ERV9PV05FRF9LRVlfQU5DSE9SECkSJgoiS0VSTkVMX1JFRlVTQUxfQ09ERV9PV05FRF9SRUNPVkVSWRAqEiwKKEtFUk5FTF9SRUZVU0FMX0NPREVfU1VSRkFDRURfQkFTSVNfQUhFQUQQKxIyCi5LRVJORUxfUkVGVVNBTF9DT0RFX1NJR05FUl9FUE9DSF9PVVRfT0ZfV0lORE9XECwSJgoiS0VSTkVMX1JFRlVTQUxfQ09ERV9FVk9MVkVfUkVGVVNFRBAtEisKJ0tFUk5FTF9SRUZVU0FMX0NPREVfQVRURVNUQVRJT05fSU5WQUxJRBAuEi0KKUtFUk5FTF9SRUZVU0FMX0NPREVfUEFSRU5UX0RJRF9OT1RfQVRURVNUEC8SKQolS0VSTkVMX1JFRlVTQUxfQ09ERV9DRVJUX0NIQUlOX0JST0tFThAwEioKJktFUk5FTF9SRUZVU0FMX0NPREVfTk9UX1JPT1RFRF9BVF9ST09UEDESKgomS0VSTkVMX1JFRlVTQUxfQ09ERV9ERUxFR0FUSU9OX0lOVkFMSUQQMhIlCiFLRVJORUxfUkVGVVNBTF9DT0RFX1BMQU5fUkVKRUNURUQQMyqFDAoOUXVlcnlPcGVyYXRpb24SHwobUVVFUllfT1BFUkFUSU9OX1VOU1BFQ0lGSUVEEAASHAoYUVVFUllfT1BFUkFUSU9OX0VYVFJFTVVNEAESJQohUVVFUllfT1BFUkFUSU9OX1BFTkRJTkdfQ09ORkxJQ1RTEAISLAooUVVFUllfT1BFUkFUSU9OX1BFTkRJTkdfQ09ORkxJQ1RfU1VNTUFSWRADEiAKHFFVRVJZX09QRVJBVElPTl9SRUFEX1BPU1RVUkUQBBIfChtRVUVSWV9PUEVSQVRJT05fQ1VSUkVOVF9MQVcQBRIjCh9RVUVSWV9PUEVSQVRJT05fSU5URVJGQUNFX09GRkVSEAYSJwojUVVFUllfT1BFUkFUSU9OX1JFTEFUSU9OX0dBVEVfT0ZGRVIQBxIdChlRVUVSWV9PUEVSQVRJT05fU0NFTkVfTEFXEAgSIQodUVVFUllfT1BFUkFUSU9OX0lOU1RBTExFRF9MQVcQCRIcChhRVUVSWV9PUEVSQVRJT05fREVTQ1JJQkUQChIgChxRVUVSWV9PUEVSQVRJT05fS0VSTkVMX1NUQU1QEAsSIwofUVVFUllfT1BFUkFUSU9OX0RFVkVMT1BFUl9TUEFOUxAMEikKJVFVRVJZX09QRVJBVElPTl9ERUNMQVJFRF9DQVBBQklMSVRJRVMQDRIdChlRVUVSWV9PUEVSQVRJT05fUkVBRElORVNTEA4SJAogUVVFUllfT1BFUkFUSU9OX1BST0pFQ1RJT05fU1RBVFMQDxIlCiFRVUVSWV9PUEVSQVRJT05fTUVNT1JZX0RST1BfUFJPQkUQEBIYChRRVUVSWV9PUEVSQVRJT05fV0FSTRAREhsKF1FVRVJZX09QRVJBVElPTl9SRUZSRVNIEBISIAocUVVFUllfT1BFUkFUSU9OX1ZFUklGWV9DSEFJThATEiUKIVFVRVJZX09QRVJBVElPTl9ISVNUT1JZX1BSRUZMSUdIVBAUEhkKFVFVRVJZX09QRVJBVElPTl9ST1VURRAVEhgKFFFVRVJZX09QRVJBVElPTl9NSU5UEBYSIQodUVVFUllfT1BFUkFUSU9OX0NSWVBUT19LRVlHRU4QFxIlCiFRVUVSWV9PUEVSQVRJT05fQ1JZUFRPX1NFQUxfRklFTEQQGBIsCihRVUVSWV9PUEVSQVRJT05fQ1JZUFRPX0JMSU5EX0lOREVYX1RPS0VOEBkSKgomUVVFUllfT1BFUkFUSU9OX0NSWVBUT19PV05FRF9TQ09QRV9LRVkQGhIvCitRVUVSWV9PUEVSQVRJT05fQ1JZUFRPX09XTkVEX0RFVklDRV9SRVFVRVNUEBsSMQotUVVFUllfT1BFUkFUSU9OX0NSWVBUT19PV05FRF9QUkVQQVJFX0FQUFJPVkFMEBwSMQotUVVFUllfT1BFUkFUSU9OX0NSWVBUT19PV05FRF9QUkVQQVJFX1JFQ09WRVJZEB0SIwofUVVFUllfT1BFUkFUSU9OX0NSWVBUT19XUkFQX0tFWRAeEiUKIVFVRVJZX09QRVJBVElPTl9DUllQVE9fVU5XUkFQX0tFWRAfEiEKHVFVRVJZX09QRVJBVElPTl9BVVRIT1JfS0VZR0VOECASJAogUVVFUllfT1BFUkFUSU9OX0FUVEVTVEFUSU9OX1NJR04QIRIgChxRVUVSWV9PUEVSQVRJT05fUkVDRUlQVF9QQVRIECISHQoZUVVFUllfT1BFUkFUSU9OX0NFUlRfU0lHThAjEiUKIVFVRVJZX09QRVJBVElPTl9CSVJUSF9UUlVTVF9TVEFURRAkEiEKHVFVRVJZX09QRVJBVElPTl9FUkFfQ0VSVF9TSUdOECUSKAokUVVFUllfT1BFUkFUSU9OX0RFTEVHQVRJT05fQ0VSVF9TSUdOECYSKQolUVVFUllfT1BFUkFUSU9OX0NBTk9OSUNBTElaRV9GUk9OVElFUhAnEisKJ1FVRVJZX09QRVJBVElPTl9DQU5PTklDQUxJWkVfUFJPSkVDVElPThAoMlkKEk5vbW9zS2VybmVsU2VydmljZRJDCgRDYWxsEhwubm9tb3Mua2VybmVsLnYxLkNhbGxSZXF1ZXN0Gh0ubm9tb3Mua2VybmVsLnYxLkNhbGxSZXNwb25zZWIGcHJvdG8z");
|
|
486
|
+
CallRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 0);
|
|
487
|
+
CallResponseSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 1);
|
|
488
|
+
WorkspaceTargetSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 15);
|
|
489
|
+
DirectiveCallSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 17);
|
|
490
|
+
AuthoringOptionsSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 18);
|
|
491
|
+
CapturedClockSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 19);
|
|
492
|
+
OfferRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 20);
|
|
493
|
+
QueryRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 23);
|
|
494
|
+
QueryAuthoritySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 24);
|
|
495
|
+
InjectedKeySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 25);
|
|
496
|
+
RowsQuerySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 26);
|
|
497
|
+
PageQuerySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 27);
|
|
498
|
+
ByIdQuerySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 28);
|
|
499
|
+
TallyQuerySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 33);
|
|
500
|
+
SpatialQuerySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 34);
|
|
501
|
+
NamedQuerySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 35);
|
|
502
|
+
AuthorizationObjectSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 36);
|
|
503
|
+
AuthorizationSubjectSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 37);
|
|
504
|
+
AuthorizationConsistencySchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 39);
|
|
505
|
+
AuthorizationCheckRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 41);
|
|
506
|
+
AuthorizationExpandRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 42);
|
|
507
|
+
OutboxRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 48);
|
|
508
|
+
SyncRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 49);
|
|
509
|
+
TestRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 50);
|
|
510
|
+
SetTestRootRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 51);
|
|
511
|
+
CustodyRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 53);
|
|
512
|
+
PackDeltaRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 54);
|
|
513
|
+
ApplyPackRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 55);
|
|
514
|
+
RepoStatsRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 56);
|
|
515
|
+
IntentsAboveRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 57);
|
|
516
|
+
InspectChangeRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 58);
|
|
517
|
+
EncodeDocumentRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 59);
|
|
518
|
+
InspectDocumentRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 60);
|
|
519
|
+
ReadBlobRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 61);
|
|
520
|
+
ResolveRefRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 62);
|
|
521
|
+
ListRefsRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 63);
|
|
522
|
+
WriteRefRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 64);
|
|
523
|
+
DeleteRefRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 65);
|
|
524
|
+
WriteMetaCommitRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 67);
|
|
525
|
+
LawClosureInfoRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 68);
|
|
526
|
+
CheckpointExportRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 69);
|
|
527
|
+
CheckpointImportRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 70);
|
|
528
|
+
CapacityReserveRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 71);
|
|
529
|
+
RestoreMainRequestSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 72);
|
|
530
|
+
NomosValueSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 93);
|
|
531
|
+
NomosStructSchema = /* @__PURE__ */ messageDesc(file_nomos_kernel_v1_kernel, 96);
|
|
532
|
+
QueryOperationSchema = /* @__PURE__ */ enumDesc(file_nomos_kernel_v1_kernel, 1);
|
|
533
|
+
QueryOperation = /* @__PURE__ */ tsEnum(QueryOperationSchema);
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
// vendor/engine/engine.ts
|
|
538
|
+
var engine_exports = {};
|
|
539
|
+
__export(engine_exports, {
|
|
540
|
+
NOMOS_SHARD_ROWS_READ: () => NOMOS_SHARD_ROWS_READ,
|
|
541
|
+
admitAll: () => admitAll,
|
|
542
|
+
admitIntentOffers: () => admitIntentOffers,
|
|
543
|
+
applyIntentBytes: () => applyIntentBytes,
|
|
544
|
+
archiveRefusedMain: () => archiveRefusedMain,
|
|
545
|
+
attestationSign: () => attestationSign,
|
|
546
|
+
author: () => author,
|
|
547
|
+
authorEphemeral: () => authorEphemeral,
|
|
548
|
+
authorKeygen: () => authorKeygen,
|
|
549
|
+
authorOn: () => authorOn,
|
|
550
|
+
backupHead: () => backupHead,
|
|
551
|
+
backupToCustody: () => backupToCustody,
|
|
552
|
+
boot: () => boot,
|
|
553
|
+
certSign: () => certSign,
|
|
554
|
+
check: () => check,
|
|
555
|
+
checkpointStateHash: () => checkpointStateHash,
|
|
556
|
+
clearCheckpointRefs: () => clearCheckpointRefs,
|
|
557
|
+
closureInstallPayload: () => closureInstallPayload,
|
|
558
|
+
collectGlobalIntents: () => collectGlobalIntents,
|
|
559
|
+
collectHomedIntents: () => collectHomedIntents,
|
|
560
|
+
commitAndPush: () => commitAndPush,
|
|
561
|
+
count: () => count,
|
|
562
|
+
countRemoteCommits: () => countRemoteCommits,
|
|
563
|
+
countTenantRows: () => countTenantRows,
|
|
564
|
+
countTenantRowsByHome: () => countTenantRowsByHome,
|
|
565
|
+
createEngine: () => createEngine,
|
|
566
|
+
cryptoKeygen: () => cryptoKeygen,
|
|
567
|
+
cryptoOwnedDeviceRequest: () => cryptoOwnedDeviceRequest,
|
|
568
|
+
cryptoOwnedPrepareApproval: () => cryptoOwnedPrepareApproval,
|
|
569
|
+
cryptoOwnedPrepareRecovery: () => cryptoOwnedPrepareRecovery,
|
|
570
|
+
cryptoOwnedScopeKey: () => cryptoOwnedScopeKey,
|
|
571
|
+
cryptoSealField: () => cryptoSealField,
|
|
572
|
+
cryptoUnwrapKey: () => cryptoUnwrapKey,
|
|
573
|
+
cryptoWrapKey: () => cryptoWrapKey,
|
|
574
|
+
currentLaw: () => currentLaw,
|
|
575
|
+
declaredCapabilities: () => declaredCapabilities,
|
|
576
|
+
deepVerifyShard: () => deepVerifyShard,
|
|
577
|
+
delegationCertSign: () => delegationCertSign,
|
|
578
|
+
deleteRefusedRef: () => deleteRefusedRef,
|
|
579
|
+
deriveSummarySuffix: () => deriveSummarySuffix,
|
|
580
|
+
describe: () => describe,
|
|
581
|
+
directiveRoutes: () => directiveRoutes,
|
|
582
|
+
emitOutbox: () => emitOutbox,
|
|
583
|
+
eraCertSign: () => eraCertSign,
|
|
584
|
+
evalCanonicalPred: () => evalCanonicalPred,
|
|
585
|
+
evolveDryRun: () => evolveDryRun,
|
|
586
|
+
expand: () => expand,
|
|
587
|
+
exportCheckpoint: () => exportCheckpoint,
|
|
588
|
+
extremum: () => extremum,
|
|
589
|
+
flushDeferredProjections: () => flushDeferredProjections,
|
|
590
|
+
gitdirOf: () => gitdirOf,
|
|
591
|
+
globalAggregates: () => globalAggregates,
|
|
592
|
+
historyPreflight: () => historyPreflight,
|
|
593
|
+
historyRestorePreflight: () => historyRestorePreflight,
|
|
594
|
+
importCheckpoint: () => importCheckpoint,
|
|
595
|
+
importCustodyObjects: () => importCustodyObjects,
|
|
596
|
+
ingestPackAsCustody: () => ingestPackAsCustody,
|
|
597
|
+
installedLaw: () => installedLaw,
|
|
598
|
+
isWarranted: () => isWarranted,
|
|
599
|
+
kernelStamp: () => kernelStamp,
|
|
600
|
+
kgit: () => kgit,
|
|
601
|
+
lawParity: () => lawParity,
|
|
602
|
+
ledgerStats: () => ledgerStats,
|
|
603
|
+
listRefusedRefs: () => listRefusedRefs,
|
|
604
|
+
materializeRefused: () => materializeRefused,
|
|
605
|
+
memoryDropProbe: () => memoryDropProbe,
|
|
606
|
+
migrateHomes: () => migrateHomes,
|
|
607
|
+
mintId: () => mintId,
|
|
608
|
+
mountEphemeralWorkspace: () => mountEphemeralWorkspace,
|
|
609
|
+
mountWorkspace: () => mountWorkspace,
|
|
610
|
+
nomosActive: () => nomosActive,
|
|
611
|
+
offerAdmit: () => offerAdmit,
|
|
612
|
+
offerIntent: () => offerIntent,
|
|
613
|
+
outboxRefExists: () => outboxRefExists,
|
|
614
|
+
packBornChildren: () => packBornChildren,
|
|
615
|
+
packDelta: () => packDelta,
|
|
616
|
+
pendingConflictSummary: () => pendingConflictSummary,
|
|
617
|
+
pendingConflicts: () => pendingConflicts,
|
|
618
|
+
placementDirectives: () => placementDirectives,
|
|
619
|
+
projectionStats: () => projectionStats,
|
|
620
|
+
promotePreflighted: () => promotePreflighted,
|
|
621
|
+
pushCheckpoint: () => pushCheckpoint,
|
|
622
|
+
pushShape: () => pushShape,
|
|
623
|
+
pushStagedCheckpoint: () => pushStagedCheckpoint,
|
|
624
|
+
qById: () => qById,
|
|
625
|
+
query: () => query,
|
|
626
|
+
queryEphemeral: () => queryEphemeral,
|
|
627
|
+
queryPage: () => queryPage,
|
|
628
|
+
queryProfile: () => queryProfile,
|
|
629
|
+
reactorScan: () => reactorScan,
|
|
630
|
+
readCheckpointBlob: () => readCheckpointBlob,
|
|
631
|
+
readPosture: () => readPosture,
|
|
632
|
+
readShape: () => readShape,
|
|
633
|
+
readiness: () => readiness,
|
|
634
|
+
rebirthCompact: () => rebirthCompact,
|
|
635
|
+
reconcileBornPacks: () => reconcileBornPacks,
|
|
636
|
+
refreshProjection: () => refreshProjection,
|
|
637
|
+
refusedSummary: () => refusedSummary,
|
|
638
|
+
replicateIntents: () => replicateIntents,
|
|
639
|
+
repoArgOf: () => repoArgOf,
|
|
640
|
+
reserveKernelCapacity: () => reserveKernelCapacity,
|
|
641
|
+
restoreCheckpointFromCustody: () => restoreCheckpointFromCustody,
|
|
642
|
+
restorePreviousPreflighted: () => restorePreviousPreflighted,
|
|
643
|
+
sceneLaw: () => sceneLaw,
|
|
644
|
+
scopedReads: () => scopedReads,
|
|
645
|
+
sealHomes: () => sealHomes,
|
|
646
|
+
servePack: () => servePack,
|
|
647
|
+
setTestKRoot: () => setTestKRoot,
|
|
648
|
+
sha256hex: () => sha256hex,
|
|
649
|
+
snapshot: () => snapshot,
|
|
650
|
+
spatialBboxParams: () => spatialBboxParams,
|
|
651
|
+
spatialWithin: () => spatialWithin,
|
|
652
|
+
stageCheckpoint: () => stageCheckpoint,
|
|
653
|
+
stageLawClosure: () => stageLawClosure,
|
|
654
|
+
stats: () => stats,
|
|
655
|
+
sum: () => sum,
|
|
656
|
+
summaryCloseAgainstHeld: () => summaryCloseAgainstHeld,
|
|
657
|
+
syncCandidate: () => syncCandidate,
|
|
658
|
+
unmount: () => unmount,
|
|
659
|
+
verifyChain: () => verifyChain,
|
|
660
|
+
verifyChainLocal: () => verifyChainLocal,
|
|
661
|
+
warmEngine: () => warmEngine,
|
|
662
|
+
warmKernelCaches: () => warmKernelCaches,
|
|
663
|
+
workspaceGenesis: () => workspaceGenesis,
|
|
664
|
+
writeCheckpointObjects: () => writeCheckpointObjects,
|
|
665
|
+
writeOutboxRef: () => writeOutboxRef,
|
|
666
|
+
writeRefusedRef: () => writeRefusedRef,
|
|
667
|
+
wrongHomeVerdict: () => wrongHomeVerdict
|
|
668
|
+
});
|
|
669
|
+
import { WASI, File, Directory, OpenFile, ConsoleStdout, PreopenDirectory } from "@bjorn3/browser_wasi_shim";
|
|
670
|
+
import { create, fromBinary, toBinary } from "@bufbuild/protobuf";
|
|
671
|
+
function b64Bytes(bytes) {
|
|
672
|
+
let s = "";
|
|
673
|
+
for (let i = 0; i < bytes.length; i += 32768) {
|
|
674
|
+
s += String.fromCharCode(...bytes.subarray(i, i + 32768));
|
|
675
|
+
}
|
|
676
|
+
return btoa(s);
|
|
677
|
+
}
|
|
678
|
+
async function sha256hex(t) {
|
|
679
|
+
const b = await crypto.subtle.digest("SHA-256", enc3.encode(t));
|
|
680
|
+
return [...new Uint8Array(b)].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
681
|
+
}
|
|
682
|
+
function osEntropyBuffer(n) {
|
|
683
|
+
const bytes = new Uint8Array(n * 8);
|
|
684
|
+
for (let o = 0; o < bytes.length; o += 65536) crypto.getRandomValues(bytes.subarray(o, Math.min(o + 65536, bytes.length)));
|
|
685
|
+
const out2 = new Array(n), T = 2 ** 53;
|
|
686
|
+
for (let i = 0; i < n; i++) {
|
|
687
|
+
let z = 0n;
|
|
688
|
+
for (let b = 7; b >= 0; b--) z = z << 8n | BigInt(bytes[i * 8 + b]);
|
|
689
|
+
out2[i] = Number(z >> 11n) / T;
|
|
690
|
+
}
|
|
691
|
+
return out2;
|
|
692
|
+
}
|
|
693
|
+
function callProto(ex, operation, STDERR) {
|
|
694
|
+
const requestId = `adapter-${++protoRequestSequence}`;
|
|
695
|
+
const request = create(CallRequestSchema, {
|
|
696
|
+
protocolVersion: PROTO_ABI_VERSION,
|
|
697
|
+
requestId,
|
|
698
|
+
operation
|
|
699
|
+
});
|
|
700
|
+
const bytes = toBinary(CallRequestSchema, request);
|
|
701
|
+
const requestPtr = ex.git_holon_alloc(bytes.length) >>> 0;
|
|
702
|
+
try {
|
|
703
|
+
new Uint8Array(ex.memory.buffer, requestPtr, bytes.length).set(bytes);
|
|
704
|
+
let packed;
|
|
705
|
+
try {
|
|
706
|
+
packed = ex.git_holon_call_proto(requestPtr, bytes.length);
|
|
707
|
+
} catch (error) {
|
|
708
|
+
const tail = STDERR.length ? ` | stderr: ${STDERR.slice(-8).join(" / ")}` : "";
|
|
709
|
+
throw new Error(`${String(error?.stack || error)}${tail}`);
|
|
710
|
+
}
|
|
711
|
+
const { ptr, len } = unpack(packed);
|
|
712
|
+
try {
|
|
713
|
+
const responseBytes = new Uint8Array(ex.memory.buffer, ptr, len).slice();
|
|
714
|
+
const response = fromBinary(CallResponseSchema, responseBytes);
|
|
715
|
+
if (response.protocolVersion !== PROTO_ABI_VERSION) {
|
|
716
|
+
throw new Error(`kernel protobuf ABI ${response.protocolVersion}; expected ${PROTO_ABI_VERSION}`);
|
|
717
|
+
}
|
|
718
|
+
if (response.requestId !== requestId) {
|
|
719
|
+
throw new Error(`kernel protobuf response id ${response.requestId || "<empty>"}; expected ${requestId}`);
|
|
720
|
+
}
|
|
721
|
+
if (response.outcome.case === "failure") {
|
|
722
|
+
throw new Error(`${response.outcome.value.code}: ${response.outcome.value.message}`);
|
|
723
|
+
}
|
|
724
|
+
return response;
|
|
725
|
+
} finally {
|
|
726
|
+
ex.git_holon_dealloc(ptr, len);
|
|
727
|
+
}
|
|
728
|
+
} finally {
|
|
729
|
+
ex.git_holon_dealloc(requestPtr, bytes.length);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function protoValue(value) {
|
|
733
|
+
if (value === null || value === void 0) {
|
|
734
|
+
return create(NomosValueSchema, { kind: { case: "null", value: {} } });
|
|
735
|
+
}
|
|
736
|
+
if (typeof value === "boolean") {
|
|
737
|
+
return create(NomosValueSchema, { kind: { case: "boolean", value } });
|
|
738
|
+
}
|
|
739
|
+
if (typeof value === "bigint") {
|
|
740
|
+
return value < 0n ? create(NomosValueSchema, { kind: { case: "signedInteger", value } }) : create(NomosValueSchema, { kind: { case: "unsignedInteger", value } });
|
|
741
|
+
}
|
|
742
|
+
if (typeof value === "number") {
|
|
743
|
+
if (!Number.isFinite(value)) throw new Error("NomosValue numbers must be finite");
|
|
744
|
+
if (Number.isSafeInteger(value)) {
|
|
745
|
+
return value < 0 ? create(NomosValueSchema, { kind: { case: "signedInteger", value: BigInt(value) } }) : create(NomosValueSchema, { kind: { case: "unsignedInteger", value: BigInt(value) } });
|
|
746
|
+
}
|
|
747
|
+
return create(NomosValueSchema, { kind: { case: "floatingPoint", value } });
|
|
748
|
+
}
|
|
749
|
+
if (typeof value === "string") {
|
|
750
|
+
return create(NomosValueSchema, { kind: { case: "text", value } });
|
|
751
|
+
}
|
|
752
|
+
if (value instanceof Uint8Array) {
|
|
753
|
+
return create(NomosValueSchema, { kind: { case: "bytes", value } });
|
|
754
|
+
}
|
|
755
|
+
if (Array.isArray(value)) {
|
|
756
|
+
return create(NomosValueSchema, {
|
|
757
|
+
kind: { case: "list", value: { values: value.map(protoValue) } }
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
if (typeof value === "object") {
|
|
761
|
+
return create(NomosValueSchema, {
|
|
762
|
+
kind: { case: "object", value: protoStruct(value) }
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
throw new Error(`unsupported NomosValue type: ${typeof value}`);
|
|
766
|
+
}
|
|
767
|
+
function protoStruct(value) {
|
|
768
|
+
return create(NomosStructSchema, {
|
|
769
|
+
fields: Object.fromEntries(Object.entries(value).map(([key, field]) => [key, protoValue(field)]))
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
function jsValue(value) {
|
|
773
|
+
if (!value) return void 0;
|
|
774
|
+
switch (value.kind.case) {
|
|
775
|
+
case "null":
|
|
776
|
+
return null;
|
|
777
|
+
case "boolean":
|
|
778
|
+
case "floatingPoint":
|
|
779
|
+
case "text":
|
|
780
|
+
case "bytes":
|
|
781
|
+
return value.kind.value;
|
|
782
|
+
case "signedInteger":
|
|
783
|
+
case "unsignedInteger": {
|
|
784
|
+
const integer = value.kind.value;
|
|
785
|
+
return integer >= BigInt(Number.MIN_SAFE_INTEGER) && integer <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(integer) : integer;
|
|
786
|
+
}
|
|
787
|
+
case "list":
|
|
788
|
+
return value.kind.value.values.map(jsValue);
|
|
789
|
+
case "object":
|
|
790
|
+
return jsStruct(value.kind.value);
|
|
791
|
+
default:
|
|
792
|
+
return void 0;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
function jsStruct(value) {
|
|
796
|
+
if (!value) return {};
|
|
797
|
+
return Object.fromEntries(Object.entries(value.fields).map(([key, field]) => [key, jsValue(field)]));
|
|
798
|
+
}
|
|
799
|
+
function unreachableOfferOutcome(value) {
|
|
800
|
+
throw new Error(`kernel returned an unsupported offer outcome: ${String(value)}`);
|
|
801
|
+
}
|
|
802
|
+
function offerResult(response) {
|
|
803
|
+
const outcome = response.outcome;
|
|
804
|
+
switch (outcome.case) {
|
|
805
|
+
case "admitted": {
|
|
806
|
+
const value = jsStruct(outcome.value.result);
|
|
807
|
+
return {
|
|
808
|
+
ok: true,
|
|
809
|
+
outcome: "admitted",
|
|
810
|
+
...typeof value.head === "string" ? { head: value.head } : {},
|
|
811
|
+
...value.intentOut !== void 0 ? { intentOut: value.intentOut } : {},
|
|
812
|
+
created: Array.isArray(value.created) ? value.created : [],
|
|
813
|
+
affected: Array.isArray(value.affected) ? value.affected : [],
|
|
814
|
+
born: Array.isArray(value.born) ? value.born : [],
|
|
815
|
+
birthOutcomes: Array.isArray(value.birthOutcomes) ? value.birthOutcomes : [],
|
|
816
|
+
...value.kernelSpans !== void 0 ? { kernelSpans: value.kernelSpans } : {},
|
|
817
|
+
...value.dryRun === true ? { dryRun: true } : {}
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
case "refused": {
|
|
821
|
+
const refusal = outcome.value.refusal;
|
|
822
|
+
if (!refusal) throw new Error("kernel returned an offer refusal without its typed refusal");
|
|
823
|
+
const diagnostics = jsStruct(outcome.value.diagnostics);
|
|
824
|
+
return {
|
|
825
|
+
ok: false,
|
|
826
|
+
outcome: "refused",
|
|
827
|
+
...outcome.value.offerId !== void 0 ? { offerId: outcome.value.offerId } : {},
|
|
828
|
+
refusal: {
|
|
829
|
+
code: refusal.code,
|
|
830
|
+
message: refusal.message,
|
|
831
|
+
details: jsStruct(refusal.details)
|
|
832
|
+
},
|
|
833
|
+
error: refusal.message,
|
|
834
|
+
...diagnostics.kernelSpans !== void 0 ? { kernelSpans: diagnostics.kernelSpans } : {}
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
case "deadLettered": {
|
|
838
|
+
const diagnostics = jsStruct(outcome.value.diagnostics);
|
|
839
|
+
return {
|
|
840
|
+
ok: false,
|
|
841
|
+
outcome: "deadLettered",
|
|
842
|
+
...outcome.value.offerId !== void 0 ? { offerId: outcome.value.offerId } : {},
|
|
843
|
+
reason: outcome.value.reason,
|
|
844
|
+
error: outcome.value.reason,
|
|
845
|
+
...diagnostics.kernelSpans !== void 0 ? { kernelSpans: diagnostics.kernelSpans } : {}
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
case "quarantined": {
|
|
849
|
+
const diagnostics = jsStruct(outcome.value.diagnostics);
|
|
850
|
+
return {
|
|
851
|
+
ok: false,
|
|
852
|
+
outcome: "quarantined",
|
|
853
|
+
...outcome.value.offerId !== void 0 ? { offerId: outcome.value.offerId } : {},
|
|
854
|
+
authoredLawHash: outcome.value.authoredLawHash,
|
|
855
|
+
currentLawHash: outcome.value.currentLawHash,
|
|
856
|
+
reason: outcome.value.reason,
|
|
857
|
+
error: outcome.value.reason,
|
|
858
|
+
...diagnostics.kernelSpans !== void 0 ? { kernelSpans: diagnostics.kernelSpans } : {}
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
case "blockedOnDependency": {
|
|
862
|
+
const diagnostics = jsStruct(outcome.value.diagnostics);
|
|
863
|
+
return {
|
|
864
|
+
ok: false,
|
|
865
|
+
outcome: "blockedOnDependency",
|
|
866
|
+
...outcome.value.offerId !== void 0 ? { offerId: outcome.value.offerId } : {},
|
|
867
|
+
detail: outcome.value.detail,
|
|
868
|
+
error: outcome.value.detail,
|
|
869
|
+
...diagnostics.kernelSpans !== void 0 ? { kernelSpans: diagnostics.kernelSpans } : {}
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
case void 0:
|
|
873
|
+
throw new Error("kernel returned an empty offer outcome");
|
|
874
|
+
default:
|
|
875
|
+
return unreachableOfferOutcome(outcome);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
function applicationQueryProto(eng, ws, query2, options = {}) {
|
|
879
|
+
const response = callProto(eng.ex, {
|
|
880
|
+
case: "query",
|
|
881
|
+
value: create(QueryRequestSchema, {
|
|
882
|
+
target: protoTarget(ws, options.branch ?? BRANCH),
|
|
883
|
+
authority: protoAuthority(
|
|
884
|
+
options.principal,
|
|
885
|
+
options.keys,
|
|
886
|
+
options.authToken,
|
|
887
|
+
options.nowUnix,
|
|
888
|
+
options.authorSecret
|
|
889
|
+
),
|
|
890
|
+
spans: options.spans ?? false,
|
|
891
|
+
query: query2
|
|
892
|
+
})
|
|
893
|
+
}, eng.STDERR);
|
|
894
|
+
if (response.outcome.case !== "query") {
|
|
895
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for application query`);
|
|
896
|
+
}
|
|
897
|
+
const result = response.outcome.value.result;
|
|
898
|
+
if (result.case === "applicationJson") {
|
|
899
|
+
return JSON.parse(dec3.decode(result.value.utf8));
|
|
900
|
+
}
|
|
901
|
+
if (result.case === "value") return jsValue(result.value);
|
|
902
|
+
throw new Error(`kernel returned ${result.case || "empty"} for application query`);
|
|
903
|
+
}
|
|
904
|
+
function namedQueryProto(eng, ws, operation, arguments_ = {}, options = {}) {
|
|
905
|
+
return applicationQueryProto(eng, ws, {
|
|
906
|
+
case: "named",
|
|
907
|
+
value: create(NamedQuerySchema, { operation, arguments: protoStruct(arguments_) })
|
|
908
|
+
}, options);
|
|
909
|
+
}
|
|
910
|
+
function custodyProto(eng, operation) {
|
|
911
|
+
return custodyProtoWith(eng.ex, operation, eng.STDERR);
|
|
912
|
+
}
|
|
913
|
+
function custodyProtoWith(ex, operation, STDERR) {
|
|
914
|
+
const response = callProto(ex, {
|
|
915
|
+
case: "custody",
|
|
916
|
+
value: create(CustodyRequestSchema, { operation })
|
|
917
|
+
}, STDERR);
|
|
918
|
+
if (response.outcome.case !== "custody" || !response.outcome.value.operation.case) {
|
|
919
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for custody request`);
|
|
920
|
+
}
|
|
921
|
+
return response.outcome.value.operation;
|
|
922
|
+
}
|
|
923
|
+
function custodyProtoCase(eng, operation, expected) {
|
|
924
|
+
const result = custodyProto(eng, operation);
|
|
925
|
+
if (result.case !== expected) {
|
|
926
|
+
throw new Error(`kernel returned custody.${result.case || "empty"}; expected custody.${expected}`);
|
|
927
|
+
}
|
|
928
|
+
return result.value;
|
|
929
|
+
}
|
|
930
|
+
function workspaceGenesis(eng, ws) {
|
|
931
|
+
const gitdir = gitdirOf(ws);
|
|
932
|
+
const head = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
933
|
+
if (!head) throw new Error(`workspaceGenesis: workspace '${ws}' has no main custody`);
|
|
934
|
+
const first = kgit.intentsAbove(eng, gitdir, head, "", 0, true)[0];
|
|
935
|
+
if (!first?.oid) throw new Error(`workspaceGenesis: workspace '${ws}' has an empty main custody`);
|
|
936
|
+
return first.oid;
|
|
937
|
+
}
|
|
938
|
+
async function createEngine({ wasmModule, bootstrapLawUsdz, nomosLawUsdz, replica, installedBy = "nomos-cloud" }) {
|
|
939
|
+
const assertUsdz = (name, bytes) => {
|
|
940
|
+
if (!(bytes instanceof Uint8Array) || bytes.length < 4 || bytes[0] !== 80 || bytes[1] !== 75 || bytes[2] !== 3 || bytes[3] !== 4) {
|
|
941
|
+
throw new Error(`${name} must be opaque USDZ bytes`);
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
assertUsdz("bootstrapLawUsdz", bootstrapLawUsdz);
|
|
945
|
+
assertUsdz("nomosLawUsdz", nomosLawUsdz);
|
|
946
|
+
const root = /* @__PURE__ */ new Map();
|
|
947
|
+
root.set("bootstrap.law.usdz", new File(bootstrapLawUsdz));
|
|
948
|
+
root.set("nomos.law.usdz", new File(nomosLawUsdz));
|
|
949
|
+
root.set("ws", new Directory(/* @__PURE__ */ new Map()));
|
|
950
|
+
const preopen = new PreopenDirectory("/work", root);
|
|
951
|
+
const STDERR = [];
|
|
952
|
+
const streamKernelStderr = globalThis.process?.env?.NOMOS_WASM_STDERR === "1";
|
|
953
|
+
const pushStderr = (l) => {
|
|
954
|
+
if (STDERR.length >= 500) STDERR.splice(0, STDERR.length - 499);
|
|
955
|
+
STDERR.push(l);
|
|
956
|
+
if (streamKernelStderr) console.error(`[nomos-kernel-stderr] ${l}`);
|
|
957
|
+
};
|
|
958
|
+
const fds = [new OpenFile(new File([])), ConsoleStdout.lineBuffered(() => {
|
|
959
|
+
}), ConsoleStdout.lineBuffered(pushStderr), preopen];
|
|
960
|
+
const wasi = new WASI(["wasm_git_holon", "reactor"], [], fds, { debug: false });
|
|
961
|
+
const wasiImports = unsignedWasiPointers(wasi.wasiImport);
|
|
962
|
+
const inst = await WebAssembly.instantiate(wasmModule, { wasi_snapshot_preview1: wasiImports });
|
|
963
|
+
const code = wasi.start(inst);
|
|
964
|
+
if (code !== 0) throw new Error(`reactor init exited ${code}; stderr=${STDERR.join("\n")}`);
|
|
965
|
+
const instExports = inst.exports;
|
|
966
|
+
for (const n of ["memory", "git_holon_alloc", "git_holon_dealloc", "git_holon_call_proto"]) if (!instExports[n]) throw new Error(`missing export ${n}`);
|
|
967
|
+
const ex = instExports;
|
|
968
|
+
const closureInfo = (closureFile) => {
|
|
969
|
+
const response = custodyProtoWith(ex, {
|
|
970
|
+
case: "lawClosureInfo",
|
|
971
|
+
value: create(LawClosureInfoRequestSchema, { closureFile })
|
|
972
|
+
}, STDERR);
|
|
973
|
+
if (response.case !== "lawClosureInfo") {
|
|
974
|
+
throw new Error(`kernel returned custody.${response.case || "empty"}; expected custody.lawClosureInfo`);
|
|
975
|
+
}
|
|
976
|
+
return response.value;
|
|
977
|
+
};
|
|
978
|
+
const bootstrapInfo = closureInfo("/work/bootstrap.law.usdz");
|
|
979
|
+
const nomosInfo = closureInfo("/work/nomos.law.usdz");
|
|
980
|
+
if (!bootstrapInfo.identity) throw new Error("bootstrap USDA closure refused: missing identity");
|
|
981
|
+
if (!nomosInfo.identity) throw new Error("Nomos USDA closure refused: missing identity");
|
|
982
|
+
const hashes = { bootstrap: bootstrapInfo.identity, nomos: nomosInfo.identity };
|
|
983
|
+
const eng = {
|
|
984
|
+
ex,
|
|
985
|
+
preopen,
|
|
986
|
+
STDERR,
|
|
987
|
+
seq: 0,
|
|
988
|
+
replica,
|
|
989
|
+
hashes,
|
|
990
|
+
bootstrapLawUsdz,
|
|
991
|
+
nomosLawUsdz,
|
|
992
|
+
installedBy,
|
|
993
|
+
fs: makeGitFs(preopen, "/work", { File, Directory }),
|
|
994
|
+
mounted: /* @__PURE__ */ new Map(),
|
|
995
|
+
// ws -> { restored, remoteMain, restoreError }
|
|
996
|
+
mainIntents: /* @__PURE__ */ new Map()
|
|
997
|
+
// ws -> { head, ids:Set, oids:Set } (admission idempotence)
|
|
998
|
+
};
|
|
999
|
+
return eng;
|
|
1000
|
+
}
|
|
1001
|
+
function directiveRoutes(eng) {
|
|
1002
|
+
return /* @__PURE__ */ new Map();
|
|
1003
|
+
}
|
|
1004
|
+
function routeTagHexOfMintedId(id) {
|
|
1005
|
+
const i = id.indexOf("_");
|
|
1006
|
+
if (i <= 0) return void 0;
|
|
1007
|
+
const body = id.slice(i + 1).replace(/-/g, "").toLowerCase();
|
|
1008
|
+
return /^[0-9a-f]{32}$/.test(body) ? body.slice(0, 12) : void 0;
|
|
1009
|
+
}
|
|
1010
|
+
async function wrongHomeVerdict(shardRouting, route, payload) {
|
|
1011
|
+
const value = payload ? payload[route.key] : void 0;
|
|
1012
|
+
if (typeof value !== "string" || !value) return null;
|
|
1013
|
+
const rows = await shardRouting.assignments() || [];
|
|
1014
|
+
let assignment = null;
|
|
1015
|
+
if (route.via === "axis") {
|
|
1016
|
+
assignment = rows.find((a) => a.homeKey === value) || null;
|
|
1017
|
+
} else {
|
|
1018
|
+
const tag = routeTagHexOfMintedId(value);
|
|
1019
|
+
if (tag !== void 0) {
|
|
1020
|
+
for (const a of rows) {
|
|
1021
|
+
if (await routeTagHexOfHomeKey(String(a.homeKey)) === tag) {
|
|
1022
|
+
assignment = a;
|
|
1023
|
+
break;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
if (!assignment) {
|
|
1029
|
+
return {
|
|
1030
|
+
error: `no shard placement for this write's home ('${route.key}': ${value.slice(0, 80)}) \u2014 author the derived placement intent (birth<Type>) on the coordinator '${shardRouting.coordinatorWs}' first, then POST /dead-letters/retry`,
|
|
1031
|
+
deadLettered: true
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
const movingTo = typeof assignment.status === "string" && assignment.status.startsWith("moving:") ? assignment.status.slice("moving:".length) : null;
|
|
1035
|
+
if (movingTo) {
|
|
1036
|
+
return {
|
|
1037
|
+
error: `home-moving: home '${value.slice(0, 80)}' is migrating ${assignment.shard} -> ${movingTo} (shard map v${assignment.mapVersion ?? 1}) \u2014 parked; a routed client retries automatically after the handoff seals`,
|
|
1038
|
+
homeMoving: { homeKey: value, from: assignment.shard, target: movingTo, workspace: `${shardRouting.coordinatorWs}--${movingTo}` },
|
|
1039
|
+
deadLettered: true
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
if (shardRouting.selfLabel === assignment.shard) return null;
|
|
1043
|
+
const correct = `${shardRouting.coordinatorWs}--${assignment.shard}`;
|
|
1044
|
+
return {
|
|
1045
|
+
error: `wrong-home: this write's home is assigned to '${correct}' (shard map v${assignment.mapVersion ?? 1}) \u2014 the client's shard map is stale; a routed client re-routes and retries automatically`,
|
|
1046
|
+
wrongHome: { workspace: correct, ...assignment.mapVersion !== void 0 ? { mapVersion: assignment.mapVersion } : {} }
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
function tenantTypes(eng) {
|
|
1050
|
+
return /* @__PURE__ */ new Set();
|
|
1051
|
+
}
|
|
1052
|
+
function placementDirectives(eng) {
|
|
1053
|
+
return /* @__PURE__ */ new Map();
|
|
1054
|
+
}
|
|
1055
|
+
function scopedReads(eng) {
|
|
1056
|
+
return [];
|
|
1057
|
+
}
|
|
1058
|
+
function evalCanonicalPred(pred, get) {
|
|
1059
|
+
if (!pred || typeof pred !== "object") return true;
|
|
1060
|
+
if (pred.kind === "and") return (pred.clauses || []).every((c) => evalCanonicalPred(c, get));
|
|
1061
|
+
if (pred.kind === "or") return (pred.clauses || []).some((c) => evalCanonicalPred(c, get));
|
|
1062
|
+
const raw = get(pred.field);
|
|
1063
|
+
const present = raw !== void 0 && raw !== null;
|
|
1064
|
+
const canonical = present ? String(raw) : void 0;
|
|
1065
|
+
if (pred.kind === "eq") return present && canonical === pred.value;
|
|
1066
|
+
if (pred.kind === "ne") return !present || canonical !== pred.value;
|
|
1067
|
+
return true;
|
|
1068
|
+
}
|
|
1069
|
+
function globalAggregates(eng) {
|
|
1070
|
+
return /* @__PURE__ */ new Set();
|
|
1071
|
+
}
|
|
1072
|
+
function parseIntentEvents(doc) {
|
|
1073
|
+
const rawEvents = doc?.events;
|
|
1074
|
+
const events = Array.isArray(rawEvents) ? rawEvents : [];
|
|
1075
|
+
return events.map((ev) => {
|
|
1076
|
+
const sets = /* @__PURE__ */ new Map();
|
|
1077
|
+
for (const op of ev.ops || []) {
|
|
1078
|
+
const v = op && op.op && op.op.Set;
|
|
1079
|
+
if (v === void 0) continue;
|
|
1080
|
+
if (typeof v.Str === "string") sets.set(op.field, v.Str);
|
|
1081
|
+
else if (typeof v.Int === "number") sets.set(op.field, v.Int);
|
|
1082
|
+
}
|
|
1083
|
+
return { aggregate: String(ev.aggregate || ""), sets };
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
function beginSummaryCapture(eng, ws, ctx, doc) {
|
|
1087
|
+
const events = parseIntentEvents(doc);
|
|
1088
|
+
if (events.length === 0) return null;
|
|
1089
|
+
const pre = /* @__PURE__ */ new Map();
|
|
1090
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
1091
|
+
for (const ev of events) {
|
|
1092
|
+
if (!pre.has(ev.aggregate)) {
|
|
1093
|
+
const rows = qById(eng, ws, ev.aggregate);
|
|
1094
|
+
pre.set(ev.aggregate, rows.length ? { type: rows[0].type, data: rows[0].data || {} } : null);
|
|
1095
|
+
}
|
|
1096
|
+
const before = pre.get(ev.aggregate);
|
|
1097
|
+
const evType = ev.sets.get("__type") ?? (before ? before.type : void 0);
|
|
1098
|
+
for (const read of ctx.reads) {
|
|
1099
|
+
if (read.of !== evType) continue;
|
|
1100
|
+
const oldGroup = before ? groupOf(read, before.data) : void 0;
|
|
1101
|
+
if (oldGroup !== void 0) candidates.add(summaryKey(read.id, oldGroup));
|
|
1102
|
+
if (read.by === null) candidates.add(summaryKey(read.id, ""));
|
|
1103
|
+
else if (ev.sets.has(read.by)) candidates.add(summaryKey(read.id, String(ev.sets.get(read.by))));
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
const preTallies = /* @__PURE__ */ new Map();
|
|
1107
|
+
for (const key of candidates) {
|
|
1108
|
+
const [readId, group] = splitSummaryKey(key);
|
|
1109
|
+
const read = ctx.reads.find((r) => r.id === readId);
|
|
1110
|
+
const v = tallyOf(eng, ws, read, group);
|
|
1111
|
+
preTallies.set(key, v);
|
|
1112
|
+
if (!ctx.prevs.has(key)) ctx.prevs.set(key, { read, group, value: v });
|
|
1113
|
+
}
|
|
1114
|
+
return { events, pre, candidates, preTallies };
|
|
1115
|
+
}
|
|
1116
|
+
function finishSummaryCapture(eng, ws, ctx, cap, oid, intentId) {
|
|
1117
|
+
const deltas = [];
|
|
1118
|
+
for (const key of cap.candidates) {
|
|
1119
|
+
const [readId, group] = splitSummaryKey(key);
|
|
1120
|
+
const read = ctx.reads.find((r) => r.id === readId);
|
|
1121
|
+
const after = tallyOf(eng, ws, read, group);
|
|
1122
|
+
if (isExtremumRead(read)) {
|
|
1123
|
+
const before = cap.preTallies.has(key) ? cap.preTallies.get(key) : null;
|
|
1124
|
+
if (after !== before) {
|
|
1125
|
+
deltas.push({ readId, group, delta: after });
|
|
1126
|
+
if (!extremumMonotone(read, before, after)) ctx.rederived.add(key);
|
|
1127
|
+
}
|
|
1128
|
+
} else {
|
|
1129
|
+
const before = cap.preTallies.get(key) ?? 0;
|
|
1130
|
+
if (after !== before) deltas.push({ readId, group, delta: after - before });
|
|
1131
|
+
}
|
|
1132
|
+
ctx.values.set(key, { read, group, value: after });
|
|
1133
|
+
}
|
|
1134
|
+
let rowsDelta = 0;
|
|
1135
|
+
for (const [aggregateId, before] of cap.pre) {
|
|
1136
|
+
const rows = qById(eng, ws, aggregateId);
|
|
1137
|
+
const type = rows.length ? rows[0].type : before ? before.type : void 0;
|
|
1138
|
+
if (type === void 0 || !tenantTypes(eng).has(type)) continue;
|
|
1139
|
+
const existsAfter = rows.length > 0;
|
|
1140
|
+
const flip = !before && existsAfter ? 1 : before && !existsAfter ? -1 : 0;
|
|
1141
|
+
if (flip === 0) continue;
|
|
1142
|
+
rowsDelta += flip;
|
|
1143
|
+
const homeKey = ctx.homeKeySet && ctx.homeKeySet.has(aggregateId) ? aggregateId : ctx.homeTags ? ctx.homeTags.get(routeTagHexOfMintedId(aggregateId) ?? "") : void 0;
|
|
1144
|
+
if (homeKey !== void 0) {
|
|
1145
|
+
deltas.push({ readId: NOMOS_SHARD_ROWS_READ, group: homeKey, delta: flip });
|
|
1146
|
+
ctx.rowsByHome.set(homeKey, (ctx.rowsByHome.get(homeKey) ?? 0) + flip);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
if (rowsDelta !== 0) {
|
|
1150
|
+
deltas.push({ readId: NOMOS_SHARD_ROWS_READ, group: "", delta: rowsDelta });
|
|
1151
|
+
ctx.rowsDelta += rowsDelta;
|
|
1152
|
+
}
|
|
1153
|
+
if (deltas.length > 0) ctx.events.push({ oid, intentId: intentId || "", deltas });
|
|
1154
|
+
}
|
|
1155
|
+
function summaryOfCapture(ctx, fromOid, toOid) {
|
|
1156
|
+
if (ctx.events.length === 0 || !toOid || fromOid === toOid) return null;
|
|
1157
|
+
const touched = /* @__PURE__ */ new Set();
|
|
1158
|
+
for (const ev of ctx.events) for (const d of ev.deltas) touched.add(summaryKey(d.readId, d.group));
|
|
1159
|
+
const subtotals = [];
|
|
1160
|
+
for (const [key, cur] of ctx.values) {
|
|
1161
|
+
const extremum2 = isExtremumRead(cur.read);
|
|
1162
|
+
const prev = ctx.prevs.get(key);
|
|
1163
|
+
const prevValue = prev ? prev.value : extremum2 ? null : 0;
|
|
1164
|
+
if (cur.value === prevValue && !touched.has(key)) continue;
|
|
1165
|
+
subtotals.push({
|
|
1166
|
+
readId: cur.read.id,
|
|
1167
|
+
group: cur.group,
|
|
1168
|
+
kind: cur.read.kind,
|
|
1169
|
+
prev: prevValue,
|
|
1170
|
+
value: cur.value,
|
|
1171
|
+
...extremum2 && ctx.rederived.has(key) ? { rederived: true } : {}
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
if (subtotals.length === 0 && ctx.rowsDelta === 0 && ctx.rowsByHome.size === 0) return null;
|
|
1175
|
+
return {
|
|
1176
|
+
fromOid: fromOid || "",
|
|
1177
|
+
toOid,
|
|
1178
|
+
subtotals: subtotals.sort((a, b) => summaryKey(a.readId, a.group) < summaryKey(b.readId, b.group) ? -1 : 1),
|
|
1179
|
+
events: ctx.events,
|
|
1180
|
+
rowsDelta: ctx.rowsDelta,
|
|
1181
|
+
// SLICE 8: the exact per-home row deltas — the adapter closes each against the
|
|
1182
|
+
// coordinator-held per-home subtotal exactly like the "" grand total.
|
|
1183
|
+
rowsByHome: Object.fromEntries([...ctx.rowsByHome.entries()].sort((a, b) => a[0] < b[0] ? -1 : 1))
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
async function deriveSummarySuffix(eng, ws, fromOid) {
|
|
1187
|
+
const reads = scopedReads(eng);
|
|
1188
|
+
const gitdir = gitdirOf(ws);
|
|
1189
|
+
const head = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
1190
|
+
if (!head) return { ok: false, error: "no local main to derive from" };
|
|
1191
|
+
const commits = kgit.intentsAbove(eng, gitdir, head);
|
|
1192
|
+
const state = /* @__PURE__ */ new Map();
|
|
1193
|
+
const running = /* @__PURE__ */ new Map();
|
|
1194
|
+
const bump = (key, d) => running.set(key, (running.get(key) ?? 0) + d);
|
|
1195
|
+
const extRows = /* @__PURE__ */ new Map();
|
|
1196
|
+
const extRunning = /* @__PURE__ */ new Map();
|
|
1197
|
+
const extRederived = /* @__PURE__ */ new Set();
|
|
1198
|
+
const extBucketRows = (key) => {
|
|
1199
|
+
let m = extRows.get(key);
|
|
1200
|
+
if (!m) {
|
|
1201
|
+
m = /* @__PURE__ */ new Map();
|
|
1202
|
+
extRows.set(key, m);
|
|
1203
|
+
}
|
|
1204
|
+
return m;
|
|
1205
|
+
};
|
|
1206
|
+
const recomputeExt = (read, key) => {
|
|
1207
|
+
let v = null;
|
|
1208
|
+
const m = extRows.get(key);
|
|
1209
|
+
if (m) for (const x of m.values()) v = v === null ? x : read.kind === "min" ? Math.min(v, x) : Math.max(v, x);
|
|
1210
|
+
return v;
|
|
1211
|
+
};
|
|
1212
|
+
const homeKeySet = /* @__PURE__ */ new Set();
|
|
1213
|
+
const homeTags = /* @__PURE__ */ new Map();
|
|
1214
|
+
let prevs = null;
|
|
1215
|
+
let extPrevs = null;
|
|
1216
|
+
let events = [];
|
|
1217
|
+
let inSuffix = fromOid === "" || fromOid === void 0;
|
|
1218
|
+
if (inSuffix) {
|
|
1219
|
+
prevs = /* @__PURE__ */ new Map();
|
|
1220
|
+
extPrevs = /* @__PURE__ */ new Map();
|
|
1221
|
+
}
|
|
1222
|
+
let sawFrom = inSuffix;
|
|
1223
|
+
for (const c of commits) {
|
|
1224
|
+
let blob = null;
|
|
1225
|
+
try {
|
|
1226
|
+
blob = bytesFromB64(c.changeB64);
|
|
1227
|
+
} catch {
|
|
1228
|
+
}
|
|
1229
|
+
const deltas = [];
|
|
1230
|
+
let intentId = "";
|
|
1231
|
+
if (blob) {
|
|
1232
|
+
const doc = c.intent;
|
|
1233
|
+
if (doc && Array.isArray(doc.strikes) && doc.strikes.length > 0) {
|
|
1234
|
+
return { ok: true, strikeBearing: true, head };
|
|
1235
|
+
}
|
|
1236
|
+
intentId = doc && doc.id || "";
|
|
1237
|
+
for (const ev of parseIntentEvents(doc)) {
|
|
1238
|
+
const cur = state.get(ev.aggregate) ?? { type: void 0, fields: /* @__PURE__ */ new Map(), exists: false };
|
|
1239
|
+
const newType = ev.sets.get("__type");
|
|
1240
|
+
if (newType !== void 0) cur.type = newType;
|
|
1241
|
+
const tallyBefore = /* @__PURE__ */ new Map();
|
|
1242
|
+
for (const read of reads) {
|
|
1243
|
+
if (read.of !== cur.type && read.of !== newType) continue;
|
|
1244
|
+
tallyBefore.set(read.id, contribution(read, cur));
|
|
1245
|
+
}
|
|
1246
|
+
const existedBefore = cur.exists;
|
|
1247
|
+
for (const [f, v] of ev.sets) cur.fields.set(f, v);
|
|
1248
|
+
cur.exists = true;
|
|
1249
|
+
state.set(ev.aggregate, cur);
|
|
1250
|
+
const effType = cur.type ?? newType;
|
|
1251
|
+
if (effType === "NomosHomeReceipt") {
|
|
1252
|
+
const hk = cur.fields.get("homeKey");
|
|
1253
|
+
if (typeof hk === "string" && hk && !homeKeySet.has(hk)) {
|
|
1254
|
+
homeKeySet.add(hk);
|
|
1255
|
+
homeTags.set(await routeTagHexOfHomeKey(hk), hk);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
if (!existedBefore && effType !== void 0 && tenantTypes(eng).has(effType)) {
|
|
1259
|
+
bump(summaryKey(NOMOS_SHARD_ROWS_READ, ""), 1);
|
|
1260
|
+
deltas.push({ readId: NOMOS_SHARD_ROWS_READ, group: "", delta: 1 });
|
|
1261
|
+
const homeKey = homeKeySet.has(ev.aggregate) ? ev.aggregate : homeTags.get(routeTagHexOfMintedId(ev.aggregate) ?? "");
|
|
1262
|
+
if (homeKey !== void 0) {
|
|
1263
|
+
bump(summaryKey(NOMOS_SHARD_ROWS_READ, homeKey), 1);
|
|
1264
|
+
deltas.push({ readId: NOMOS_SHARD_ROWS_READ, group: homeKey, delta: 1 });
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
for (const read of reads) {
|
|
1268
|
+
if (read.of !== cur.type) continue;
|
|
1269
|
+
const before = tallyBefore.get(read.id) ?? null;
|
|
1270
|
+
const after = contribution(read, cur);
|
|
1271
|
+
if (isExtremumRead(read)) {
|
|
1272
|
+
const touchedBuckets = /* @__PURE__ */ new Set();
|
|
1273
|
+
if (before) {
|
|
1274
|
+
const bk = summaryKey(read.id, before.group);
|
|
1275
|
+
if (!after || after.group !== before.group) extBucketRows(bk).delete(ev.aggregate);
|
|
1276
|
+
touchedBuckets.add(bk);
|
|
1277
|
+
}
|
|
1278
|
+
if (after) {
|
|
1279
|
+
const ak = summaryKey(read.id, after.group);
|
|
1280
|
+
extBucketRows(ak).set(ev.aggregate, after.value);
|
|
1281
|
+
touchedBuckets.add(ak);
|
|
1282
|
+
}
|
|
1283
|
+
for (const bk of touchedBuckets) {
|
|
1284
|
+
const ov = extRunning.has(bk) ? extRunning.get(bk) ?? null : null;
|
|
1285
|
+
const nv = recomputeExt(read, bk);
|
|
1286
|
+
if (nv === ov) continue;
|
|
1287
|
+
extRunning.set(bk, nv);
|
|
1288
|
+
if (inSuffix) {
|
|
1289
|
+
if (!extremumMonotone(read, ov, nv)) extRederived.add(bk);
|
|
1290
|
+
const [, group] = splitSummaryKey(bk);
|
|
1291
|
+
deltas.push({ readId: read.id, group, delta: nv, __extremum: true });
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
} else {
|
|
1295
|
+
for (const d of contributionDiff(read, before, after)) {
|
|
1296
|
+
bump(summaryKey(d.readId, d.group), d.delta ?? 0);
|
|
1297
|
+
deltas.push(d);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
if (inSuffix && deltas.length) {
|
|
1304
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1305
|
+
const extLast = /* @__PURE__ */ new Map();
|
|
1306
|
+
for (const d of deltas) {
|
|
1307
|
+
const k = summaryKey(d.readId, d.group);
|
|
1308
|
+
if (d.__extremum) extLast.set(k, d.delta);
|
|
1309
|
+
else byKey.set(k, (byKey.get(k) ?? 0) + d.delta);
|
|
1310
|
+
}
|
|
1311
|
+
const merged = [...byKey.entries()].filter(([, d]) => d !== 0).map(([k, d]) => {
|
|
1312
|
+
const [readId, group] = splitSummaryKey(k);
|
|
1313
|
+
return { readId, group, delta: d };
|
|
1314
|
+
});
|
|
1315
|
+
for (const [k, v] of extLast) {
|
|
1316
|
+
const [readId, group] = splitSummaryKey(k);
|
|
1317
|
+
merged.push({ readId, group, delta: v });
|
|
1318
|
+
}
|
|
1319
|
+
if (merged.length) events.push({ oid: c.oid, intentId, deltas: merged });
|
|
1320
|
+
}
|
|
1321
|
+
if (!inSuffix && c.oid === fromOid) {
|
|
1322
|
+
inSuffix = true;
|
|
1323
|
+
sawFrom = true;
|
|
1324
|
+
prevs = new Map(running);
|
|
1325
|
+
extPrevs = new Map(extRunning);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
if (!sawFrom) return { ok: false, error: `fromOid ${String(fromOid).slice(0, 12)} is not on this shard's main \u2014 cannot derive the suffix` };
|
|
1329
|
+
if (!prevs) prevs = /* @__PURE__ */ new Map();
|
|
1330
|
+
const touched = /* @__PURE__ */ new Set();
|
|
1331
|
+
for (const ev of events) for (const d of ev.deltas) touched.add(summaryKey(d.readId, d.group));
|
|
1332
|
+
const subtotals = [];
|
|
1333
|
+
const keys = /* @__PURE__ */ new Set([...running.keys(), ...prevs.keys()]);
|
|
1334
|
+
for (const key of keys) {
|
|
1335
|
+
const value = running.get(key) ?? 0;
|
|
1336
|
+
const prev = prevs.get(key) ?? 0;
|
|
1337
|
+
if (value === prev && !touched.has(key)) continue;
|
|
1338
|
+
const [readId, group] = splitSummaryKey(key);
|
|
1339
|
+
const read = reads.find((r) => r.id === readId);
|
|
1340
|
+
subtotals.push({ readId, group, kind: readId === NOMOS_SHARD_ROWS_READ ? "rows" : read ? read.kind : "count", prev, value });
|
|
1341
|
+
}
|
|
1342
|
+
const extKeys = /* @__PURE__ */ new Set([...extRunning.keys(), ...extPrevs ? extPrevs.keys() : []]);
|
|
1343
|
+
for (const key of extKeys) {
|
|
1344
|
+
const value = extRunning.has(key) ? extRunning.get(key) : null;
|
|
1345
|
+
const prev = extPrevs && extPrevs.has(key) ? extPrevs.get(key) : null;
|
|
1346
|
+
if (value === prev && !touched.has(key)) continue;
|
|
1347
|
+
const [readId, group] = splitSummaryKey(key);
|
|
1348
|
+
const read = reads.find((r) => r.id === readId);
|
|
1349
|
+
if (!read) continue;
|
|
1350
|
+
subtotals.push({ readId, group, kind: read.kind, prev, value, ...extRederived.has(key) ? { rederived: true } : {} });
|
|
1351
|
+
}
|
|
1352
|
+
if (subtotals.length === 0) return { ok: true, upToDate: true, head };
|
|
1353
|
+
return {
|
|
1354
|
+
ok: true,
|
|
1355
|
+
head,
|
|
1356
|
+
payload: {
|
|
1357
|
+
fromOid: fromOid || "",
|
|
1358
|
+
toOid: head,
|
|
1359
|
+
subtotals: subtotals.sort((a, b) => summaryKey(a.readId, a.group) < summaryKey(b.readId, b.group) ? -1 : 1),
|
|
1360
|
+
events
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
function contribution(read, cur) {
|
|
1365
|
+
if (!cur || !cur.exists || cur.type !== read.of) return null;
|
|
1366
|
+
if (read.where && !evalCanonicalPred(read.where, (f) => cur.fields.get(f))) return null;
|
|
1367
|
+
const group = read.by === null ? "" : cur.fields.has(read.by) ? String(cur.fields.get(read.by)) : void 0;
|
|
1368
|
+
if (group === void 0) return null;
|
|
1369
|
+
if (read.kind === "count") return { group, value: 1 };
|
|
1370
|
+
const raw = cur.fields.get(read.field);
|
|
1371
|
+
if (isExtremumRead(read) && typeof raw !== "number") return null;
|
|
1372
|
+
return { group, value: typeof raw === "number" ? raw : 0 };
|
|
1373
|
+
}
|
|
1374
|
+
function contributionDiff(read, before, after) {
|
|
1375
|
+
const out2 = [];
|
|
1376
|
+
if (before && after && before.group === after.group) {
|
|
1377
|
+
const d = after.value - before.value;
|
|
1378
|
+
if (d !== 0) out2.push({ readId: read.id, group: after.group, delta: d });
|
|
1379
|
+
return out2;
|
|
1380
|
+
}
|
|
1381
|
+
if (before) out2.push({ readId: read.id, group: before.group, delta: -before.value });
|
|
1382
|
+
if (after) out2.push({ readId: read.id, group: after.group, delta: after.value });
|
|
1383
|
+
return out2.filter((d) => d.delta !== 0);
|
|
1384
|
+
}
|
|
1385
|
+
function countTenantRows(eng, ws) {
|
|
1386
|
+
let total = 0;
|
|
1387
|
+
for (const type of tenantTypes(eng)) {
|
|
1388
|
+
total += query(eng, ws, "aggregatesByType", JSON.stringify({ __type: type })).length;
|
|
1389
|
+
}
|
|
1390
|
+
return total;
|
|
1391
|
+
}
|
|
1392
|
+
async function countTenantRowsByHome(eng, ws, homeKeys) {
|
|
1393
|
+
const keySet = new Set(homeKeys);
|
|
1394
|
+
const tagOf = /* @__PURE__ */ new Map();
|
|
1395
|
+
for (const hk of homeKeys) tagOf.set(await routeTagHexOfHomeKey(hk), hk);
|
|
1396
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
1397
|
+
for (const hk of homeKeys) out2.set(hk, 0);
|
|
1398
|
+
for (const type of tenantTypes(eng)) {
|
|
1399
|
+
for (const r of query(eng, ws, "aggregatesByType", JSON.stringify({ __type: type }))) {
|
|
1400
|
+
const id = String(r.id || "");
|
|
1401
|
+
const hk = keySet.has(id) ? id : tagOf.get(routeTagHexOfMintedId(id) ?? "");
|
|
1402
|
+
if (hk !== void 0) out2.set(hk, (out2.get(hk) ?? 0) + 1);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
return out2;
|
|
1406
|
+
}
|
|
1407
|
+
async function collectHomedIntents(eng, ws, homeKeys) {
|
|
1408
|
+
const routes = directiveRoutes(eng);
|
|
1409
|
+
const tagOf = /* @__PURE__ */ new Map();
|
|
1410
|
+
for (const hk of homeKeys) tagOf.set(await routeTagHexOfHomeKey(hk), hk);
|
|
1411
|
+
const keySet = new Set(homeKeys);
|
|
1412
|
+
const gitdir = gitdirOf(ws);
|
|
1413
|
+
const head = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
1414
|
+
const commits = head ? kgit.intentsAbove(eng, gitdir, head) : [];
|
|
1415
|
+
const docs = [];
|
|
1416
|
+
const strikeParity = /* @__PURE__ */ new Map();
|
|
1417
|
+
for (const c of commits) {
|
|
1418
|
+
let doc = null;
|
|
1419
|
+
try {
|
|
1420
|
+
const blob = bytesFromB64(c.changeB64);
|
|
1421
|
+
doc = c.intent;
|
|
1422
|
+
docs.push({ oid: c.oid, blob, doc });
|
|
1423
|
+
} catch {
|
|
1424
|
+
continue;
|
|
1425
|
+
}
|
|
1426
|
+
for (const target of doc && Array.isArray(doc.strikes) ? doc.strikes : []) {
|
|
1427
|
+
strikeParity.set(target, (strikeParity.get(target) ?? 0) + 1);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
const out2 = [];
|
|
1431
|
+
for (const { oid, blob, doc } of docs) {
|
|
1432
|
+
const id = doc && typeof doc.id === "string" ? doc.id : null;
|
|
1433
|
+
if (!id || (strikeParity.get(id) ?? 0) % 2 === 1) continue;
|
|
1434
|
+
const dom = doc.payload && typeof doc.payload.domain === "string" ? doc.payload.domain : null;
|
|
1435
|
+
const dirId = doc.payload && typeof doc.payload.directiveId === "string" ? doc.payload.directiveId : null;
|
|
1436
|
+
const route = dom && dirId ? routes.get(`${dom} ${dirId}`) : null;
|
|
1437
|
+
if (!route) continue;
|
|
1438
|
+
const value = doc.payload.payload ? doc.payload.payload[route.key] : void 0;
|
|
1439
|
+
if (typeof value !== "string" || !value) continue;
|
|
1440
|
+
let homeKey = null;
|
|
1441
|
+
if (route.via === "axis") homeKey = keySet.has(value) ? value : null;
|
|
1442
|
+
else {
|
|
1443
|
+
const tag = routeTagHexOfMintedId(value);
|
|
1444
|
+
homeKey = tag !== void 0 ? tagOf.get(tag) ?? null : null;
|
|
1445
|
+
}
|
|
1446
|
+
if (homeKey !== null) out2.push({ oid, id, homeKey, blob });
|
|
1447
|
+
}
|
|
1448
|
+
return out2;
|
|
1449
|
+
}
|
|
1450
|
+
async function migrateHomes(eng, ws, ledger, sourceWs, homeKeys, { onlyIds = null } = {}) {
|
|
1451
|
+
const wanted = onlyIds ? new Set(onlyIds) : null;
|
|
1452
|
+
const homed = await collectHomedIntents(eng, sourceWs, homeKeys);
|
|
1453
|
+
const main = await mainIntentIds(eng, ws);
|
|
1454
|
+
const migrated = [], skipped = [], refused = [];
|
|
1455
|
+
for (const e of homed) {
|
|
1456
|
+
if (wanted && !wanted.has(e.id)) continue;
|
|
1457
|
+
if (main.ids.has(e.id)) {
|
|
1458
|
+
skipped.push(e.id);
|
|
1459
|
+
continue;
|
|
1460
|
+
}
|
|
1461
|
+
const res = offerAdmit(eng, ws, e.blob);
|
|
1462
|
+
if (res.ok) {
|
|
1463
|
+
main.ids.add(e.id);
|
|
1464
|
+
main.oids.add(res.head);
|
|
1465
|
+
main.head = res.head;
|
|
1466
|
+
migrated.push(e.id);
|
|
1467
|
+
} else {
|
|
1468
|
+
refused.push({ intentId: e.id, oid: e.oid.slice(0, 10), error: String(res.error || "").slice(0, 300) });
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
if (migrated.length) await commitAndPush(eng, ws, ledger);
|
|
1472
|
+
log("migrate-homes", { ws, from: sourceWs, migrated: migrated.length, skipped: skipped.length, refused: refused.length });
|
|
1473
|
+
return { migrated, skipped, refused };
|
|
1474
|
+
}
|
|
1475
|
+
async function sealHomes(eng, ws, ledger, { domain, lawHash, homeKeys, target, migratedIds, sealedAt }) {
|
|
1476
|
+
const have = new Set(migratedIds);
|
|
1477
|
+
const homed = await collectHomedIntents(eng, ws, homeKeys);
|
|
1478
|
+
const missing = homed.filter((e) => !have.has(e.id)).map((e) => e.id);
|
|
1479
|
+
if (missing.length) return { ok: false, missing };
|
|
1480
|
+
const ids = homed.map((e) => e.id);
|
|
1481
|
+
const CHUNK = 1024;
|
|
1482
|
+
let head = null, struck = 0;
|
|
1483
|
+
for (let i = 0; i < Math.max(1, Math.ceil(ids.length / CHUNK)); i++) {
|
|
1484
|
+
const intentIds = ids.slice(i * CHUNK, (i + 1) * CHUNK);
|
|
1485
|
+
const res = author(eng, ws, domain, "nomosSealHome", { homeKeys: [...homeKeys], target, intentIds, sealedAt }, lawHash, { rngDraws: 8 });
|
|
1486
|
+
if (res && res.ok === false) return { ok: false, error: String(res.error || "the law refused the seal").slice(0, 400) };
|
|
1487
|
+
head = res.head;
|
|
1488
|
+
struck += intentIds.length;
|
|
1489
|
+
}
|
|
1490
|
+
await commitAndPush(eng, ws, ledger);
|
|
1491
|
+
log("seal-homes", { ws, target, homes: homeKeys.length, struck, head });
|
|
1492
|
+
return { ok: true, head, struck };
|
|
1493
|
+
}
|
|
1494
|
+
async function summaryCloseAgainstHeld(eng, ws, heldRows, heldFrontier) {
|
|
1495
|
+
const head = kgit.resolveRef(eng, gitdirOf(ws), BRANCH);
|
|
1496
|
+
if (!head) return { ok: false, error: "no local main to close against" };
|
|
1497
|
+
if (head === heldFrontier) return { ok: true, upToDate: true, head };
|
|
1498
|
+
const subtotals = [];
|
|
1499
|
+
const deltas = [];
|
|
1500
|
+
const heldHomes = heldRows.map((row) => row.data || row).filter((d) => d.readId === NOMOS_SHARD_ROWS_READ && typeof d.group === "string" && d.group !== "").map((d) => d.group);
|
|
1501
|
+
const byHome = heldHomes.length ? await countTenantRowsByHome(eng, ws, heldHomes) : /* @__PURE__ */ new Map();
|
|
1502
|
+
for (const row of heldRows) {
|
|
1503
|
+
const d = row.data || row;
|
|
1504
|
+
if (typeof d.readId !== "string") continue;
|
|
1505
|
+
const group = typeof d.group === "string" ? d.group : "";
|
|
1506
|
+
if (d.kind === "min" || d.kind === "max") {
|
|
1507
|
+
const heldVal = d.empty === 1 || typeof d.value !== "number" ? null : d.value;
|
|
1508
|
+
const nowVal = extremum(eng, ws, d.readId, d.kind, group).value;
|
|
1509
|
+
if (nowVal === heldVal) continue;
|
|
1510
|
+
subtotals.push({ readId: d.readId, group, kind: d.kind, prev: heldVal, value: nowVal, rederived: true });
|
|
1511
|
+
deltas.push({ readId: d.readId, group, delta: nowVal });
|
|
1512
|
+
continue;
|
|
1513
|
+
}
|
|
1514
|
+
const held = typeof d.value === "number" ? d.value : 0;
|
|
1515
|
+
let now;
|
|
1516
|
+
if (d.readId === NOMOS_SHARD_ROWS_READ) now = group === "" ? countTenantRows(eng, ws) : byHome.get(group) ?? 0;
|
|
1517
|
+
else if (d.kind === "sum") now = sum(eng, ws, d.readId, group).sum;
|
|
1518
|
+
else now = count(eng, ws, d.readId, group).count;
|
|
1519
|
+
if (now === held) continue;
|
|
1520
|
+
subtotals.push({ readId: d.readId, group, kind: d.kind === "sum" || d.kind === "rows" ? d.kind : "count", prev: held, value: now });
|
|
1521
|
+
deltas.push({ readId: d.readId, group, delta: now - held });
|
|
1522
|
+
}
|
|
1523
|
+
if (subtotals.length === 0) return { ok: true, frontierOnly: true, head };
|
|
1524
|
+
return {
|
|
1525
|
+
ok: true,
|
|
1526
|
+
head,
|
|
1527
|
+
payload: {
|
|
1528
|
+
fromOid: heldFrontier || "",
|
|
1529
|
+
toOid: head,
|
|
1530
|
+
subtotals: subtotals.sort((a, b) => summaryKey(a.readId, a.group) < summaryKey(b.readId, b.group) ? -1 : 1),
|
|
1531
|
+
events: [{ oid: head, intentId: "", deltas }]
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
}
|
|
1535
|
+
async function collectGlobalIntents(eng, ws) {
|
|
1536
|
+
const globals = globalAggregates(eng);
|
|
1537
|
+
if (globals.size === 0) return [];
|
|
1538
|
+
const gitdir = gitdirOf(ws);
|
|
1539
|
+
const head = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
1540
|
+
const commits = head ? kgit.intentsAbove(eng, gitdir, head) : [];
|
|
1541
|
+
const typeOf = /* @__PURE__ */ new Map();
|
|
1542
|
+
const strikeParity = /* @__PURE__ */ new Map();
|
|
1543
|
+
const docs = [];
|
|
1544
|
+
for (const c of commits) {
|
|
1545
|
+
let blob = null, doc = null;
|
|
1546
|
+
try {
|
|
1547
|
+
blob = bytesFromB64(c.changeB64);
|
|
1548
|
+
doc = c.intent;
|
|
1549
|
+
} catch {
|
|
1550
|
+
continue;
|
|
1551
|
+
}
|
|
1552
|
+
docs.push({ oid: c.oid, blob, doc });
|
|
1553
|
+
for (const target of doc && Array.isArray(doc.strikes) ? doc.strikes : []) {
|
|
1554
|
+
strikeParity.set(target, (strikeParity.get(target) ?? 0) + 1);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
const out2 = [];
|
|
1558
|
+
for (const { oid, blob, doc } of docs) {
|
|
1559
|
+
const id = doc && typeof doc.id === "string" ? doc.id : null;
|
|
1560
|
+
let touches = false;
|
|
1561
|
+
for (const ev of parseIntentEvents(doc)) {
|
|
1562
|
+
const newType = ev.sets.get("__type");
|
|
1563
|
+
if (newType !== void 0 && !typeOf.has(ev.aggregate)) typeOf.set(ev.aggregate, newType);
|
|
1564
|
+
const t = newType ?? typeOf.get(ev.aggregate);
|
|
1565
|
+
if (t !== void 0 && globals.has(t)) touches = true;
|
|
1566
|
+
}
|
|
1567
|
+
if (!touches || !id || (strikeParity.get(id) ?? 0) % 2 === 1) continue;
|
|
1568
|
+
out2.push({ oid, id, blob });
|
|
1569
|
+
}
|
|
1570
|
+
return out2;
|
|
1571
|
+
}
|
|
1572
|
+
async function replicateIntents(eng, ws, ledger, intents, { push = true } = {}) {
|
|
1573
|
+
const main = await mainIntentIds(eng, ws);
|
|
1574
|
+
const replicated = [], skipped = [], refused = [];
|
|
1575
|
+
for (const e of intents) {
|
|
1576
|
+
if (e.id && main.ids.has(e.id)) {
|
|
1577
|
+
skipped.push(e.id);
|
|
1578
|
+
continue;
|
|
1579
|
+
}
|
|
1580
|
+
const res = offerAdmit(eng, ws, e.blob);
|
|
1581
|
+
if (res.ok) {
|
|
1582
|
+
if (e.id) main.ids.add(e.id);
|
|
1583
|
+
main.oids.add(res.head);
|
|
1584
|
+
main.head = res.head;
|
|
1585
|
+
replicated.push(e.id || res.head);
|
|
1586
|
+
} else {
|
|
1587
|
+
refused.push({ intentId: e.id || "", error: String(res.error || "").slice(0, 300) });
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
if (replicated.length && push) await commitAndPush(eng, ws, ledger);
|
|
1591
|
+
log("replicate-globals", { ws, replicated: replicated.length, skipped: skipped.length, refused: refused.length });
|
|
1592
|
+
return { replicated, skipped, refused };
|
|
1593
|
+
}
|
|
1594
|
+
async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence = null, shardRouting = null, clientBase = null } = {}) {
|
|
1595
|
+
const main = await mainIntentIds(eng, ws);
|
|
1596
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
1597
|
+
const deadLetters = [];
|
|
1598
|
+
let admittedTotal = 0;
|
|
1599
|
+
const born = [];
|
|
1600
|
+
const birthOutcomes = [];
|
|
1601
|
+
const timings = { spans: [], intents: 0, sessions: 0 };
|
|
1602
|
+
const summaryCtx = shardRouting && shardRouting.selfLabel && scopedReads(eng).length > 0 ? { reads: scopedReads(eng), prevs: /* @__PURE__ */ new Map(), values: /* @__PURE__ */ new Map(), events: [], rowsDelta: 0, rederived: /* @__PURE__ */ new Set(), rowsByHome: /* @__PURE__ */ new Map(), homeTags: /* @__PURE__ */ new Map(), homeKeySet: /* @__PURE__ */ new Set() } : null;
|
|
1603
|
+
if (summaryCtx) {
|
|
1604
|
+
try {
|
|
1605
|
+
for (const r of query(eng, ws, "aggregatesByType", JSON.stringify({ __type: "NomosHomeReceipt" }))) {
|
|
1606
|
+
const hk = r.data && typeof r.data.homeKey === "string" ? r.data.homeKey : null;
|
|
1607
|
+
if (!hk) continue;
|
|
1608
|
+
summaryCtx.homeKeySet.add(hk);
|
|
1609
|
+
summaryCtx.homeTags.set(await routeTagHexOfHomeKey(hk), hk);
|
|
1610
|
+
}
|
|
1611
|
+
} catch (e) {
|
|
1612
|
+
log("home-tag-table-error", { ws, error: String(e).slice(0, 200) });
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
const gitdir0 = gitdirOf(ws);
|
|
1616
|
+
const headBefore = summaryCtx ? kgit.resolveRef(eng, gitdir0, BRANCH) : null;
|
|
1617
|
+
const t0 = Date.now();
|
|
1618
|
+
let seq = 0;
|
|
1619
|
+
const span = (name, kind, depth = 1, extra = {}) => {
|
|
1620
|
+
const s0 = Date.now();
|
|
1621
|
+
return (end = {}) => timings.spans.push({ id: `intent-offer-${t0}-${seq++}`, track: "cloud", name, kind, depth, t0: s0, t1: Date.now(), ...extra, ...end });
|
|
1622
|
+
};
|
|
1623
|
+
for (const offer of Array.isArray(offers) ? offers : []) {
|
|
1624
|
+
const cid = typeof offer?.session === "string" && offer.session ? offer.session : "direct";
|
|
1625
|
+
const rec = sessions.get(cid) || { session: cid, admitted: [], rejected: [], skipped: [] };
|
|
1626
|
+
sessions.set(cid, rec);
|
|
1627
|
+
const done = span(`intent offer ${cid.slice(0, 14)}`, "cadmit", 1, { client: cid });
|
|
1628
|
+
let blob = offer?.blob instanceof Uint8Array ? offer.blob : null;
|
|
1629
|
+
try {
|
|
1630
|
+
if (!blob && typeof offer?.changeB64 === "string") blob = Uint8Array.from(atob(offer.changeB64), (c) => c.charCodeAt(0));
|
|
1631
|
+
const maxOfferBytes = offer?.staged ? 64 * 1024 * 1024 : 32 * 1024 * 1024;
|
|
1632
|
+
if (!blob || blob.byteLength === 0 || blob.byteLength > maxOfferBytes) {
|
|
1633
|
+
rec.rejected.push({ oid: String(offer?.oid || "").slice(0, 10), error: `intent offer must carry changeB64 <= ${maxOfferBytes / (1024 * 1024)} MiB` });
|
|
1634
|
+
continue;
|
|
1635
|
+
}
|
|
1636
|
+
const doc = offer?.intent ?? kgit.inspectChange(eng, blob);
|
|
1637
|
+
const intentId = typeof doc?.id === "string" ? doc.id : null;
|
|
1638
|
+
const dom = typeof doc?.payload?.domain === "string" ? doc.payload.domain : null;
|
|
1639
|
+
const dirId = typeof doc?.payload?.directiveId === "string" ? doc.payload.directiveId : null;
|
|
1640
|
+
const oid = String(offer?.oid || intentId || "").slice(0, 10);
|
|
1641
|
+
if (!dom) {
|
|
1642
|
+
rec.rejected.push({ oid, error: "non-authored intent \u2014 governance enters its own admin lane" });
|
|
1643
|
+
continue;
|
|
1644
|
+
}
|
|
1645
|
+
if (receiptFence && dirId && Array.isArray(receiptFence[dom]) && receiptFence[dom].includes(dirId)) {
|
|
1646
|
+
const error = `'${dom}/${dirId}' is a capability RECEIPT \u2014 receipts are executor/owner writes, never open-session writes. Author it via POST /v1/workspaces/${ws}/author (owner Bearer), or \u2014 if this parked receipt is sanctioned \u2014 the owner unjams it: POST /v1/workspaces/${ws}/dead-letters/retry`;
|
|
1647
|
+
rec.rejected.push({ oid, error, deadLettered: true });
|
|
1648
|
+
deadLetters.push({ intentId, oid, session: cid, error, blob, domain: dom, directiveId: dirId });
|
|
1649
|
+
continue;
|
|
1650
|
+
}
|
|
1651
|
+
if (intentId && main.ids.has(intentId)) {
|
|
1652
|
+
rec.skipped.push({ oid, intent: intentId.slice(0, 12), alreadyOnMain: true });
|
|
1653
|
+
continue;
|
|
1654
|
+
}
|
|
1655
|
+
const cap = summaryCtx ? beginSummaryCapture(eng, ws, summaryCtx, doc) : null;
|
|
1656
|
+
const _tOffer = Date.now();
|
|
1657
|
+
const res = offerAdmit(eng, ws, blob, { defer: false });
|
|
1658
|
+
log("offer-admit-ms", { ws, ms: Date.now() - _tOffer, deferred: false, ok: res.ok });
|
|
1659
|
+
if (res.ok) {
|
|
1660
|
+
if (intentId) main.ids.add(intentId);
|
|
1661
|
+
main.oids.add(res.head);
|
|
1662
|
+
main.head = res.head;
|
|
1663
|
+
rec.admitted.push({ oid, head: res.head });
|
|
1664
|
+
admittedTotal += 1;
|
|
1665
|
+
if (Array.isArray(res.born) && res.born.length) born.push(...res.born);
|
|
1666
|
+
if (Array.isArray(res.birthOutcomes) && res.birthOutcomes.length) birthOutcomes.push(...res.birthOutcomes);
|
|
1667
|
+
if (typeof process !== "undefined" && process.env?.NOMOS_TEST_DIAGNOSTICS === "1" && Array.isArray(res.birthOutcomes) && res.birthOutcomes.length) {
|
|
1668
|
+
log("offer-birth-outcomes", { ws, outcomes: res.birthOutcomes });
|
|
1669
|
+
}
|
|
1670
|
+
if (cap) finishSummaryCapture(eng, ws, summaryCtx, cap, res.head ?? "", intentId);
|
|
1671
|
+
} else {
|
|
1672
|
+
if (typeof process !== "undefined" && process.env?.NOMOS_TEST_DIAGNOSTICS === "1") {
|
|
1673
|
+
log("offer-admit-refused", {
|
|
1674
|
+
ws,
|
|
1675
|
+
domain: dom,
|
|
1676
|
+
directiveId: dirId,
|
|
1677
|
+
error: String(res.error || "").slice(0, 2e3)
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1680
|
+
const error = `${String(res.error || "").slice(0, 300)} \u2014 dead-lettered; fix the law (or the payload), then POST /v1/workspaces/${ws}/dead-letters/retry`;
|
|
1681
|
+
rec.rejected.push({ oid, error, deadLettered: true });
|
|
1682
|
+
deadLetters.push({ intentId, oid, session: cid, error, blob, domain: dom, directiveId: dirId });
|
|
1683
|
+
}
|
|
1684
|
+
} catch (e) {
|
|
1685
|
+
if (typeof process !== "undefined" && process.env?.NOMOS_TEST_DIAGNOSTICS === "1") {
|
|
1686
|
+
log("offer-admit-threw", {
|
|
1687
|
+
ws,
|
|
1688
|
+
error: String(e).slice(0, 2e3)
|
|
1689
|
+
});
|
|
1690
|
+
}
|
|
1691
|
+
rec.rejected.push({ oid: String(offer?.oid || "").slice(0, 10), error: String(e).slice(0, 200) });
|
|
1692
|
+
} finally {
|
|
1693
|
+
done();
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
timings.sessions = sessions.size;
|
|
1697
|
+
timings.intents = admittedTotal;
|
|
1698
|
+
if (deadLetters.length) {
|
|
1699
|
+
try {
|
|
1700
|
+
await materializeRefused(eng, ws, ledger, deadLetters);
|
|
1701
|
+
} catch (e) {
|
|
1702
|
+
log("refused-materialize-failed", { ws, error: String(e).slice(0, 200) });
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
if (admittedTotal) {
|
|
1706
|
+
const sealDone = span("seal offered intents", "cseal", 1, { admitted: admittedTotal });
|
|
1707
|
+
await commitAndPush(eng, ws, ledger);
|
|
1708
|
+
sealDone();
|
|
1709
|
+
}
|
|
1710
|
+
const gitdir = gitdirOf(ws);
|
|
1711
|
+
const head = kgit.resolveRef(eng, gitdir, BRANCH) ?? main.head;
|
|
1712
|
+
const summary = summaryCtx ? summaryOfCapture(summaryCtx, headBefore ?? "", head ?? "") : null;
|
|
1713
|
+
let resultPackB64 = null;
|
|
1714
|
+
if (admittedTotal && head && /^[0-9a-f]{40}$/i.test(clientBase || "") && clientBase !== head) {
|
|
1715
|
+
try {
|
|
1716
|
+
const p = servePack(eng, ws, clientBase ?? "");
|
|
1717
|
+
if (p && p.packB64 && p.bytes && p.bytes <= RESULT_PACK_INLINE_MAX) resultPackB64 = p.packB64;
|
|
1718
|
+
} catch {
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
log("admit-intent-offers", { ws, sessions: sessions.size, admitted: admittedTotal, rejected: [...sessions.values()].reduce((n, s) => n + s.rejected.length, 0), resultPack: resultPackB64 ? "inline" : "none" });
|
|
1722
|
+
const bornPacked = born.length ? packBornChildren(eng, born) : born;
|
|
1723
|
+
return { sessions: [...sessions.values()].map((s) => ({ ...s, ...s.skipped.length ? {} : { skipped: void 0 } })), main: head, deadLetters, timings, summary: summary ?? null, born: bornPacked, birthOutcomes, ...resultPackB64 ? { resultPackB64, resultBase: clientBase } : {} };
|
|
1724
|
+
}
|
|
1725
|
+
async function checkpointStateHash(eng, ws) {
|
|
1726
|
+
const rows = query(eng, ws, "aggregatesByType", JSON.stringify({ __type: "NomosSummarySubtotal" }));
|
|
1727
|
+
const canon = rows.map((r) => {
|
|
1728
|
+
const d = r.data || {};
|
|
1729
|
+
return { id: r.id, readId: d.readId, group: d.group, shard: d.shard, kind: d.kind, value: d.value, frontier: d.frontier };
|
|
1730
|
+
}).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
1731
|
+
return sha256hex(JSON.stringify(canon));
|
|
1732
|
+
}
|
|
1733
|
+
async function authorOn(eng, ws, ledger, domain, directiveId, payload, lawHash, opts = {}) {
|
|
1734
|
+
await mountWorkspace(eng, ws, ledger);
|
|
1735
|
+
let res;
|
|
1736
|
+
try {
|
|
1737
|
+
res = author(eng, ws, domain, directiveId, payload, lawHash, opts);
|
|
1738
|
+
} catch (e) {
|
|
1739
|
+
return { ok: false, error: String(e?.message || e).slice(0, 500) };
|
|
1740
|
+
}
|
|
1741
|
+
if (res && res.ok === false) return { ok: false, error: String(res.error || "the law refused this intent").slice(0, 500) };
|
|
1742
|
+
await commitAndPush(eng, ws, ledger);
|
|
1743
|
+
const bornPacked = Array.isArray(res.born) && res.born.length ? packBornChildren(eng, res.born) : res.born;
|
|
1744
|
+
return { ok: true, head: res.head, born: bornPacked ?? [], birthOutcomes: res.birthOutcomes ?? [] };
|
|
1745
|
+
}
|
|
1746
|
+
async function deepVerifyShard(eng, shardWs, shardLedger, coordinatorRows) {
|
|
1747
|
+
const replay = await verifyChain(eng, shardWs, shardLedger);
|
|
1748
|
+
if (!replay.valid) {
|
|
1749
|
+
return { verdict: `invalid:${replay.check || "replay"}`, replay, checks: [] };
|
|
1750
|
+
}
|
|
1751
|
+
await mountWorkspace(eng, shardWs, shardLedger);
|
|
1752
|
+
const checks = [];
|
|
1753
|
+
let allMatch = true;
|
|
1754
|
+
const heldHomes = coordinatorRows.map((row) => row.data || row).filter((d) => d.readId === NOMOS_SHARD_ROWS_READ && typeof d.group === "string" && d.group !== "").map((d) => d.group);
|
|
1755
|
+
const byHome = heldHomes.length ? await countTenantRowsByHome(eng, shardWs, heldHomes) : /* @__PURE__ */ new Map();
|
|
1756
|
+
for (const row of coordinatorRows) {
|
|
1757
|
+
const d = row.data || row;
|
|
1758
|
+
if (typeof d.readId !== "string") continue;
|
|
1759
|
+
const group = d.group ?? "";
|
|
1760
|
+
if (d.kind === "min" || d.kind === "max") {
|
|
1761
|
+
const heldVal = d.empty === 1 || typeof d.value !== "number" ? null : d.value;
|
|
1762
|
+
const recomputed2 = extremum(eng, shardWs, d.readId, d.kind, group).value;
|
|
1763
|
+
const match2 = recomputed2 === heldVal;
|
|
1764
|
+
if (!match2) allMatch = false;
|
|
1765
|
+
checks.push({ readId: d.readId, group, kind: d.kind, coordinator: heldVal, shard: recomputed2, match: match2 });
|
|
1766
|
+
continue;
|
|
1767
|
+
}
|
|
1768
|
+
let recomputed;
|
|
1769
|
+
if (d.readId === NOMOS_SHARD_ROWS_READ) {
|
|
1770
|
+
recomputed = group === "" ? countTenantRows(eng, shardWs) : byHome.get(group) ?? 0;
|
|
1771
|
+
} else if (d.kind === "sum") {
|
|
1772
|
+
recomputed = sum(eng, shardWs, d.readId, group).sum;
|
|
1773
|
+
} else {
|
|
1774
|
+
recomputed = count(eng, shardWs, d.readId, group).count;
|
|
1775
|
+
}
|
|
1776
|
+
const match = recomputed === d.value;
|
|
1777
|
+
if (!match) allMatch = false;
|
|
1778
|
+
checks.push({ readId: d.readId, group, coordinator: d.value, shard: recomputed, match });
|
|
1779
|
+
}
|
|
1780
|
+
const head = kgit.resolveRef(eng, gitdirOf(shardWs), BRANCH);
|
|
1781
|
+
return {
|
|
1782
|
+
verdict: allMatch ? "verified" : "mismatch",
|
|
1783
|
+
head,
|
|
1784
|
+
intents: replay.intents,
|
|
1785
|
+
plansRerun: replay.plansRerun,
|
|
1786
|
+
checks
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1789
|
+
function stageWorkspaceDir(eng, ws) {
|
|
1790
|
+
const wsContents = /* @__PURE__ */ new Map();
|
|
1791
|
+
dirOf(eng.preopen.dir.contents.get("ws")).contents.set(ws, new Directory(wsContents));
|
|
1792
|
+
}
|
|
1793
|
+
async function mountWorkspace(eng, ws, ledger) {
|
|
1794
|
+
if (eng.mounted.has(ws)) return eng.mounted.get(ws);
|
|
1795
|
+
stageWorkspaceDir(eng, ws);
|
|
1796
|
+
const gitdir = gitdirOf(ws);
|
|
1797
|
+
let restored = false, remoteMain = null, restoreError = null;
|
|
1798
|
+
try {
|
|
1799
|
+
await custodySkeleton(eng, gitdir);
|
|
1800
|
+
remoteMain = await custodyFetch(eng, ws, ledger, { remoteRef: "refs/heads/main", writeRef: false });
|
|
1801
|
+
if (remoteMain) {
|
|
1802
|
+
const mounted = kgit.restoreMain(eng, ws, remoteMain);
|
|
1803
|
+
if (!mounted.verified || mounted.head !== remoteMain) {
|
|
1804
|
+
throw new Error(`kernel refused restored main ${remoteMain}: ${JSON.stringify(mounted)}`);
|
|
1805
|
+
}
|
|
1806
|
+
restored = true;
|
|
1807
|
+
}
|
|
1808
|
+
} catch (e) {
|
|
1809
|
+
restoreError = String(e?.stack || e).split("\n").slice(0, 5).join(" | ");
|
|
1810
|
+
}
|
|
1811
|
+
const m = { restored, remoteMain, restoreError };
|
|
1812
|
+
eng.mounted.set(ws, m);
|
|
1813
|
+
return m;
|
|
1814
|
+
}
|
|
1815
|
+
function assertAuthored(res, what) {
|
|
1816
|
+
if (!res || res.ok === false) throw new Error(`${what}: ${String(res && res.error || "law refused the intent").slice(0, 500)}`);
|
|
1817
|
+
return res;
|
|
1818
|
+
}
|
|
1819
|
+
async function mountEphemeralWorkspace(eng, ws, { domainHash = "", lawUsdz } = {}) {
|
|
1820
|
+
let m = eng.mounted.get(ws);
|
|
1821
|
+
if (!m) {
|
|
1822
|
+
stageWorkspaceDir(eng, ws);
|
|
1823
|
+
m = { restored: false, remoteMain: null, restoreError: null, ephemeral: true };
|
|
1824
|
+
eng.mounted.set(ws, m);
|
|
1825
|
+
}
|
|
1826
|
+
if (!nomosActive(eng, ws)) {
|
|
1827
|
+
assertAuthored(
|
|
1828
|
+
author(eng, ws, "bootstrap", "installDomain", closureInstallPayload(eng.hashes.nomos, eng.installedBy), "", { lawUsdz: eng.nomosLawUsdz, deferProjection: false, rngDraws: 8 }),
|
|
1829
|
+
`ephemeral workspace '${ws}' bootstrap`
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
if (domainHash && lawUsdz && qById(eng, ws, `domain-installation:${domainHash}`).length === 0) {
|
|
1833
|
+
assertAuthored(
|
|
1834
|
+
author(eng, ws, "nomos", "installDomain", closureInstallPayload(domainHash, eng.installedBy), eng.hashes.nomos, { lawUsdz, deferProjection: false, rngDraws: 8 }),
|
|
1835
|
+
`ephemeral workspace '${ws}' installDomain(${domainHash.slice(0, 12)})`
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
return m;
|
|
1839
|
+
}
|
|
1840
|
+
async function authorEphemeral(eng, ws, mountOpts, domain, directiveId, payload, lawHash, opts = {}) {
|
|
1841
|
+
await mountEphemeralWorkspace(eng, ws, mountOpts);
|
|
1842
|
+
return author(eng, ws, domain, directiveId, payload, lawHash, { deferProjection: false, ...opts });
|
|
1843
|
+
}
|
|
1844
|
+
async function queryEphemeral(eng, ws, mountOpts, queryId, paramsJson, principal = "", keys = []) {
|
|
1845
|
+
await mountEphemeralWorkspace(eng, ws, mountOpts);
|
|
1846
|
+
return query(eng, ws, queryId, paramsJson, principal, keys);
|
|
1847
|
+
}
|
|
1848
|
+
function unmount(eng, ws) {
|
|
1849
|
+
eng.mounted.delete(ws);
|
|
1850
|
+
eng.mainIntents.delete(ws);
|
|
1851
|
+
const wsRoot = dirOf(eng.preopen.dir.contents.get("ws"));
|
|
1852
|
+
if (wsRoot) wsRoot.contents.delete(ws);
|
|
1853
|
+
}
|
|
1854
|
+
function writeWork(eng, name, bytes) {
|
|
1855
|
+
eng.preopen.dir.contents.set(name, new File(bytes));
|
|
1856
|
+
}
|
|
1857
|
+
function stageLawClosure(eng, lawUsdz, label = "candidate-law") {
|
|
1858
|
+
const name = `${label.replace(/[^A-Za-z0-9._-]/g, "_")}.law.usdz`;
|
|
1859
|
+
writeWork(eng, name, lawUsdz);
|
|
1860
|
+
return custodyProtoCase(eng, {
|
|
1861
|
+
case: "lawClosureInfo",
|
|
1862
|
+
value: create(LawClosureInfoRequestSchema, { closureFile: `/work/${name}` })
|
|
1863
|
+
}, "lawClosureInfo");
|
|
1864
|
+
}
|
|
1865
|
+
function currentLaw(eng, ws) {
|
|
1866
|
+
const out2 = namedQueryProto(eng, ws, QueryOperation.CURRENT_LAW);
|
|
1867
|
+
return out2.keyMap || {};
|
|
1868
|
+
}
|
|
1869
|
+
function installedLaw(eng, ws) {
|
|
1870
|
+
return namedQueryProto(eng, ws, QueryOperation.INSTALLED_LAW);
|
|
1871
|
+
}
|
|
1872
|
+
function sceneLaw(eng, ws) {
|
|
1873
|
+
return namedQueryProto(eng, ws, QueryOperation.SCENE_LAW);
|
|
1874
|
+
}
|
|
1875
|
+
function kernelStamp(eng, ws) {
|
|
1876
|
+
return namedQueryProto(eng, ws, QueryOperation.KERNEL_STAMP);
|
|
1877
|
+
}
|
|
1878
|
+
function declaredCapabilities(eng, ws) {
|
|
1879
|
+
const out2 = namedQueryProto(eng, ws, QueryOperation.DECLARED_CAPABILITIES);
|
|
1880
|
+
return out2.capabilities || [];
|
|
1881
|
+
}
|
|
1882
|
+
function reactorScan(eng, ws) {
|
|
1883
|
+
const response = callProto(eng.ex, {
|
|
1884
|
+
case: "outbox",
|
|
1885
|
+
value: create(OutboxRequestSchema, { target: protoTarget(ws) })
|
|
1886
|
+
}, eng.STDERR);
|
|
1887
|
+
if (response.outcome.case !== "outbox") {
|
|
1888
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for outbox request`);
|
|
1889
|
+
}
|
|
1890
|
+
return jsStruct(response.outcome.value.result);
|
|
1891
|
+
}
|
|
1892
|
+
function evolveDryRun(eng, ws, lawUsdz, domainHash, dispositions = null) {
|
|
1893
|
+
const before = currentLaw(eng, ws);
|
|
1894
|
+
const tenantHashes = [...new Set(Object.values(before).filter(
|
|
1895
|
+
(hash) => typeof hash === "string" && hash !== eng.hashes.bootstrap && hash !== eng.hashes.nomos
|
|
1896
|
+
))];
|
|
1897
|
+
const upgrade = tenantHashes.length > 0;
|
|
1898
|
+
const supersedes = upgrade && tenantHashes.length === 1 ? tenantHashes[0] : void 0;
|
|
1899
|
+
if (upgrade && supersedes === void 0) {
|
|
1900
|
+
return { admits: false, detail: `deploy-predecessor-ambiguous: workspace serves ${tenantHashes.length} business models` };
|
|
1901
|
+
}
|
|
1902
|
+
const payload = closureInstallPayload(domainHash, eng.installedBy, {
|
|
1903
|
+
...supersedes ? { supersedes } : {},
|
|
1904
|
+
...!upgrade && dispositions ? { dispositions } : {}
|
|
1905
|
+
});
|
|
1906
|
+
const r = author(eng, ws, "nomos", upgrade ? "stageDomain" : "installDomain", payload, eng.hashes.nomos, {
|
|
1907
|
+
lawUsdz,
|
|
1908
|
+
dryRun: true,
|
|
1909
|
+
deferProjection: false
|
|
1910
|
+
});
|
|
1911
|
+
return r.ok ? { admits: true } : { admits: false, detail: r.error };
|
|
1912
|
+
}
|
|
1913
|
+
function mintId(eng, typeTag) {
|
|
1914
|
+
const out2 = namedQueryProto(eng, "root", QueryOperation.MINT, { typeTag, nowMillis: Date.now() });
|
|
1915
|
+
return out2.id;
|
|
1916
|
+
}
|
|
1917
|
+
function author(eng, ws, domain, directiveId, payload, controllerHash, opts = {}) {
|
|
1918
|
+
const seq = eng.seq++;
|
|
1919
|
+
const capPorts = { clock: { physical: Date.now(), logical: 0, replica: eng.replica }, rng: osEntropyBuffer(opts.rngDraws ?? 64) };
|
|
1920
|
+
const genesis = !controllerHash;
|
|
1921
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
1922
|
+
throw new Error(`directive ${domain}/${directiveId} payload must be an object`);
|
|
1923
|
+
}
|
|
1924
|
+
const defer = opts.deferProjection !== false;
|
|
1925
|
+
const offerOnce = () => {
|
|
1926
|
+
const response = callProto(eng.ex, {
|
|
1927
|
+
case: "offer",
|
|
1928
|
+
value: create(OfferRequestSchema, {
|
|
1929
|
+
target: protoTarget(ws),
|
|
1930
|
+
intent: {
|
|
1931
|
+
case: "call",
|
|
1932
|
+
value: create(DirectiveCallSchema, {
|
|
1933
|
+
domain,
|
|
1934
|
+
directive: directiveId,
|
|
1935
|
+
payload: protoStruct(payload)
|
|
1936
|
+
})
|
|
1937
|
+
},
|
|
1938
|
+
authoring: create(AuthoringOptionsSchema, {
|
|
1939
|
+
actor: opts.actor ?? "",
|
|
1940
|
+
authToken: opts.authToken ? enc3.encode(opts.authToken) : new Uint8Array(),
|
|
1941
|
+
authorSecret: opts.authorSecret ? bytesFromB64(opts.authorSecret) : new Uint8Array(),
|
|
1942
|
+
validFromEpoch: opts.validFromEpoch === void 0 ? void 0 : BigInt(opts.validFromEpoch),
|
|
1943
|
+
rng: capPorts.rng,
|
|
1944
|
+
deferProjection: !opts.dryRun && defer,
|
|
1945
|
+
spans: opts.spans ?? false,
|
|
1946
|
+
dryRun: opts.dryRun ?? false,
|
|
1947
|
+
sequence: BigInt(seq),
|
|
1948
|
+
clock: create(CapturedClockSchema, {
|
|
1949
|
+
physicalMillis: BigInt(capPorts.clock.physical),
|
|
1950
|
+
logical: capPorts.clock.logical,
|
|
1951
|
+
replica: BigInt(capPorts.clock.replica)
|
|
1952
|
+
})
|
|
1953
|
+
}),
|
|
1954
|
+
lawUsdz: opts.lawUsdz ?? new Uint8Array(),
|
|
1955
|
+
executionLawUsdz: genesis && domain === "bootstrap" && directiveId === "installDomain" ? eng.bootstrapLawUsdz : new Uint8Array(),
|
|
1956
|
+
controllerLawHash: genesis ? "" : controllerHash,
|
|
1957
|
+
conflictSnapshots: (opts.__nomosConflictSnapshots ?? []).map((snapshot2) => ({
|
|
1958
|
+
aggregateType: snapshot2.aggregateType,
|
|
1959
|
+
aggregateId: snapshot2.aggregateId,
|
|
1960
|
+
field: snapshot2.field,
|
|
1961
|
+
targetSchema: snapshot2.targetSchema,
|
|
1962
|
+
token: snapshot2.token
|
|
1963
|
+
}))
|
|
1964
|
+
})
|
|
1965
|
+
}, eng.STDERR);
|
|
1966
|
+
if (response.outcome.case !== "offer") {
|
|
1967
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for offer request`);
|
|
1968
|
+
}
|
|
1969
|
+
return offerResult(response.outcome.value);
|
|
1970
|
+
};
|
|
1971
|
+
const res = offerOnce();
|
|
1972
|
+
if (defer && res.ok) (eng.pendingProjection ??= /* @__PURE__ */ new Set()).add(ws);
|
|
1973
|
+
return res;
|
|
1974
|
+
}
|
|
1975
|
+
function setTestKRoot(eng, kRootPublicB64) {
|
|
1976
|
+
const response = callProto(eng.ex, {
|
|
1977
|
+
case: "test",
|
|
1978
|
+
value: create(TestRequestSchema, {
|
|
1979
|
+
operation: {
|
|
1980
|
+
case: "setRoot",
|
|
1981
|
+
value: create(SetTestRootRequestSchema, { publicKey: bytesFromB64(kRootPublicB64) })
|
|
1982
|
+
}
|
|
1983
|
+
})
|
|
1984
|
+
}, eng.STDERR);
|
|
1985
|
+
if (response.outcome.case !== "test") {
|
|
1986
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for test control`);
|
|
1987
|
+
}
|
|
1988
|
+
return { ok: true };
|
|
1989
|
+
}
|
|
1990
|
+
function refreshProjection(eng, ws) {
|
|
1991
|
+
return namedQueryProto(eng, ws, QueryOperation.REFRESH, {}, { spans: true });
|
|
1992
|
+
}
|
|
1993
|
+
function flushDeferredProjections(eng) {
|
|
1994
|
+
for (const ws of eng.pendingProjection ?? []) {
|
|
1995
|
+
const _t = Date.now();
|
|
1996
|
+
let diagnostics = null;
|
|
1997
|
+
try {
|
|
1998
|
+
const refreshed = refreshProjection(eng, ws);
|
|
1999
|
+
diagnostics = { timingsUs: refreshed?.timingsUs ?? null, kernelSpans: refreshed?.kernelSpans ?? null };
|
|
2000
|
+
} catch {
|
|
2001
|
+
}
|
|
2002
|
+
const ms = Date.now() - _t;
|
|
2003
|
+
const debugPerf = typeof process !== "undefined" && !!process.env?.NOMOS_DEBUG_PERF;
|
|
2004
|
+
if (ms >= 100 || debugPerf) {
|
|
2005
|
+
log("flush-projection-ms", { ws, ms, ...diagnostics ? diagnostics : {} });
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
if (eng.pendingProjection) eng.pendingProjection.clear();
|
|
2009
|
+
}
|
|
2010
|
+
function exportCheckpoint(eng, ws) {
|
|
2011
|
+
const response = custodyProtoCase(eng, {
|
|
2012
|
+
case: "checkpointExport",
|
|
2013
|
+
value: create(CheckpointExportRequestSchema, {
|
|
2014
|
+
target: create(WorkspaceTargetSchema, { repo: repoArgOf(ws), workspace: ws, branch: BRANCH })
|
|
2015
|
+
})
|
|
2016
|
+
}, "checkpointExport");
|
|
2017
|
+
return {
|
|
2018
|
+
ok: true,
|
|
2019
|
+
empty: response.empty,
|
|
2020
|
+
...response.cursor ? { cursor: response.cursor } : {},
|
|
2021
|
+
...response.frontier.length ? { frontier: b64Bytes(response.frontier), bytes: response.frontier.length } : {},
|
|
2022
|
+
...response.stateRoot ? { stateRoot: response.stateRoot } : {},
|
|
2023
|
+
stateTree: response.stateTree,
|
|
2024
|
+
pinned: response.pinned,
|
|
2025
|
+
readIndexSnapshot: response.readIndexSnapshot,
|
|
2026
|
+
readIndexSnapshotPending: response.readIndexSnapshotPending,
|
|
2027
|
+
...response.readIndexSqliteBytes !== void 0 ? { readIndexSqliteBytes: Number(response.readIndexSqliteBytes) } : {},
|
|
2028
|
+
...response.readIndexCustodyBytes !== void 0 ? { readIndexCustodyBytes: Number(response.readIndexCustodyBytes) } : {}
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
function importCheckpoint(eng, ws, blobB64, frontierB64, stateRoot, spans = false, cursor = null) {
|
|
2032
|
+
const response = custodyProtoCase(eng, {
|
|
2033
|
+
case: "checkpointImport",
|
|
2034
|
+
value: create(CheckpointImportRequestSchema, {
|
|
2035
|
+
target: create(WorkspaceTargetSchema, { repo: repoArgOf(ws), workspace: ws, branch: BRANCH }),
|
|
2036
|
+
frontierSource: frontierB64 ? { case: "frontier", value: bytesFromB64(frontierB64) } : { case: void 0 },
|
|
2037
|
+
cursor: cursor || void 0,
|
|
2038
|
+
stateRoot: stateRoot || void 0,
|
|
2039
|
+
spans
|
|
2040
|
+
})
|
|
2041
|
+
}, "checkpointImport");
|
|
2042
|
+
return {
|
|
2043
|
+
ok: true,
|
|
2044
|
+
restored: response.restored,
|
|
2045
|
+
...response.reason ? { reason: response.reason } : {},
|
|
2046
|
+
frontierSeeded: response.frontierSeeded,
|
|
2047
|
+
frontierVerificationPending: response.frontierVerificationPending,
|
|
2048
|
+
aggregates: Number(response.aggregateCount),
|
|
2049
|
+
...response.spans ? { kernelSpans: jsStruct(response.spans) } : {},
|
|
2050
|
+
...response.cursor ? { cursor: response.cursor } : {},
|
|
2051
|
+
readOnly: response.readOnly,
|
|
2052
|
+
lazyReadIndex: response.lazyReadIndex
|
|
2053
|
+
};
|
|
2054
|
+
}
|
|
2055
|
+
function reserveKernelCapacity(eng, aggregateCount) {
|
|
2056
|
+
const response = custodyProtoCase(eng, {
|
|
2057
|
+
case: "capacityReserve",
|
|
2058
|
+
value: create(CapacityReserveRequestSchema, { aggregateCount: BigInt(aggregateCount) })
|
|
2059
|
+
}, "capacityReserve");
|
|
2060
|
+
return {
|
|
2061
|
+
ok: true,
|
|
2062
|
+
aggregateCount: Number(response.aggregateCount),
|
|
2063
|
+
reservedBytes: Number(response.reservedBytes)
|
|
2064
|
+
};
|
|
2065
|
+
}
|
|
2066
|
+
async function streamAll(stream) {
|
|
2067
|
+
const chunks = [];
|
|
2068
|
+
const reader = stream.getReader();
|
|
2069
|
+
for (; ; ) {
|
|
2070
|
+
const { done, value } = await reader.read();
|
|
2071
|
+
if (done) break;
|
|
2072
|
+
chunks.push(value);
|
|
2073
|
+
}
|
|
2074
|
+
let len = 0;
|
|
2075
|
+
for (const c of chunks) len += c.length;
|
|
2076
|
+
const out2 = new Uint8Array(len);
|
|
2077
|
+
let at = 0;
|
|
2078
|
+
for (const c of chunks) {
|
|
2079
|
+
out2.set(c, at);
|
|
2080
|
+
at += c.length;
|
|
2081
|
+
}
|
|
2082
|
+
return out2;
|
|
2083
|
+
}
|
|
2084
|
+
async function gzip(bytes) {
|
|
2085
|
+
const cs = new CompressionStream("gzip");
|
|
2086
|
+
return streamAll(new Response(Uint8Array.from(bytes).buffer).body.pipeThrough(cs));
|
|
2087
|
+
}
|
|
2088
|
+
async function gunzip(bytes) {
|
|
2089
|
+
const ds = new DecompressionStream("gzip");
|
|
2090
|
+
return streamAll(new Response(Uint8Array.from(bytes).buffer).body.pipeThrough(ds));
|
|
2091
|
+
}
|
|
2092
|
+
async function writeCheckpointObjects(eng, ws, ex, lawHash) {
|
|
2093
|
+
const gitdir = gitdirOf(ws);
|
|
2094
|
+
const files = [];
|
|
2095
|
+
let rawLen = 0, gzLen = 0;
|
|
2096
|
+
if (ex.blob) {
|
|
2097
|
+
const gz = await gzip(enc3.encode(ex.blob));
|
|
2098
|
+
rawLen = ex.blob.length;
|
|
2099
|
+
gzLen = gz.length;
|
|
2100
|
+
files.push({ path: "checkpoint", bytes: gz });
|
|
2101
|
+
}
|
|
2102
|
+
let fgzLen = 0;
|
|
2103
|
+
if (ex.frontier) {
|
|
2104
|
+
const fgz = await gzip(enc3.encode(ex.frontier));
|
|
2105
|
+
fgzLen = fgz.length;
|
|
2106
|
+
files.push({ path: "frontier", bytes: fgz });
|
|
2107
|
+
}
|
|
2108
|
+
files.push({ path: "meta", bytes: enc3.encode(JSON.stringify({ cursor: ex.cursor, bytes: ex.bytes ?? 0, lawHash, codec: "gzip", raw: rawLen, stored: gzLen, frontierStored: fgzLen, ...ex.stateRoot ? { stateRoot: ex.stateRoot } : {} })) });
|
|
2109
|
+
const ref = CKPT_REF(lawHash);
|
|
2110
|
+
const commitOid = kgit.writeMetaCommit(eng, gitdir, { parents: [], files, message: `checkpoint ${ws} @${String(ex.cursor).slice(0, 16)}`, timeSecs: 0, ref });
|
|
2111
|
+
return { ref, commitOid };
|
|
2112
|
+
}
|
|
2113
|
+
async function readCheckpointBlob(eng, ws, commitOid) {
|
|
2114
|
+
const gitdir = gitdirOf(ws);
|
|
2115
|
+
let codec = "gzip";
|
|
2116
|
+
let stateRoot = null;
|
|
2117
|
+
let cursor = null;
|
|
2118
|
+
try {
|
|
2119
|
+
const m = JSON.parse(dec3.decode(kgit.readBlob(eng, gitdir, commitOid, "meta") ?? new Uint8Array()));
|
|
2120
|
+
codec = m.codec ?? "gzip";
|
|
2121
|
+
stateRoot = m.stateRoot ?? null;
|
|
2122
|
+
cursor = m.cursor ?? null;
|
|
2123
|
+
} catch {
|
|
2124
|
+
}
|
|
2125
|
+
const dezip = async (b) => dec3.decode(codec === "gzip" ? await gunzip(b) : b);
|
|
2126
|
+
let blob = null;
|
|
2127
|
+
try {
|
|
2128
|
+
const b = kgit.readBlob(eng, gitdir, commitOid, "checkpoint");
|
|
2129
|
+
if (b) blob = await dezip(b);
|
|
2130
|
+
} catch {
|
|
2131
|
+
}
|
|
2132
|
+
let frontier = null;
|
|
2133
|
+
try {
|
|
2134
|
+
const f = kgit.readBlob(eng, gitdir, commitOid, "frontier");
|
|
2135
|
+
if (f) frontier = await dezip(f);
|
|
2136
|
+
} catch {
|
|
2137
|
+
}
|
|
2138
|
+
return { blob, frontier, stateRoot, cursor };
|
|
2139
|
+
}
|
|
2140
|
+
async function lawParity(eng, ws, lawHash) {
|
|
2141
|
+
if (lawHash) return lawHash;
|
|
2142
|
+
try {
|
|
2143
|
+
const map = currentLaw(eng, ws) || {};
|
|
2144
|
+
return await sha256hex(JSON.stringify(Object.entries(map).sort()));
|
|
2145
|
+
} catch {
|
|
2146
|
+
return null;
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
async function pushCheckpoint(eng, ws, ledger, lawHash) {
|
|
2150
|
+
try {
|
|
2151
|
+
lawHash = await lawParity(eng, ws, lawHash) ?? "";
|
|
2152
|
+
if (!lawHash) return { pushed: false, reason: "no-law" };
|
|
2153
|
+
const gitdir = gitdirOf(ws);
|
|
2154
|
+
const head = kgit.resolveRef(eng, gitdir, "refs/heads/main");
|
|
2155
|
+
eng._ckptPushed ??= /* @__PURE__ */ new Map();
|
|
2156
|
+
if (head && eng._ckptPushed.get(ws) === `${lawHash}:${head}`) {
|
|
2157
|
+
return { pushed: false, reason: "unchanged" };
|
|
2158
|
+
}
|
|
2159
|
+
const ex = exportCheckpoint(eng, ws);
|
|
2160
|
+
if (!ex || ex.empty || !ex.ok || !ex.blob) return { pushed: false, reason: ex && ex.empty ? "empty" : "no-blob" };
|
|
2161
|
+
const tag = `${lawHash}:${ex.cursor}`;
|
|
2162
|
+
if (eng._ckptPushed.get(ws) === tag) return { pushed: false, reason: "unchanged" };
|
|
2163
|
+
const { ref } = await writeCheckpointObjects(eng, ws, ex, lawHash);
|
|
2164
|
+
await custodyPush(eng, ws, ledger, { remoteRef: ref });
|
|
2165
|
+
eng._ckptPushed.set(ws, tag);
|
|
2166
|
+
return { pushed: true, cursor: ex.cursor, bytes: ex.bytes ?? 0 };
|
|
2167
|
+
} catch (e) {
|
|
2168
|
+
return { pushed: false, reason: String(e?.message || e).slice(0, 160) };
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
async function stageCheckpoint(eng, ws, lawHash) {
|
|
2172
|
+
try {
|
|
2173
|
+
lawHash = await lawParity(eng, ws, lawHash) ?? "";
|
|
2174
|
+
if (!lawHash) return null;
|
|
2175
|
+
eng._ckptPushed ??= /* @__PURE__ */ new Map();
|
|
2176
|
+
const ex = exportCheckpoint(eng, ws);
|
|
2177
|
+
if (!ex || ex.empty || !ex.ok || !ex.blob) return null;
|
|
2178
|
+
const tag = `${lawHash}:${ex.cursor}`;
|
|
2179
|
+
if (eng._ckptPushed.get(ws) === tag) return null;
|
|
2180
|
+
const { ref } = await writeCheckpointObjects(eng, ws, ex, lawHash);
|
|
2181
|
+
return { ref, tag, cursor: ex.cursor, bytes: ex.bytes ?? 0 };
|
|
2182
|
+
} catch {
|
|
2183
|
+
return null;
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
async function pushStagedCheckpoint(eng, ws, ledger, staged) {
|
|
2187
|
+
if (!staged || !staged.ref) return { pushed: false };
|
|
2188
|
+
await custodyPush(eng, ws, ledger, { remoteRef: staged.ref });
|
|
2189
|
+
(eng._ckptPushed ??= /* @__PURE__ */ new Map()).set(ws, staged.tag);
|
|
2190
|
+
return { pushed: true, cursor: staged.cursor, bytes: staged.bytes };
|
|
2191
|
+
}
|
|
2192
|
+
async function clearCheckpointRefs(ledger) {
|
|
2193
|
+
const headers = ledger.headers || {};
|
|
2194
|
+
const refs = await lsRefs(ledger.remote, headers, { service: "git-receive-pack", prefix: "refs/meta/checkpoint/" });
|
|
2195
|
+
const deleted = [];
|
|
2196
|
+
for (const ref of Object.keys(refs)) {
|
|
2197
|
+
try {
|
|
2198
|
+
await pushVia(ledger, () => pushPack(ledger.remote, headers, { updates: [{ ref, oldOid: refs[ref], newOid: ZERO_OID }] }));
|
|
2199
|
+
deleted.push(ref);
|
|
2200
|
+
} catch {
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
return deleted;
|
|
2204
|
+
}
|
|
2205
|
+
async function restoreCheckpointFromCustody(eng, ws, ledger, lawHash) {
|
|
2206
|
+
try {
|
|
2207
|
+
const mounted = eng.mounted.get(ws);
|
|
2208
|
+
if (mounted?.checkpoint?.restored) {
|
|
2209
|
+
return { restored: false, reason: "already-mounted-checkpoint" };
|
|
2210
|
+
}
|
|
2211
|
+
lawHash = await lawParity(eng, ws, lawHash) ?? "";
|
|
2212
|
+
if (!lawHash) return { restored: false, reason: "no-law" };
|
|
2213
|
+
const ref = CKPT_REF(lawHash);
|
|
2214
|
+
const serverRefs = await custodyLsRefs(ledger, ref);
|
|
2215
|
+
const foundOid = serverRefs[ref];
|
|
2216
|
+
if (!foundOid) return { restored: false, reason: "absent" };
|
|
2217
|
+
await custodyFetch(eng, ws, ledger, { remoteRef: ref });
|
|
2218
|
+
const { blob, frontier, stateRoot, cursor } = await readCheckpointBlob(eng, ws, foundOid);
|
|
2219
|
+
const r = importCheckpoint(eng, ws, blob, frontier, stateRoot, false, cursor);
|
|
2220
|
+
if (r && r.restored === true && r.cursor) {
|
|
2221
|
+
eng._ckptPushed ??= /* @__PURE__ */ new Map();
|
|
2222
|
+
eng._ckptPushed.set(ws, `${lawHash}:${r.cursor}`);
|
|
2223
|
+
}
|
|
2224
|
+
return { restored: r && r.restored === true, frontierSeeded: r && r.frontierSeeded === true, cursor: r && r.cursor, reason: r && r.reason };
|
|
2225
|
+
} catch (e) {
|
|
2226
|
+
return { restored: false, reason: String(e?.message || e).slice(0, 160) };
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
async function custodySkeleton(eng, gitdir) {
|
|
2230
|
+
const p = eng.fs.promises;
|
|
2231
|
+
for (const d of ["", "/objects", "/objects/pack", "/objects/info", "/refs", "/refs/heads"]) {
|
|
2232
|
+
try {
|
|
2233
|
+
await p.mkdir(`${gitdir}${d}`);
|
|
2234
|
+
} catch (e) {
|
|
2235
|
+
if (e?.code !== "EEXIST") throw e;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
try {
|
|
2239
|
+
await p.writeFile(`${gitdir}/HEAD`, `ref: refs/heads/${BRANCH}
|
|
2240
|
+
`);
|
|
2241
|
+
} catch {
|
|
2242
|
+
}
|
|
2243
|
+
try {
|
|
2244
|
+
await p.writeFile(`${gitdir}/config`, "[core]\n repositoryformatversion = 0\n bare = true\n");
|
|
2245
|
+
} catch {
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
async function custodyFetch(eng, ws, ledger, { remoteRef = "refs/heads/main", localRef = null, have = null, writeRef = true } = {}) {
|
|
2249
|
+
const remoteRefFull = fullRef(remoteRef);
|
|
2250
|
+
const refs = await custodyLsRefs(ledger, remoteRefFull);
|
|
2251
|
+
const tip = refs[remoteRefFull] || null;
|
|
2252
|
+
if (!tip) return null;
|
|
2253
|
+
if (tip !== have) {
|
|
2254
|
+
const pk = await fetchPack(ledger.remote, ledger.headers || {}, { wants: [tip], haves: have ? [have] : [] });
|
|
2255
|
+
if (pk) applyPackInto(eng, ws, pk, tip);
|
|
2256
|
+
}
|
|
2257
|
+
if (writeRef) kgit.writeRef(eng, gitdirOf(ws), fullRef(localRef || remoteRef), tip);
|
|
2258
|
+
return tip;
|
|
2259
|
+
}
|
|
2260
|
+
async function custodyPush(eng, ws, ledger, { localRef = null, remoteRef, del = false, pointer = false, newOid = null }) {
|
|
2261
|
+
const headers = ledger.headers || {};
|
|
2262
|
+
const remoteRefFull = fullRef(remoteRef);
|
|
2263
|
+
let remote;
|
|
2264
|
+
try {
|
|
2265
|
+
remote = await lsRefs(ledger.remote, headers, { service: "git-receive-pack", prefix: remoteRefFull });
|
|
2266
|
+
} catch (error) {
|
|
2267
|
+
throw new Error(`custody receive-pack advertisement failed for ${remoteRefFull}: ${String(error)}`, { cause: error });
|
|
2268
|
+
}
|
|
2269
|
+
const oldOid = remote[remoteRefFull] || ZERO_OID;
|
|
2270
|
+
if (del) {
|
|
2271
|
+
if (oldOid === ZERO_OID) return;
|
|
2272
|
+
return pushVia(ledger, () => pushPack(ledger.remote, headers, { updates: [{ ref: remoteRefFull, oldOid, newOid: ZERO_OID }] }));
|
|
2273
|
+
}
|
|
2274
|
+
const tgt = newOid || kgit.resolveRef(eng, gitdirOf(ws), fullRef(localRef || remoteRef));
|
|
2275
|
+
if (!tgt) throw new Error(`custodyPush: local ref ${localRef || remoteRef} unresolved`);
|
|
2276
|
+
if (tgt === oldOid) return;
|
|
2277
|
+
let pack = null;
|
|
2278
|
+
if (!pointer) {
|
|
2279
|
+
pack = oldOid !== ZERO_OID ? packDelta(eng, ws, oldOid, tgt) : null;
|
|
2280
|
+
if (!pack) pack = packDelta(eng, ws, "", tgt);
|
|
2281
|
+
}
|
|
2282
|
+
const packBytes = pack?.byteLength ?? 0;
|
|
2283
|
+
try {
|
|
2284
|
+
return await pushVia(ledger, () => pushPack(ledger.remote, headers, { updates: [{ ref: remoteRefFull, oldOid, newOid: tgt }], pack }));
|
|
2285
|
+
} catch (error) {
|
|
2286
|
+
throw new Error(`custody receive-pack push failed for ${remoteRefFull} (${packBytes} pack bytes): ${String(error)}`, { cause: error });
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
async function commitAndPush(eng, ws, ledger) {
|
|
2290
|
+
try {
|
|
2291
|
+
await custodyPush(eng, ws, ledger, { remoteRef: "refs/heads/main" });
|
|
2292
|
+
} catch (e) {
|
|
2293
|
+
unmount(eng, ws);
|
|
2294
|
+
const cause = e instanceof Error ? e.cause : void 0;
|
|
2295
|
+
const detail = cause === void 0 ? String(e) : `${e}; cause: ${String(cause)}`;
|
|
2296
|
+
throw new Error(`ledger push failed \u2014 write NOT durable, rolled back to ledger: ${detail}`, { cause: e });
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
async function pushShape(eng, ws, ledger) {
|
|
2300
|
+
try {
|
|
2301
|
+
const st = projectionStats(eng, ws);
|
|
2302
|
+
const bytes = st && (st.sqliteBytes ?? st.bytes);
|
|
2303
|
+
if (bytes == null) return;
|
|
2304
|
+
const gitdir = gitdirOf(ws);
|
|
2305
|
+
const head = kgit.resolveRef(eng, gitdir, "refs/heads/main");
|
|
2306
|
+
if (!head) return;
|
|
2307
|
+
const newRef = `refs/meta/shape/b${bytes}`;
|
|
2308
|
+
eng._lastShapeRef ??= /* @__PURE__ */ new Map();
|
|
2309
|
+
if (eng._lastShapeRef.get(ws) === newRef) return;
|
|
2310
|
+
kgit.writeRef(eng, gitdir, newRef, head);
|
|
2311
|
+
await custodyPush(eng, ws, ledger, { remoteRef: newRef, pointer: true });
|
|
2312
|
+
const prev = eng._lastShapeRef.get(ws);
|
|
2313
|
+
if (prev && prev !== newRef) {
|
|
2314
|
+
try {
|
|
2315
|
+
await custodyPush(eng, ws, ledger, { remoteRef: prev, del: true });
|
|
2316
|
+
} catch {
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
eng._lastShapeRef.set(ws, newRef);
|
|
2320
|
+
} catch {
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
async function readShape(ledger) {
|
|
2324
|
+
try {
|
|
2325
|
+
const refs = await custodyLsRefs(ledger, "refs/meta/shape/");
|
|
2326
|
+
let best = null;
|
|
2327
|
+
for (const ref of Object.keys(refs)) {
|
|
2328
|
+
const m = /refs\/meta\/shape\/b(\d+)$/.exec(ref);
|
|
2329
|
+
if (m) {
|
|
2330
|
+
const bytes = +m[1];
|
|
2331
|
+
if (!best || bytes > best.bytes) best = { bytes };
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
return best;
|
|
2335
|
+
} catch {
|
|
2336
|
+
return null;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
function describe(eng, ws) {
|
|
2340
|
+
return namedQueryProto(eng, ws, QueryOperation.DESCRIBE, { workspace: ws });
|
|
2341
|
+
}
|
|
2342
|
+
function packDelta(eng, ws, base, head) {
|
|
2343
|
+
try {
|
|
2344
|
+
return custodyProtoCase(eng, {
|
|
2345
|
+
case: "packDelta",
|
|
2346
|
+
value: create(PackDeltaRequestSchema, { repo: repoArgOf(ws), base: base || void 0, head })
|
|
2347
|
+
}, "packDelta").pack;
|
|
2348
|
+
} catch {
|
|
2349
|
+
return null;
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
function servePack(eng, ws, base = "") {
|
|
2353
|
+
let head = null;
|
|
2354
|
+
try {
|
|
2355
|
+
head = kgit.resolveRef(eng, gitdirOf(ws), BRANCH);
|
|
2356
|
+
} catch {
|
|
2357
|
+
}
|
|
2358
|
+
let r;
|
|
2359
|
+
try {
|
|
2360
|
+
const pack = custodyProtoCase(eng, {
|
|
2361
|
+
case: "packDelta",
|
|
2362
|
+
value: create(PackDeltaRequestSchema, { repo: repoArgOf(ws), base: base || void 0, branch: BRANCH })
|
|
2363
|
+
}, "packDelta").pack;
|
|
2364
|
+
r = { ok: true, packB64: b64Bytes(pack), bytes: pack.length };
|
|
2365
|
+
} catch (e) {
|
|
2366
|
+
const msg = String(e);
|
|
2367
|
+
if (/nothing to pack|head == base/.test(msg)) return { packB64: "", bytes: 0, upToDate: true, ...head ? { head } : {} };
|
|
2368
|
+
if (base && /reached root|before base|not an ancestor|request a full pack|not found|unknown|no (?:merge )?base|missing|invalid/i.test(msg)) {
|
|
2369
|
+
try {
|
|
2370
|
+
const pack = custodyProtoCase(eng, {
|
|
2371
|
+
case: "packDelta",
|
|
2372
|
+
value: create(PackDeltaRequestSchema, { repo: repoArgOf(ws), branch: BRANCH })
|
|
2373
|
+
}, "packDelta").pack;
|
|
2374
|
+
const full = { ok: true, packB64: b64Bytes(pack), bytes: pack.length };
|
|
2375
|
+
if (full && full.ok === true && typeof full.packB64 === "string") {
|
|
2376
|
+
return { packB64: full.packB64, bytes: full.bytes, divergent: true, ...head ? { head } : {} };
|
|
2377
|
+
}
|
|
2378
|
+
} catch {
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
throw e;
|
|
2382
|
+
}
|
|
2383
|
+
if (!r || r.ok !== true || typeof r.packB64 !== "string") throw new Error("servePack: kernel produced no pack");
|
|
2384
|
+
return { packB64: r.packB64, bytes: r.bytes, ...head ? { head } : {} };
|
|
2385
|
+
}
|
|
2386
|
+
function packBornChildren(eng, born) {
|
|
2387
|
+
if (!Array.isArray(born) || !born.length) return born;
|
|
2388
|
+
return born.map((b) => {
|
|
2389
|
+
const child = b && typeof b.workspace === "string" ? b.workspace : null;
|
|
2390
|
+
const head = b && typeof b.head === "string" ? b.head : null;
|
|
2391
|
+
if (!child || !/^[0-9a-f]{40}$/i.test(head || "")) {
|
|
2392
|
+
log("born-pack-skipped", { workspace: child, head, reason: "malformed born entry" });
|
|
2393
|
+
return b;
|
|
2394
|
+
}
|
|
2395
|
+
try {
|
|
2396
|
+
const pack = packDelta(eng, child, "", head);
|
|
2397
|
+
if (!pack || !pack.length) {
|
|
2398
|
+
log("born-pack-empty", { workspace: child, head });
|
|
2399
|
+
return b;
|
|
2400
|
+
}
|
|
2401
|
+
return { ...b, packB64: b64Bytes(pack), packBytes: pack.length };
|
|
2402
|
+
} catch (e) {
|
|
2403
|
+
log("born-pack-failed", { workspace: child, head, error: String(e).slice(0, 200) });
|
|
2404
|
+
return b;
|
|
2405
|
+
}
|
|
2406
|
+
});
|
|
2407
|
+
}
|
|
2408
|
+
function reconcileBornPacks(eng, children) {
|
|
2409
|
+
const born = [];
|
|
2410
|
+
const missing = [];
|
|
2411
|
+
for (const child of Array.isArray(children) ? children : []) {
|
|
2412
|
+
if (typeof child !== "string" || !child) continue;
|
|
2413
|
+
const head = kgit.resolveRef(eng, gitdirOf(child), BRANCH);
|
|
2414
|
+
if (!head || !/^[0-9a-f]{40}$/i.test(head)) {
|
|
2415
|
+
missing.push(child);
|
|
2416
|
+
continue;
|
|
2417
|
+
}
|
|
2418
|
+
const pack = packDelta(eng, child, "", head);
|
|
2419
|
+
if (!pack || !pack.length) {
|
|
2420
|
+
missing.push(child);
|
|
2421
|
+
continue;
|
|
2422
|
+
}
|
|
2423
|
+
born.push({ workspace: child, head, packB64: b64Bytes(pack), packBytes: pack.length });
|
|
2424
|
+
}
|
|
2425
|
+
return { born, missing };
|
|
2426
|
+
}
|
|
2427
|
+
async function ingestPackAsCustody(eng, ws, packBytes, head) {
|
|
2428
|
+
if (!packBytes || !packBytes.length) throw new Error(`ingestPackAsCustody: empty pack for '${ws}'`);
|
|
2429
|
+
if (!/^[0-9a-f]{40}$/i.test(head || "")) throw new Error(`ingestPackAsCustody: bad head '${head}' for '${ws}'`);
|
|
2430
|
+
unmount(eng, ws);
|
|
2431
|
+
stageWorkspaceDir(eng, ws);
|
|
2432
|
+
const gitdir = gitdirOf(ws);
|
|
2433
|
+
await custodySkeleton(eng, gitdir);
|
|
2434
|
+
applyPackInto(eng, ws, packBytes, head);
|
|
2435
|
+
const restored = kgit.restoreMain(eng, ws, head);
|
|
2436
|
+
if (!restored.verified || restored.head !== head) {
|
|
2437
|
+
throw new Error(`ingestPackAsCustody: kernel refused '${ws}' at ${head}`);
|
|
2438
|
+
}
|
|
2439
|
+
eng.mounted.set(ws, { restored: true, remoteMain: head, restoreError: null });
|
|
2440
|
+
return { ok: true, head: kgit.resolveRef(eng, gitdir, "refs/heads/main") };
|
|
2441
|
+
}
|
|
2442
|
+
function offerIntent(eng, ws, bytes, opts = {}) {
|
|
2443
|
+
const seq = eng.seq++;
|
|
2444
|
+
const deferProjection = !!(opts && opts.defer);
|
|
2445
|
+
const branch = opts && opts.branch || BRANCH;
|
|
2446
|
+
const response = callProto(eng.ex, {
|
|
2447
|
+
case: "offer",
|
|
2448
|
+
value: create(OfferRequestSchema, {
|
|
2449
|
+
target: protoTarget(ws, String(branch)),
|
|
2450
|
+
intent: { case: "sealedChangeUsda", value: bytes },
|
|
2451
|
+
authoring: create(AuthoringOptionsSchema, {
|
|
2452
|
+
sequence: BigInt(seq),
|
|
2453
|
+
deferProjection,
|
|
2454
|
+
spans: !!opts?.spans
|
|
2455
|
+
}),
|
|
2456
|
+
candidateCommit: typeof opts?.candidateCommit === "string" ? opts.candidateCommit : void 0
|
|
2457
|
+
})
|
|
2458
|
+
}, eng.STDERR);
|
|
2459
|
+
if (response.outcome.case !== "offer") {
|
|
2460
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for sealed offer request`);
|
|
2461
|
+
}
|
|
2462
|
+
return offerResult(response.outcome.value);
|
|
2463
|
+
}
|
|
2464
|
+
function offerAdmit(eng, ws, bytes, opts = {}) {
|
|
2465
|
+
return offerIntent(eng, ws, bytes, opts);
|
|
2466
|
+
}
|
|
2467
|
+
function applyIntentBytes(eng, ws, bytes, opts = {}) {
|
|
2468
|
+
return offerAdmit(eng, ws, bytes, opts);
|
|
2469
|
+
}
|
|
2470
|
+
async function mainIntentIds(eng, ws) {
|
|
2471
|
+
const gitdir = gitdirOf(ws);
|
|
2472
|
+
const head = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
2473
|
+
if (!head) return { head: null, ids: /* @__PURE__ */ new Set(), oids: /* @__PURE__ */ new Set() };
|
|
2474
|
+
const cached = eng.mainIntents.get(ws);
|
|
2475
|
+
if (cached && cached.head === head) return cached;
|
|
2476
|
+
const ids = /* @__PURE__ */ new Set(), oids = /* @__PURE__ */ new Set();
|
|
2477
|
+
for (const c of kgit.intentsAbove(eng, gitdir, head, "", 500)) {
|
|
2478
|
+
oids.add(c.oid);
|
|
2479
|
+
try {
|
|
2480
|
+
const id = c.id;
|
|
2481
|
+
if (typeof id === "string" && id) ids.add(id);
|
|
2482
|
+
} catch {
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
const m = { head, ids, oids };
|
|
2486
|
+
eng.mainIntents.set(ws, m);
|
|
2487
|
+
return m;
|
|
2488
|
+
}
|
|
2489
|
+
async function admitAll(eng, ws, ledger, { receiptFence = null, shardRouting = null, defer = false } = {}) {
|
|
2490
|
+
const routes = shardRouting ? directiveRoutes(eng) : null;
|
|
2491
|
+
const gitdir = gitdirOf(ws);
|
|
2492
|
+
const H = () => ({ ...ledger.headers || {} });
|
|
2493
|
+
const _t0 = Date.now();
|
|
2494
|
+
let _fetchMs = 0, _sealMs = 0, _intents = 0;
|
|
2495
|
+
const _spans = [];
|
|
2496
|
+
let _traceSeq = 0;
|
|
2497
|
+
const _span = (name, kind, depth = 1, extra = {}) => {
|
|
2498
|
+
const t0 = Date.now();
|
|
2499
|
+
return (end = {}) => {
|
|
2500
|
+
const t1 = Date.now();
|
|
2501
|
+
_spans.push({ id: `admit-${_t0}-${_traceSeq++}`, track: "cloud", name, kind, depth, t0, t1, ...extra, ...end });
|
|
2502
|
+
};
|
|
2503
|
+
};
|
|
2504
|
+
const sessionRefPrefix = "refs/heads/session/";
|
|
2505
|
+
const sessions = {};
|
|
2506
|
+
const _scanDone = _span("scan session refs", "cscan", 1);
|
|
2507
|
+
for (const [ref, oid] of Object.entries(await custodyLsRefs(ledger, sessionRefPrefix))) {
|
|
2508
|
+
if (ref.startsWith(sessionRefPrefix) && oid) sessions[ref.slice(sessionRefPrefix.length)] = oid;
|
|
2509
|
+
}
|
|
2510
|
+
_scanDone({ sessions: Object.keys(sessions).length });
|
|
2511
|
+
const _scanMs = Date.now() - _t0;
|
|
2512
|
+
const results = [], deadLetters = [], placements = [], splits = [], globalsOut = [];
|
|
2513
|
+
const consumed = [];
|
|
2514
|
+
let totalAdmitted = 0;
|
|
2515
|
+
const globalsDeclared = shardRouting && !shardRouting.selfLabel ? globalAggregates(eng) : null;
|
|
2516
|
+
const summaryCtx = shardRouting && shardRouting.selfLabel && scopedReads(eng).length > 0 ? { reads: scopedReads(eng), prevs: /* @__PURE__ */ new Map(), values: /* @__PURE__ */ new Map(), events: [], rowsDelta: 0, rederived: /* @__PURE__ */ new Set(), rowsByHome: /* @__PURE__ */ new Map(), homeTags: /* @__PURE__ */ new Map(), homeKeySet: /* @__PURE__ */ new Set() } : null;
|
|
2517
|
+
const canDeferProjection = !summaryCtx && !(globalsDeclared && globalsDeclared.size > 0);
|
|
2518
|
+
if (summaryCtx) {
|
|
2519
|
+
try {
|
|
2520
|
+
for (const r of query(eng, ws, "aggregatesByType", JSON.stringify({ __type: "NomosHomeReceipt" }))) {
|
|
2521
|
+
const hk = r.data && typeof r.data.homeKey === "string" ? r.data.homeKey : null;
|
|
2522
|
+
if (!hk) continue;
|
|
2523
|
+
summaryCtx.homeKeySet.add(hk);
|
|
2524
|
+
summaryCtx.homeTags.set(await routeTagHexOfHomeKey(hk), hk);
|
|
2525
|
+
}
|
|
2526
|
+
} catch (e) {
|
|
2527
|
+
log("home-tag-table-error", { ws, error: String(e).slice(0, 200) });
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
const headBefore = summaryCtx ? kgit.resolveRef(eng, gitdir, BRANCH) : null;
|
|
2531
|
+
for (const [cid, head] of Object.entries(sessions)) {
|
|
2532
|
+
const ref = `refs/heads/session/${cid}`;
|
|
2533
|
+
const shortCid = cid.length > 14 ? `${cid.slice(0, 14)}...` : cid;
|
|
2534
|
+
const _sessionDone = _span(`session ${shortCid}`, "csession", 1, { client: cid });
|
|
2535
|
+
try {
|
|
2536
|
+
const _fetchDone = _span(`fetch ${shortCid}`, "cfetch", 2, { client: cid });
|
|
2537
|
+
const _f = Date.now();
|
|
2538
|
+
try {
|
|
2539
|
+
const localMain = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
2540
|
+
try {
|
|
2541
|
+
await custodyFetch(eng, ws, ledger, { remoteRef: ref, have: localMain });
|
|
2542
|
+
} catch (thinErr) {
|
|
2543
|
+
log("thin-fetch-fallback", { ws, cid, error: String(thinErr?.message || thinErr).slice(0, 160) });
|
|
2544
|
+
await custodyFetch(eng, ws, ledger, { remoteRef: ref, have: null });
|
|
2545
|
+
}
|
|
2546
|
+
} finally {
|
|
2547
|
+
_fetchMs += Date.now() - _f;
|
|
2548
|
+
_fetchDone();
|
|
2549
|
+
}
|
|
2550
|
+
const _walkDone = _span(`walk ${shortCid}`, "cwalk", 2, { client: cid });
|
|
2551
|
+
const main = await mainIntentIds(eng, ws);
|
|
2552
|
+
const recent = kgit.intentsAbove(eng, gitdir, head ?? "", "", 100);
|
|
2553
|
+
const chain = [];
|
|
2554
|
+
for (let i = recent.length - 1; i >= 0; i--) {
|
|
2555
|
+
if (main.oids.has(recent[i].oid)) break;
|
|
2556
|
+
chain.push(recent[i]);
|
|
2557
|
+
}
|
|
2558
|
+
chain.reverse();
|
|
2559
|
+
_walkDone({ intents: chain.length });
|
|
2560
|
+
const admitted = [], rejected = [], skipped = [];
|
|
2561
|
+
const _gateDone = _span(`gate+fold ${shortCid}`, "cgate", 2, { client: cid, intents: chain.length });
|
|
2562
|
+
for (const c of chain) {
|
|
2563
|
+
const oid = c.oid;
|
|
2564
|
+
try {
|
|
2565
|
+
const blob = bytesFromB64(c.changeB64);
|
|
2566
|
+
const doc = c.intent;
|
|
2567
|
+
const intentId = typeof c.id === "string" ? c.id : null;
|
|
2568
|
+
const dom = typeof c.domain === "string" ? c.domain : null;
|
|
2569
|
+
const dirId = typeof c.directiveId === "string" ? c.directiveId : null;
|
|
2570
|
+
if (!dom) {
|
|
2571
|
+
rejected.push({ oid: oid.slice(0, 10), error: "non-authored intent \u2014 governance enters its own admin lane" });
|
|
2572
|
+
continue;
|
|
2573
|
+
}
|
|
2574
|
+
if (receiptFence && dirId && Array.isArray(receiptFence[dom]) && receiptFence[dom].includes(dirId)) {
|
|
2575
|
+
const error = `'${dom}/${dirId}' is a capability RECEIPT \u2014 receipts are executor/owner writes, never open-session writes. Author it via POST /v1/workspaces/${ws}/author (owner Bearer), or \u2014 if this parked receipt is sanctioned \u2014 the owner unjams it: POST /v1/workspaces/${ws}/dead-letters/retry`;
|
|
2576
|
+
rejected.push({ oid: oid.slice(0, 10), error, deadLettered: true });
|
|
2577
|
+
deadLetters.push({ intentId, oid: oid.slice(0, 10), session: cid, error, blob, domain: dom, directiveId: dirId });
|
|
2578
|
+
continue;
|
|
2579
|
+
}
|
|
2580
|
+
if (routes && dom && dirId) {
|
|
2581
|
+
if (dirId === "nomosSealHome" || dirId === "nomosSealHandoff") {
|
|
2582
|
+
rejected.push({ oid: oid.slice(0, 10), error: `session lane refuses '${dirId}' \u2014 the \xA76 handoff seals are authored by the adapter after migration verifies (begin a move with nomosSplitShard, or POST /v1/workspaces/<coordinator>/split)` });
|
|
2583
|
+
continue;
|
|
2584
|
+
}
|
|
2585
|
+
const route = routes.get(`${dom} ${dirId}`);
|
|
2586
|
+
if (route) {
|
|
2587
|
+
const payloadObj = doc?.payload?.payload ?? null;
|
|
2588
|
+
const verdict2 = await wrongHomeVerdict(shardRouting, route, payloadObj);
|
|
2589
|
+
if (verdict2) {
|
|
2590
|
+
rejected.push({ oid: oid.slice(0, 10), error: verdict2.error, ...verdict2.wrongHome ? { wrongHome: verdict2.wrongHome } : {}, ...verdict2.homeMoving ? { homeMoving: verdict2.homeMoving } : {}, ...verdict2.deadLettered ? { deadLettered: true } : {} });
|
|
2591
|
+
if (verdict2.deadLettered) deadLetters.push({ intentId, oid: oid.slice(0, 10), session: cid, error: verdict2.error, blob, domain: dom, directiveId: dirId });
|
|
2592
|
+
continue;
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
if (dirId === "nomosReceiveAssignment" && shardRouting) {
|
|
2596
|
+
const p = doc?.payload?.payload ?? null;
|
|
2597
|
+
const homeKey = p && typeof p.homeKey === "string" ? p.homeKey : null;
|
|
2598
|
+
const rows = homeKey ? await shardRouting.assignments() || [] : [];
|
|
2599
|
+
const a = homeKey ? rows.find((x) => x.homeKey === homeKey) : null;
|
|
2600
|
+
if (!a) {
|
|
2601
|
+
const error = `assignment receipt for home '${String(homeKey).slice(0, 80)}' has NO placement on the coordinator '${shardRouting.coordinatorWs}' \u2014 author the derived placement intent (birth<Type>) first, then POST /dead-letters/retry`;
|
|
2602
|
+
rejected.push({ oid: oid.slice(0, 10), error, deadLettered: true });
|
|
2603
|
+
deadLetters.push({ intentId, oid: oid.slice(0, 10), session: cid, error, blob, domain: dom, directiveId: dirId });
|
|
2604
|
+
continue;
|
|
2605
|
+
}
|
|
2606
|
+
if (a.shard !== shardRouting.selfLabel || p && p.shard !== shardRouting.selfLabel) {
|
|
2607
|
+
const correct = `${shardRouting.coordinatorWs}--${a.shard}`;
|
|
2608
|
+
rejected.push({
|
|
2609
|
+
oid: oid.slice(0, 10),
|
|
2610
|
+
error: `wrong-home: the coordinator's shard map assigns home '${homeKey.slice(0, 80)}' to '${correct}' (not this workspace) \u2014 a routed client re-routes and retries automatically`,
|
|
2611
|
+
wrongHome: { workspace: correct, ...a.mapVersion !== void 0 ? { mapVersion: a.mapVersion } : {} }
|
|
2612
|
+
});
|
|
2613
|
+
continue;
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
if (intentId && main.ids.has(intentId)) {
|
|
2618
|
+
skipped.push({ oid: oid.slice(0, 10), intent: intentId.slice(0, 12), alreadyOnMain: true });
|
|
2619
|
+
continue;
|
|
2620
|
+
}
|
|
2621
|
+
const cap = summaryCtx ? beginSummaryCapture(eng, ws, summaryCtx, doc) : null;
|
|
2622
|
+
const verdict = offerIntent(eng, ws, blob, {
|
|
2623
|
+
defer: canDeferProjection,
|
|
2624
|
+
// The session commit is inert custody. Passing its content address lets the kernel recover
|
|
2625
|
+
// typed auxiliary assets (notably a USDA law closure) bound by the sealed intent. The kernel
|
|
2626
|
+
// authenticates the closure and runs the same offer gate; the adapter interprets nothing.
|
|
2627
|
+
candidateCommit: oid
|
|
2628
|
+
});
|
|
2629
|
+
const res = verdict.outcome === "admitted" ? { ok: true, head: verdict.head } : { ok: false, error: verdict.error };
|
|
2630
|
+
if (res.ok) {
|
|
2631
|
+
if (intentId) main.ids.add(intentId);
|
|
2632
|
+
main.oids.add(res.head);
|
|
2633
|
+
main.head = res.head;
|
|
2634
|
+
admitted.push({ oid: oid.slice(0, 10), head: res.head });
|
|
2635
|
+
if (cap) finishSummaryCapture(eng, ws, summaryCtx, cap, res.head ?? "", intentId ?? "");
|
|
2636
|
+
if (shardRouting && dirId) {
|
|
2637
|
+
const placement = placementDirectives(eng).get(dirId);
|
|
2638
|
+
if (placement) {
|
|
2639
|
+
const p = doc?.payload?.payload ?? null;
|
|
2640
|
+
const homeKey = p ? p[String(placement.keyField)] : void 0;
|
|
2641
|
+
if (typeof homeKey === "string" && typeof p?.shard === "string") {
|
|
2642
|
+
placements.push({ directive: dirId, homeKey, shard: p.shard, mapVersion: 1 });
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
if (dirId === "nomosSplitShard" && !shardRouting.selfLabel) {
|
|
2646
|
+
const p = doc?.payload?.payload ?? null;
|
|
2647
|
+
if (p && typeof p.fromShard === "string" && typeof p.toShard === "string" && Array.isArray(p.homeKeys)) {
|
|
2648
|
+
splits.push({ fromShard: p.fromShard, toShard: p.toShard, homeKeys: p.homeKeys.filter((k) => typeof k === "string") });
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
if (globalsDeclared && globalsDeclared.size > 0) {
|
|
2653
|
+
let touchesGlobal = false;
|
|
2654
|
+
for (const ev of parseIntentEvents(doc)) {
|
|
2655
|
+
const rows = qById(eng, ws, ev.aggregate);
|
|
2656
|
+
const t = ev.sets.get("__type") ?? (rows.length ? rows[0].type : void 0);
|
|
2657
|
+
if (t !== void 0 && globalsDeclared.has(t)) {
|
|
2658
|
+
touchesGlobal = true;
|
|
2659
|
+
break;
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
if (touchesGlobal) globalsOut.push({ intentId: intentId || "", oid: oid.slice(0, 10), blob });
|
|
2663
|
+
}
|
|
2664
|
+
} else {
|
|
2665
|
+
const wh = String(res.error || "").match(/wrong-home:(s\d+)/);
|
|
2666
|
+
if (wh) {
|
|
2667
|
+
const coordinator = shardRouting && shardRouting.coordinatorWs || (ws.match(/^(.*)--s\d+$/) || [])[1] || ws;
|
|
2668
|
+
rejected.push({
|
|
2669
|
+
oid: oid.slice(0, 10),
|
|
2670
|
+
error: `wrong-home: this write's home is assigned to '${coordinator}--${wh[1]}' \u2014 the chain gate's homing invariant refused it; a routed client re-routes and retries automatically`,
|
|
2671
|
+
wrongHome: { workspace: `${coordinator}--${wh[1]}` }
|
|
2672
|
+
});
|
|
2673
|
+
continue;
|
|
2674
|
+
}
|
|
2675
|
+
const error = `${String(res.error || "").slice(0, 300)} \u2014 dead-lettered; fix the law (or the payload), then POST /v1/workspaces/${ws}/dead-letters/retry`;
|
|
2676
|
+
rejected.push({ oid: oid.slice(0, 10), error, deadLettered: true });
|
|
2677
|
+
deadLetters.push({ intentId, oid: oid.slice(0, 10), session: cid, error, blob, domain: dom, directiveId: dirId });
|
|
2678
|
+
}
|
|
2679
|
+
} catch (e) {
|
|
2680
|
+
rejected.push({ oid: oid.slice(0, 10), error: String(e).slice(0, 200) });
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
_gateDone({ admitted: admitted.length, rejected: rejected.length, skipped: skipped.length });
|
|
2684
|
+
_intents += admitted.length;
|
|
2685
|
+
totalAdmitted += admitted.length;
|
|
2686
|
+
consumed.push({ cid, ref });
|
|
2687
|
+
results.push({ session: cid, admitted, rejected, ...skipped.length ? { skipped } : {} });
|
|
2688
|
+
} catch (e) {
|
|
2689
|
+
results.push({ session: cid, error: String(e).slice(0, 200) });
|
|
2690
|
+
} finally {
|
|
2691
|
+
_sessionDone();
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
if (canDeferProjection && totalAdmitted) {
|
|
2695
|
+
const _projDone = _span("projection flush (batch)", "cproject", 1, { admitted: totalAdmitted });
|
|
2696
|
+
try {
|
|
2697
|
+
refreshProjection(eng, ws);
|
|
2698
|
+
} catch (e) {
|
|
2699
|
+
log("admit-projection-flush-failed", { ws, error: String(e).slice(0, 200) });
|
|
2700
|
+
} finally {
|
|
2701
|
+
_projDone();
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
let unparkedSessions = /* @__PURE__ */ new Set();
|
|
2705
|
+
if (deadLetters.length) {
|
|
2706
|
+
try {
|
|
2707
|
+
unparkedSessions = (await materializeRefused(eng, ws, ledger, deadLetters)).unparkedSessions;
|
|
2708
|
+
} catch (e) {
|
|
2709
|
+
unparkedSessions = new Set(deadLetters.map((dl) => dl.session).filter(Boolean));
|
|
2710
|
+
log("refused-materialize-failed", { ws, error: String(e).slice(0, 200) });
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
const prunable = unparkedSessions.size ? consumed.filter((c) => !unparkedSessions.has(c.cid)) : consumed;
|
|
2714
|
+
const hasCoordination = !!(summaryCtx || placements.length || splits.length || globalsOut.length);
|
|
2715
|
+
const deferDurability = defer && !hasCoordination;
|
|
2716
|
+
let _sealed = true;
|
|
2717
|
+
if (totalAdmitted && !deferDurability) {
|
|
2718
|
+
const _sealDone = _span(`seal (batch)`, "cseal", 1, { sessions: consumed.length, admitted: totalAdmitted });
|
|
2719
|
+
const _s = Date.now();
|
|
2720
|
+
try {
|
|
2721
|
+
await commitAndPush(eng, ws, ledger);
|
|
2722
|
+
} catch (e) {
|
|
2723
|
+
_sealed = false;
|
|
2724
|
+
log("admit-batch-push-failed", { ws, sessions: consumed.length, admitted: totalAdmitted, error: String(e).slice(0, 200) });
|
|
2725
|
+
} finally {
|
|
2726
|
+
_sealMs += Date.now() - _s;
|
|
2727
|
+
_sealDone();
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
if (_sealed && !deferDurability) {
|
|
2731
|
+
for (const { ref } of prunable) {
|
|
2732
|
+
try {
|
|
2733
|
+
await custodyPush(eng, ws, ledger, { remoteRef: ref, del: true });
|
|
2734
|
+
} catch {
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
const newMain = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
2739
|
+
log("admit", { ws, sessions: results.length, main: newMain });
|
|
2740
|
+
const summary = summaryCtx ? summaryOfCapture(summaryCtx, headBefore ?? "", newMain) : null;
|
|
2741
|
+
const _total = Date.now() - _t0;
|
|
2742
|
+
const timings = { totalMs: _total, scanMs: _scanMs, fetchMs: _fetchMs, sealMs: _sealMs, gateFoldMs: Math.max(0, _total - _scanMs - _fetchMs - _sealMs), intents: _intents, sessions: results.length, spans: _spans };
|
|
2743
|
+
return {
|
|
2744
|
+
sessions: results,
|
|
2745
|
+
main: newMain,
|
|
2746
|
+
deadLetters,
|
|
2747
|
+
timings,
|
|
2748
|
+
...summary ? { summary } : {},
|
|
2749
|
+
...placements.length ? { placements } : {},
|
|
2750
|
+
...splits.length ? { splits } : {},
|
|
2751
|
+
...globalsOut.length ? { globals: globalsOut } : {},
|
|
2752
|
+
// The adapter's backup lane consumes these: `deferred` ⇒ resident main carries totalAdmitted
|
|
2753
|
+
// un-backed-up commits and `consumed` are the session branches to delete AFTER the push lands.
|
|
2754
|
+
...deferDurability && totalAdmitted ? { deferred: true, consumed: prunable, admitted: totalAdmitted } : {}
|
|
2755
|
+
};
|
|
2756
|
+
}
|
|
2757
|
+
async function backupHead(eng, ws, ledger, head) {
|
|
2758
|
+
if (!eng.mounted.has(ws)) return { ok: false, error: "not mounted" };
|
|
2759
|
+
if (!head) return { ok: false, error: "no head" };
|
|
2760
|
+
try {
|
|
2761
|
+
await custodyPush(eng, ws, ledger, { remoteRef: "refs/heads/main", newOid: head });
|
|
2762
|
+
return { ok: true, head };
|
|
2763
|
+
} catch (e) {
|
|
2764
|
+
return { ok: false, error: String(e?.message || e).slice(0, 200), head };
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
async function backupToCustody(eng, ws, ledger, { consumed = [] } = {}) {
|
|
2768
|
+
if (!eng.mounted.has(ws)) return { ok: false, error: "not mounted" };
|
|
2769
|
+
const gitdir = gitdirOf(ws);
|
|
2770
|
+
let head = null;
|
|
2771
|
+
head = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
2772
|
+
if (!head) return { ok: false, error: "no local main" };
|
|
2773
|
+
try {
|
|
2774
|
+
await custodyPush(eng, ws, ledger, { remoteRef: "refs/heads/main" });
|
|
2775
|
+
} catch (e) {
|
|
2776
|
+
return { ok: false, error: String(e).slice(0, 200), head };
|
|
2777
|
+
}
|
|
2778
|
+
for (const { ref } of consumed) {
|
|
2779
|
+
try {
|
|
2780
|
+
await custodyPush(eng, ws, ledger, { remoteRef: ref, del: true });
|
|
2781
|
+
} catch {
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
return { ok: true, head };
|
|
2785
|
+
}
|
|
2786
|
+
async function verifyChain(eng, ws, ledger) {
|
|
2787
|
+
unmount(eng, ws);
|
|
2788
|
+
const m = await mountWorkspace(eng, ws, ledger);
|
|
2789
|
+
if (!m.restored) {
|
|
2790
|
+
return { valid: false, check: "mount", error: m.restoreError || "no refs/heads/main on the ledger \u2014 nothing to verify (push refs/heads/main to deliver a chain first)" };
|
|
2791
|
+
}
|
|
2792
|
+
try {
|
|
2793
|
+
return namedQueryProto(eng, ws, QueryOperation.VERIFY_CHAIN);
|
|
2794
|
+
} finally {
|
|
2795
|
+
unmount(eng, ws);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
function verifyChainLocal(eng, ws) {
|
|
2799
|
+
return namedQueryProto(eng, ws, QueryOperation.VERIFY_CHAIN);
|
|
2800
|
+
}
|
|
2801
|
+
function historyPreflight(eng, ws, domain, candidateHash, atHash, dispositions) {
|
|
2802
|
+
return namedQueryProto(eng, ws, QueryOperation.HISTORY_PREFLIGHT, {
|
|
2803
|
+
domain,
|
|
2804
|
+
candidateHash,
|
|
2805
|
+
atHash,
|
|
2806
|
+
...dispositions ? { dispositions } : {}
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
function historyRestorePreflight(eng, ws, domain, currentHash, priorHash, atHash, actor) {
|
|
2810
|
+
return namedQueryProto(eng, ws, QueryOperation.HISTORY_PREFLIGHT, {
|
|
2811
|
+
domain,
|
|
2812
|
+
candidateHash: priorHash,
|
|
2813
|
+
atHash,
|
|
2814
|
+
restorePreviousOf: currentHash,
|
|
2815
|
+
ackBy: actor
|
|
2816
|
+
});
|
|
2817
|
+
}
|
|
2818
|
+
function promotePreflighted(eng, ws, domain, candidateHash, opts = {}) {
|
|
2819
|
+
const actingPrincipal = opts.actor?.trim() || String(eng.installedBy || "").trim();
|
|
2820
|
+
if (!actingPrincipal && !opts.authToken) {
|
|
2821
|
+
return {
|
|
2822
|
+
ok: false,
|
|
2823
|
+
stage: "identity",
|
|
2824
|
+
error: "promotion needs the stateful client's current principal so its business decision is attributable"
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
const atHash = kgit.resolveRef(eng, gitdirOf(ws), BRANCH);
|
|
2828
|
+
if (!atHash) {
|
|
2829
|
+
return { ok: false, stage: "preflight", error: "workspace has no history to prove" };
|
|
2830
|
+
}
|
|
2831
|
+
let report;
|
|
2832
|
+
try {
|
|
2833
|
+
report = historyPreflight(eng, ws, domain, candidateHash, atHash, opts.dispositions);
|
|
2834
|
+
} catch (error) {
|
|
2835
|
+
return { ok: false, stage: "preflight", error: String(error?.message || error) };
|
|
2836
|
+
}
|
|
2837
|
+
const prepared = prepareManagedPromotion(report, candidateHash, domain, opts);
|
|
2838
|
+
if (!prepared.ok) return prepared;
|
|
2839
|
+
const {
|
|
2840
|
+
replaces: _replaces,
|
|
2841
|
+
retireReplaced: _retireReplaced,
|
|
2842
|
+
dispositions: _dispositions,
|
|
2843
|
+
acceptanceReason: _acceptance,
|
|
2844
|
+
...authorOpts
|
|
2845
|
+
} = opts;
|
|
2846
|
+
const result = author(eng, ws, "nomos", "promoteDomain", prepared.payload, eng.hashes.nomos, {
|
|
2847
|
+
...authorOpts,
|
|
2848
|
+
...actingPrincipal ? { actor: actingPrincipal } : {}
|
|
2849
|
+
});
|
|
2850
|
+
return result.ok ? { ...result, stage: "promoted", report, receiptId: prepared.receiptId } : { ...result, stage: "admission", report, receiptId: prepared.receiptId };
|
|
2851
|
+
}
|
|
2852
|
+
function restorePreviousPreflighted(eng, ws, domain, currentHash, opts = {}) {
|
|
2853
|
+
const actingPrincipal = opts.actor?.trim() || String(eng.installedBy || "").trim();
|
|
2854
|
+
if (!actingPrincipal) {
|
|
2855
|
+
return {
|
|
2856
|
+
ok: false,
|
|
2857
|
+
stage: "identity",
|
|
2858
|
+
error: "model restoration needs the stateful client's current principal so its business decision is attributable"
|
|
2859
|
+
};
|
|
2860
|
+
}
|
|
2861
|
+
const resolved = currentLaw(eng, ws)[domain];
|
|
2862
|
+
if (resolved !== currentHash) {
|
|
2863
|
+
return {
|
|
2864
|
+
ok: false,
|
|
2865
|
+
stage: "preflight",
|
|
2866
|
+
error: "the generated model is no longer current; nothing changed [nomos.rollout.restore-current-changed]"
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2869
|
+
const current = qById(eng, ws, `domain-installation:${currentHash}`)[0]?.data;
|
|
2870
|
+
const priorHash = typeof current?.["spec.supersedes"] === "string" ? current["spec.supersedes"] : "";
|
|
2871
|
+
if (!priorHash) {
|
|
2872
|
+
return {
|
|
2873
|
+
ok: false,
|
|
2874
|
+
stage: "preflight",
|
|
2875
|
+
error: "this model has no previous model to restore [nomos.rollout.restore-no-previous]"
|
|
2876
|
+
};
|
|
2877
|
+
}
|
|
2878
|
+
const atHash = kgit.resolveRef(eng, gitdirOf(ws), BRANCH);
|
|
2879
|
+
if (!atHash) return { ok: false, stage: "preflight", error: "workspace has no history to prove" };
|
|
2880
|
+
let report;
|
|
2881
|
+
try {
|
|
2882
|
+
report = historyRestorePreflight(
|
|
2883
|
+
eng,
|
|
2884
|
+
ws,
|
|
2885
|
+
domain,
|
|
2886
|
+
currentHash,
|
|
2887
|
+
priorHash,
|
|
2888
|
+
atHash,
|
|
2889
|
+
actingPrincipal
|
|
2890
|
+
);
|
|
2891
|
+
} catch (error) {
|
|
2892
|
+
return { ok: false, stage: "preflight", error: String(error?.message || error) };
|
|
2893
|
+
}
|
|
2894
|
+
const prepared = prepareManagedRestoration(report, currentHash, priorHash, domain, opts);
|
|
2895
|
+
if (!prepared.ok) return prepared;
|
|
2896
|
+
const { acceptanceReason: _acceptance, ...authorOpts } = opts;
|
|
2897
|
+
const result = author(eng, ws, "nomos", "rollbackDomain", prepared.payload, eng.hashes.nomos, {
|
|
2898
|
+
...authorOpts,
|
|
2899
|
+
...actingPrincipal ? { actor: actingPrincipal } : {}
|
|
2900
|
+
});
|
|
2901
|
+
return result.ok ? { ...result, stage: "restored", report, receiptId: prepared.receiptId } : { ...result, stage: "admission", report, receiptId: prepared.receiptId };
|
|
2902
|
+
}
|
|
2903
|
+
async function rebirthCompact(eng, ws, ledger, { reason = "", supersededAt = 0, parent = "" } = {}) {
|
|
2904
|
+
const incWs = `${ws}__rebirth`;
|
|
2905
|
+
try {
|
|
2906
|
+
const mounted = eng.mounted.get(ws) ?? await mountWorkspace(eng, ws, ledger || { remote: "https://unborn.invalid/", headers: {} });
|
|
2907
|
+
const srcGitdir = gitdirOf(ws);
|
|
2908
|
+
const oldHead = kgit.resolveRef(eng, srcGitdir, BRANCH) || mounted.remoteMain || "";
|
|
2909
|
+
if (!/^[0-9a-f]{40}$/i.test(oldHead)) return { ok: false, error: `'${ws}' has no refs/heads/main to rebirth \u2014 nothing to compact` };
|
|
2910
|
+
const sealed = kgit.intentsAbove(eng, srcGitdir, oldHead, "", 0);
|
|
2911
|
+
if (!Array.isArray(sealed) || !sealed.length) return { ok: false, error: `'${ws}' main carries no intents to replay` };
|
|
2912
|
+
unmount(eng, incWs);
|
|
2913
|
+
await mountEphemeralWorkspace(eng, incWs, {});
|
|
2914
|
+
const isGenesisBootstrapInstall = (c) => c.domain === "bootstrap" && c.directiveId === "installDomain";
|
|
2915
|
+
const transformState = (sealedBytes, _ctx) => sealedBytes;
|
|
2916
|
+
const carried = [];
|
|
2917
|
+
const parkedIntents = [];
|
|
2918
|
+
const parkedBlobs = [];
|
|
2919
|
+
let idx = -1, lastCarriedIdx = -1, firstParkedIdx = -1;
|
|
2920
|
+
for (const c of sealed) {
|
|
2921
|
+
idx++;
|
|
2922
|
+
if (isGenesisBootstrapInstall(c)) continue;
|
|
2923
|
+
let bytes;
|
|
2924
|
+
try {
|
|
2925
|
+
bytes = transformState(bytesFromB64(c.changeB64), { oid: c.oid, incWs });
|
|
2926
|
+
} catch {
|
|
2927
|
+
parkedIntents.push({ oid: c.oid, reason: "undecodable intent blob" });
|
|
2928
|
+
parkedBlobs.push(bytesFromB64(c.changeB64));
|
|
2929
|
+
if (firstParkedIdx < 0) firstParkedIdx = idx;
|
|
2930
|
+
continue;
|
|
2931
|
+
}
|
|
2932
|
+
const r = applyIntentBytes(eng, incWs, bytes, { defer: false });
|
|
2933
|
+
if (r && r.ok) {
|
|
2934
|
+
carried.push(c.oid);
|
|
2935
|
+
lastCarriedIdx = idx;
|
|
2936
|
+
} else {
|
|
2937
|
+
parkedIntents.push({ oid: c.oid, reason: String(r && r.error || "refused").slice(0, 200) });
|
|
2938
|
+
parkedBlobs.push(bytes);
|
|
2939
|
+
if (firstParkedIdx < 0) firstParkedIdx = idx;
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
const scarShape = parkedIntents.length === 0 ? "none" : firstParkedIdx > lastCarriedIdx ? "tail" : "mid-chain";
|
|
2943
|
+
const incGitdir = gitdirOf(incWs);
|
|
2944
|
+
const head = kgit.resolveRef(eng, incGitdir, BRANCH);
|
|
2945
|
+
if (!/^[0-9a-f]{40}$/i.test(head || "")) {
|
|
2946
|
+
unmount(eng, incWs);
|
|
2947
|
+
return { ok: false, error: `the incarnation folded no intents (all ${sealed.length} refused \u2014 all parked-to-be, nothing to serve)`, parked: parkedIntents.length, parkedIntents };
|
|
2948
|
+
}
|
|
2949
|
+
const incChain = kgit.intentsAbove(eng, incGitdir, head, "", 0);
|
|
2950
|
+
const genesisOid = incChain.length ? incChain[0].oid : head;
|
|
2951
|
+
let parkedRef = "";
|
|
2952
|
+
let parkedTip = "";
|
|
2953
|
+
if (parkedBlobs.length) {
|
|
2954
|
+
parkedRef = `refs/heads/parked/rebirth/${supersededAt || Date.now()}`;
|
|
2955
|
+
let parentOid = head;
|
|
2956
|
+
for (let i = 0; i < parkedBlobs.length; i++) {
|
|
2957
|
+
parentOid = kgit.writeMetaCommit(eng, incGitdir, {
|
|
2958
|
+
parents: [parentOid],
|
|
2959
|
+
files: [{ path: "change.usda", bytes: parkedBlobs[i] }],
|
|
2960
|
+
message: `unreplayed: ${parkedIntents[i].oid.slice(0, 12)} \u2014 ${parkedIntents[i].reason.slice(0, 120)}`,
|
|
2961
|
+
timeSecs: 0,
|
|
2962
|
+
ref: i === parkedBlobs.length - 1 ? parkedRef : ""
|
|
2963
|
+
});
|
|
2964
|
+
}
|
|
2965
|
+
parkedTip = parentOid;
|
|
2966
|
+
}
|
|
2967
|
+
const verdict = verifyChainLocal(eng, incWs);
|
|
2968
|
+
const verified = verdict && verdict.valid === true;
|
|
2969
|
+
if (ws !== "root" && !isWarranted(eng, incWs)) {
|
|
2970
|
+
unmount(eng, incWs);
|
|
2971
|
+
return {
|
|
2972
|
+
ok: false,
|
|
2973
|
+
error: `the incarnation carries no GenesisWarrant (${carried.length} carried, ${parkedIntents.length} parked) \u2014 refusing to swap to a bootstrap-only holon`,
|
|
2974
|
+
verified,
|
|
2975
|
+
carried: carried.length,
|
|
2976
|
+
parked: parkedIntents.length,
|
|
2977
|
+
parkedIntents,
|
|
2978
|
+
scarShape
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2981
|
+
let packB64 = "";
|
|
2982
|
+
let parkedPackB64 = "";
|
|
2983
|
+
if (verified) {
|
|
2984
|
+
const pack = packDelta(eng, incWs, "", head);
|
|
2985
|
+
if (pack && pack.length) packB64 = b64Bytes(pack);
|
|
2986
|
+
if (parkedTip) {
|
|
2987
|
+
const ppack = packDelta(eng, incWs, head, parkedTip);
|
|
2988
|
+
if (ppack && ppack.length) parkedPackB64 = b64Bytes(ppack);
|
|
2989
|
+
if (!parkedPackB64) {
|
|
2990
|
+
unmount(eng, incWs);
|
|
2991
|
+
return { ok: false, error: "parked intents exist but produced no parked pack \u2014 refusing (parked work must never be lost)", parked: parkedIntents.length };
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
unmount(eng, incWs);
|
|
2996
|
+
if (verified && !packB64) return { ok: false, error: "the incarnation self-verified but produced no pack", verified: true };
|
|
2997
|
+
return {
|
|
2998
|
+
ok: true,
|
|
2999
|
+
packB64,
|
|
3000
|
+
head,
|
|
3001
|
+
genesisOid,
|
|
3002
|
+
verified,
|
|
3003
|
+
...verified ? {} : { verifyError: verdict && verdict.error || "verify_chain returned invalid" },
|
|
3004
|
+
carried: carried.length,
|
|
3005
|
+
parked: parkedIntents.length,
|
|
3006
|
+
parkedIntents,
|
|
3007
|
+
scarShape,
|
|
3008
|
+
...parkedTip ? { parkedRef, parkedTip, parkedPackB64 } : {},
|
|
3009
|
+
// rebornFrom = the SUPERSEDED chain's genesis oid (the old ancestry the reborn holon descends
|
|
3010
|
+
// from). Surfaced for the worker's status contract; NOT re-authored IN-CHAIN here (stamping it
|
|
3011
|
+
// onto birthCloud would re-sign the record → the operator key, the CLI lane).
|
|
3012
|
+
rebornFrom: sealed[0].oid,
|
|
3013
|
+
parent,
|
|
3014
|
+
reason,
|
|
3015
|
+
supersededAt
|
|
3016
|
+
};
|
|
3017
|
+
} catch (e) {
|
|
3018
|
+
try {
|
|
3019
|
+
unmount(eng, incWs);
|
|
3020
|
+
} catch {
|
|
3021
|
+
}
|
|
3022
|
+
return { ok: false, error: String(e?.message || e).slice(0, 300) };
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
async function archiveRefusedMain(eng, ws, ledger, label) {
|
|
3026
|
+
unmount(eng, ws);
|
|
3027
|
+
const m = await mountWorkspace(eng, ws, ledger);
|
|
3028
|
+
if (!m.restored) {
|
|
3029
|
+
unmount(eng, ws);
|
|
3030
|
+
return { archived: false, error: "no main to archive" };
|
|
3031
|
+
}
|
|
3032
|
+
const gitdir = gitdirOf(ws);
|
|
3033
|
+
try {
|
|
3034
|
+
await custodyPush(eng, ws, ledger, { localRef: "refs/heads/main", remoteRef: `refs/heads/refused/${label}`, pointer: true });
|
|
3035
|
+
await custodyPush(eng, ws, ledger, { remoteRef: "refs/heads/main", del: true });
|
|
3036
|
+
return { archived: true, ref: `refs/heads/refused/${label}` };
|
|
3037
|
+
} finally {
|
|
3038
|
+
unmount(eng, ws);
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
async function writeRefusedRef(eng, ws, dl) {
|
|
3042
|
+
const gitdir = gitdirOf(ws);
|
|
3043
|
+
const blob = dl.blob instanceof Uint8Array ? dl.blob : enc3.encode(String(dl.blob || ""));
|
|
3044
|
+
const refForStamp = refusedRefName(dl.intentId || dl.oid);
|
|
3045
|
+
let parkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3046
|
+
try {
|
|
3047
|
+
const prevOid = kgit.resolveRef(eng, gitdir, refForStamp);
|
|
3048
|
+
if (prevOid) {
|
|
3049
|
+
const prevBytes = kgit.readBlob(eng, gitdir, prevOid, "verdict.usda");
|
|
3050
|
+
const prev = prevBytes ? kgit.inspectDocument(eng, prevBytes) : null;
|
|
3051
|
+
if (prev && typeof prev.parkedAt === "string") parkedAt = prev.parkedAt;
|
|
3052
|
+
}
|
|
3053
|
+
} catch {
|
|
3054
|
+
}
|
|
3055
|
+
const verdict = kgit.encodeDocument(eng, {
|
|
3056
|
+
offerId: dl.intentId || null,
|
|
3057
|
+
oid: dl.oid || null,
|
|
3058
|
+
domain: dl.domain || null,
|
|
3059
|
+
directiveId: dl.directiveId || null,
|
|
3060
|
+
session: dl.session || null,
|
|
3061
|
+
parkedAt,
|
|
3062
|
+
verdict: { reason: String(dl.error || "refused") }
|
|
3063
|
+
});
|
|
3064
|
+
const ref = refusedRefName(dl.intentId || dl.oid);
|
|
3065
|
+
kgit.writeMetaCommit(eng, gitdir, {
|
|
3066
|
+
parents: [],
|
|
3067
|
+
files: [{ path: "change.usda", bytes: blob }, { path: "verdict.usda", bytes: verdict }],
|
|
3068
|
+
message: `refused: ${dl.domain || "?"}/${dl.directiveId || "?"} \u2014 ${String(dl.error || "").slice(0, 120)}`,
|
|
3069
|
+
timeSecs: 0,
|
|
3070
|
+
ref
|
|
3071
|
+
});
|
|
3072
|
+
return ref;
|
|
3073
|
+
}
|
|
3074
|
+
async function listRefusedRefs(eng, ws) {
|
|
3075
|
+
const gitdir = gitdirOf(ws);
|
|
3076
|
+
const refs = kgit.listRefs(eng, gitdir, "refs/heads/refused/");
|
|
3077
|
+
const out2 = [];
|
|
3078
|
+
for (const { ref, oid } of refs) {
|
|
3079
|
+
try {
|
|
3080
|
+
const vb = kgit.readBlob(eng, gitdir, oid, "verdict.usda") ?? new Uint8Array();
|
|
3081
|
+
const ib = kgit.readBlob(eng, gitdir, oid, "change.usda") ?? new Uint8Array();
|
|
3082
|
+
const v = kgit.inspectDocument(eng, vb);
|
|
3083
|
+
out2.push({ ref, ...v, changeB64: b64Bytes(ib) });
|
|
3084
|
+
} catch {
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
return out2;
|
|
3088
|
+
}
|
|
3089
|
+
async function refusedSummary(eng, ws) {
|
|
3090
|
+
const gitdir = gitdirOf(ws);
|
|
3091
|
+
const refs = kgit.listRefs(eng, gitdir, "refs/heads/refused/");
|
|
3092
|
+
let count2 = 0, latestParkedAt = null;
|
|
3093
|
+
for (const { oid } of refs) {
|
|
3094
|
+
try {
|
|
3095
|
+
const bytes = kgit.readBlob(eng, gitdir, oid, "verdict.usda");
|
|
3096
|
+
if (!bytes) continue;
|
|
3097
|
+
const v = kgit.inspectDocument(eng, bytes);
|
|
3098
|
+
count2++;
|
|
3099
|
+
if (v && typeof v.parkedAt === "string" && (!latestParkedAt || v.parkedAt > latestParkedAt)) latestParkedAt = v.parkedAt;
|
|
3100
|
+
} catch {
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
return { count: count2, latestParkedAt };
|
|
3104
|
+
}
|
|
3105
|
+
async function materializeRefused(eng, ws, ledger, deadLetters) {
|
|
3106
|
+
const refs = [];
|
|
3107
|
+
const unparkedSessions = /* @__PURE__ */ new Set();
|
|
3108
|
+
for (const dl of deadLetters || []) {
|
|
3109
|
+
try {
|
|
3110
|
+
const ref = await writeRefusedRef(eng, ws, dl);
|
|
3111
|
+
await custodyPush(eng, ws, ledger, { remoteRef: ref });
|
|
3112
|
+
refs.push(ref);
|
|
3113
|
+
} catch (e) {
|
|
3114
|
+
if (dl && dl.session) unparkedSessions.add(dl.session);
|
|
3115
|
+
log("refused-ref-materialize-failed", { ws, intentId: dl?.intentId, error: String(e).slice(0, 200) });
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
return { refs, unparkedSessions };
|
|
3119
|
+
}
|
|
3120
|
+
async function deleteRefusedRef(eng, ws, ledger, offerId) {
|
|
3121
|
+
const gitdir = gitdirOf(ws);
|
|
3122
|
+
const ref = refusedRefName(offerId);
|
|
3123
|
+
try {
|
|
3124
|
+
kgit.deleteRef(eng, gitdir, ref);
|
|
3125
|
+
} catch {
|
|
3126
|
+
}
|
|
3127
|
+
try {
|
|
3128
|
+
await custodyPush(eng, ws, ledger, { remoteRef: ref, del: true });
|
|
3129
|
+
} catch (e) {
|
|
3130
|
+
log("refused-ref-delete-push-failed", { ws, ref, error: String(e).slice(0, 200) });
|
|
3131
|
+
}
|
|
3132
|
+
return ref;
|
|
3133
|
+
}
|
|
3134
|
+
async function outboxRefExists(eng, ws, requestId) {
|
|
3135
|
+
return !!kgit.resolveRef(eng, gitdirOf(ws), outboxRefName(requestId));
|
|
3136
|
+
}
|
|
3137
|
+
async function writeOutboxRef(eng, ws, rec) {
|
|
3138
|
+
const gitdir = gitdirOf(ws);
|
|
3139
|
+
const orderBlob = enc3.encode(JSON.stringify(rec.order ?? {}));
|
|
3140
|
+
const delivery = enc3.encode(JSON.stringify({
|
|
3141
|
+
requestId: rec.requestId || null,
|
|
3142
|
+
capability: rec.capability || null,
|
|
3143
|
+
url: rec.url || null,
|
|
3144
|
+
status: rec.status || "delivered",
|
|
3145
|
+
httpStatus: rec.httpStatus ?? null
|
|
3146
|
+
}));
|
|
3147
|
+
const ref = outboxRefName(rec.requestId);
|
|
3148
|
+
kgit.writeMetaCommit(eng, gitdir, {
|
|
3149
|
+
parents: [],
|
|
3150
|
+
files: [{ path: "order.json", bytes: orderBlob }, { path: "delivery.json", bytes: delivery }],
|
|
3151
|
+
message: `outbox: ${rec.capability || "?"} \u2192 ${String(rec.url || "?").slice(0, 80)}`,
|
|
3152
|
+
timeSecs: 0,
|
|
3153
|
+
ref
|
|
3154
|
+
});
|
|
3155
|
+
return ref;
|
|
3156
|
+
}
|
|
3157
|
+
async function emitOutbox(eng, ws, ledger) {
|
|
3158
|
+
const orders = (() => {
|
|
3159
|
+
try {
|
|
3160
|
+
return reactorScan(eng, ws);
|
|
3161
|
+
} catch {
|
|
3162
|
+
return [];
|
|
3163
|
+
}
|
|
3164
|
+
})();
|
|
3165
|
+
if (!Array.isArray(orders) || orders.length === 0) return { delivered: [], skipped: 0, errors: 0 };
|
|
3166
|
+
const byType = /* @__PURE__ */ new Map();
|
|
3167
|
+
for (const c of declaredCapabilities(eng, ws)) if (c && c.aggregateId) byType.set(c.aggregateId, c);
|
|
3168
|
+
const gitdir = gitdirOf(ws);
|
|
3169
|
+
const delivered = [];
|
|
3170
|
+
let skipped = 0, errors = 0;
|
|
3171
|
+
for (const order of orders) {
|
|
3172
|
+
const cap = byType.get(order.taskType);
|
|
3173
|
+
if (!cap || !cap.endpoint) {
|
|
3174
|
+
skipped++;
|
|
3175
|
+
continue;
|
|
3176
|
+
}
|
|
3177
|
+
if (await outboxRefExists(eng, ws, order.requestId)) {
|
|
3178
|
+
skipped++;
|
|
3179
|
+
continue;
|
|
3180
|
+
}
|
|
3181
|
+
try {
|
|
3182
|
+
const res = await fetch(cap.endpoint, {
|
|
3183
|
+
method: "POST",
|
|
3184
|
+
headers: { "content-type": "application/json", "x-nomos-capability": cap.capability, "x-nomos-workspace": ws },
|
|
3185
|
+
body: JSON.stringify({ capability: cap.capability, requestId: order.requestId, taskType: order.taskType, params: order.params, scheduledAt: order.scheduledAt, deadlineAt: order.deadlineAt }),
|
|
3186
|
+
signal: AbortSignal.timeout(3e4)
|
|
3187
|
+
});
|
|
3188
|
+
if (!res.ok) {
|
|
3189
|
+
errors++;
|
|
3190
|
+
log("outbox-deliver-non2xx", { ws, requestId: order.requestId, url: cap.endpoint, status: res.status });
|
|
3191
|
+
continue;
|
|
3192
|
+
}
|
|
3193
|
+
const ref = await writeOutboxRef(eng, ws, { requestId: order.requestId, capability: cap.capability, url: cap.endpoint, order, status: "delivered", httpStatus: res.status });
|
|
3194
|
+
try {
|
|
3195
|
+
await custodyPush(eng, ws, ledger, { remoteRef: ref });
|
|
3196
|
+
} catch (e) {
|
|
3197
|
+
log("outbox-ref-push-failed", { ws, ref, error: String(e).slice(0, 200) });
|
|
3198
|
+
}
|
|
3199
|
+
delivered.push(order.requestId);
|
|
3200
|
+
} catch (e) {
|
|
3201
|
+
errors++;
|
|
3202
|
+
log("outbox-deliver-failed", { ws, requestId: order.requestId, url: cap.endpoint, error: String(e).slice(0, 200) });
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
if (delivered.length || errors) log("outbox", { ws, delivered: delivered.length, skipped, errors });
|
|
3206
|
+
return { delivered, skipped, errors };
|
|
3207
|
+
}
|
|
3208
|
+
async function boot(eng, ws, ledger) {
|
|
3209
|
+
const m = await mountWorkspace(eng, ws, ledger);
|
|
3210
|
+
if (nomosActive(eng, ws)) {
|
|
3211
|
+
if (ws !== "root" && !isWarranted(eng, ws)) {
|
|
3212
|
+
throw new Error(
|
|
3213
|
+
`unwarranted-workspace: '${ws}' is booted but its genesis never landed a GenesisWarrant \u2014 an era-0 workspace is born ONLY by its parent's warranted+attested birth. This is a host-authored/legacy orphan and will not serve (author its birth on its parent to bring it into the holarchy lawfully).`
|
|
3214
|
+
);
|
|
3215
|
+
}
|
|
3216
|
+
return { status: "already-initialized", head: m.remoteMain ?? void 0, controllerHash: eng.hashes.nomos, rows: qById(eng, ws, `domain-installation:${eng.hashes.nomos}`), mount: m };
|
|
3217
|
+
}
|
|
3218
|
+
throw new Error(
|
|
3219
|
+
`unborn-workspace: '${ws}' has no genesis and the host does not create workspaces \u2014 author its birth on its PARENT (birthChild/birthHome/an estate .births()); the parent's offer-effect materializes it in custody, then it serves from here. (root self-adopts via _ensureRootGenesis; this is not that path.)`
|
|
3220
|
+
);
|
|
3221
|
+
}
|
|
3222
|
+
function snapshot(eng, ws) {
|
|
3223
|
+
const wsDir = dirOf(eng.preopen.dir.contents.get("ws")).contents.get(ws);
|
|
3224
|
+
return serializeTree(wsDir);
|
|
3225
|
+
}
|
|
3226
|
+
function stats(eng) {
|
|
3227
|
+
return {
|
|
3228
|
+
mounted: eng.mounted.size,
|
|
3229
|
+
wasmLinearMemMB: +(eng.ex.memory.buffer.byteLength / 1048576).toFixed(1)
|
|
3230
|
+
};
|
|
3231
|
+
}
|
|
3232
|
+
async function ledgerStats(eng, ws, ledger = null) {
|
|
3233
|
+
const gitdir = gitdirOf(ws);
|
|
3234
|
+
let head = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
3235
|
+
if (!head && ledger?.remote) {
|
|
3236
|
+
try {
|
|
3237
|
+
await custodySkeleton(eng, gitdir);
|
|
3238
|
+
const remoteMain = await custodyFetch(eng, ws, ledger, { remoteRef: "refs/heads/main", writeRef: false });
|
|
3239
|
+
if (!remoteMain) return { head: null, commits: 0 };
|
|
3240
|
+
kgit.restoreMain(eng, ws, remoteMain);
|
|
3241
|
+
head = kgit.resolveRef(eng, gitdir, BRANCH);
|
|
3242
|
+
const mounted2 = eng.mounted.get(ws);
|
|
3243
|
+
if (mounted2) {
|
|
3244
|
+
mounted2.restored = true;
|
|
3245
|
+
mounted2.remoteMain = remoteMain;
|
|
3246
|
+
mounted2.restoreError = null;
|
|
3247
|
+
}
|
|
3248
|
+
} catch {
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
if (!head) return { head: null, commits: 0 };
|
|
3252
|
+
const mounted = eng.mounted.get(ws);
|
|
3253
|
+
if (mounted && mounted.ledgerStats?.head === head) return mounted.ledgerStats;
|
|
3254
|
+
const commits = kgit.intentsAbove(eng, gitdir, head).length;
|
|
3255
|
+
const out2 = { head, commits };
|
|
3256
|
+
if (mounted) mounted.ledgerStats = out2;
|
|
3257
|
+
return out2;
|
|
3258
|
+
}
|
|
3259
|
+
async function countRemoteCommits(eng, ledger) {
|
|
3260
|
+
const head = (await custodyLsRefs(ledger, "refs/heads/main"))["refs/heads/main"] || null;
|
|
3261
|
+
if (!head) return { head: null, commits: 0 };
|
|
3262
|
+
const scratch = "__ledgercount__";
|
|
3263
|
+
try {
|
|
3264
|
+
stageWorkspaceDir(eng, scratch);
|
|
3265
|
+
await custodySkeleton(eng, gitdirOf(scratch));
|
|
3266
|
+
await custodyFetch(eng, scratch, ledger, { remoteRef: "refs/heads/main", writeRef: false });
|
|
3267
|
+
const commits = kgit.intentsAbove(eng, gitdirOf(scratch), head).length;
|
|
3268
|
+
return { head, commits };
|
|
3269
|
+
} finally {
|
|
3270
|
+
try {
|
|
3271
|
+
dirOf(eng.preopen.dir.contents.get("ws")).contents.delete(scratch);
|
|
3272
|
+
} catch {
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
function warmEngine(eng, opts = {}) {
|
|
3277
|
+
flushDeferredProjections(eng);
|
|
3278
|
+
return warmKernelCaches(eng, opts);
|
|
3279
|
+
}
|
|
3280
|
+
function warmKernelCaches(eng, opts = {}) {
|
|
3281
|
+
const workspace = opts.workspace ?? "root";
|
|
3282
|
+
return namedQueryProto(eng, workspace, QueryOperation.WARM, {
|
|
3283
|
+
...opts.workspace ? { repoArg: repoArgOf(workspace), workspace, packCustody: true } : {},
|
|
3284
|
+
...opts.compareStateProjections ? { compareStateProjections: true } : {},
|
|
3285
|
+
...opts.requestedDomain ? { requestedDomain: opts.requestedDomain } : {},
|
|
3286
|
+
...opts.requestedDirective ? { requestedDirective: opts.requestedDirective } : {},
|
|
3287
|
+
...opts.requestedPackage ? { requestedPackage: opts.requestedPackage } : {},
|
|
3288
|
+
...opts.interactiveOnly ? { interactiveOnly: true } : {}
|
|
3289
|
+
});
|
|
3290
|
+
}
|
|
3291
|
+
var enc3, dec3, BRANCH, PROTO_ABI_VERSION, protoRequestSequence, RESULT_PACK_INLINE_MAX, dirOf, repoArgOf, gitdirOf, unpack, unsignedWasiPointers, log, protoTarget, protoAuthority, repoArgOfGitdir, bytesFromB64, kgit, closureInstallPayload, routeTagHexOfHomeKey, SUMMARY_SEP, summaryKey, splitSummaryKey, NOMOS_SHARD_ROWS_READ, groupOf, tallyOf, isExtremumRead, extremumMonotone, CKPT_REF, pushVia, fullRef, applyPackInto, importCustodyObjects, syncCandidate, custodyLsRefs, queryArguments, queryAuthorityOptions, qById, query, queryPage, queryProfile, authorizationAddress, authorizationSubject, currentAuthorizationFrontier, check, expand, cryptoSealField, cryptoOwnedScopeKey, cryptoOwnedDeviceRequest, cryptoOwnedPrepareApproval, cryptoOwnedPrepareRecovery, cryptoKeygen, authorKeygen, eraCertSign, delegationCertSign, attestationSign, certSign, cryptoWrapKey, cryptoUnwrapKey, readPosture, count, sum, pendingConflicts, pendingConflictSummary, spatialBboxParams, spatialWithin, extremum, nomosActive, refusedRefName, outboxRefName, GENESIS_WARRANT_ID, isWarranted, projectionStats, memoryDropProbe, readiness;
|
|
3292
|
+
var init_engine = __esm({
|
|
3293
|
+
"vendor/engine/engine.ts"() {
|
|
3294
|
+
"use strict";
|
|
3295
|
+
init_git_fs();
|
|
3296
|
+
init_tree();
|
|
3297
|
+
init_custody_transport();
|
|
3298
|
+
init_managed_promotion();
|
|
3299
|
+
init_kernel_pb();
|
|
3300
|
+
enc3 = new TextEncoder();
|
|
3301
|
+
dec3 = new TextDecoder();
|
|
3302
|
+
BRANCH = "main";
|
|
3303
|
+
PROTO_ABI_VERSION = 1;
|
|
3304
|
+
protoRequestSequence = 0;
|
|
3305
|
+
RESULT_PACK_INLINE_MAX = 256 * 1024;
|
|
3306
|
+
dirOf = (n) => n;
|
|
3307
|
+
repoArgOf = (ws) => `/work/ws/${ws}`;
|
|
3308
|
+
gitdirOf = (ws) => `/work/ws/${ws}/nomos.git`;
|
|
3309
|
+
unpack = (p) => {
|
|
3310
|
+
const v = BigInt.asUintN(64, typeof p === "bigint" ? p : BigInt(p));
|
|
3311
|
+
return { ptr: Number(v >> 32n & 0xffffffffn), len: Number(v & 0xffffffffn) };
|
|
3312
|
+
};
|
|
3313
|
+
unsignedWasiPointers = (imports) => {
|
|
3314
|
+
const pointerArgs = {
|
|
3315
|
+
args_sizes_get: [0, 1],
|
|
3316
|
+
args_get: [0, 1],
|
|
3317
|
+
environ_sizes_get: [0, 1],
|
|
3318
|
+
environ_get: [0, 1],
|
|
3319
|
+
clock_res_get: [1],
|
|
3320
|
+
clock_time_get: [2],
|
|
3321
|
+
fd_fdstat_get: [1],
|
|
3322
|
+
fd_filestat_get: [1],
|
|
3323
|
+
fd_pread: [1, 4],
|
|
3324
|
+
fd_prestat_get: [1],
|
|
3325
|
+
fd_prestat_dir_name: [1],
|
|
3326
|
+
fd_pwrite: [1, 4],
|
|
3327
|
+
fd_read: [1, 3],
|
|
3328
|
+
fd_readdir: [1, 4],
|
|
3329
|
+
fd_seek: [3],
|
|
3330
|
+
fd_tell: [1],
|
|
3331
|
+
fd_write: [1, 3],
|
|
3332
|
+
path_create_directory: [1],
|
|
3333
|
+
path_filestat_get: [2, 4],
|
|
3334
|
+
path_filestat_set_times: [2],
|
|
3335
|
+
path_link: [2, 5],
|
|
3336
|
+
path_open: [2, 8],
|
|
3337
|
+
path_readlink: [1, 3, 5],
|
|
3338
|
+
path_remove_directory: [1],
|
|
3339
|
+
path_rename: [1, 4],
|
|
3340
|
+
path_symlink: [0, 3],
|
|
3341
|
+
path_unlink_file: [1],
|
|
3342
|
+
poll_oneoff: [0, 1],
|
|
3343
|
+
random_get: [0]
|
|
3344
|
+
};
|
|
3345
|
+
for (const [name, indexes] of Object.entries(pointerArgs)) {
|
|
3346
|
+
const original = imports[name];
|
|
3347
|
+
if (typeof original !== "function") continue;
|
|
3348
|
+
imports[name] = (...args) => {
|
|
3349
|
+
for (const index of indexes) args[index] = args[index] >>> 0;
|
|
3350
|
+
return original(...args);
|
|
3351
|
+
};
|
|
3352
|
+
}
|
|
3353
|
+
return imports;
|
|
3354
|
+
};
|
|
3355
|
+
log = (evt, fields = {}) => console.log(JSON.stringify({ evt, t: Date.now(), ...fields }));
|
|
3356
|
+
protoTarget = (ws = "root", branch = BRANCH) => create(WorkspaceTargetSchema, {
|
|
3357
|
+
repo: repoArgOf(ws),
|
|
3358
|
+
workspace: ws,
|
|
3359
|
+
branch
|
|
3360
|
+
});
|
|
3361
|
+
protoAuthority = (principal = "", keys = [], authToken = "", nowUnix = 0, authorSecret = "") => create(QueryAuthoritySchema, {
|
|
3362
|
+
principalClaim: principal,
|
|
3363
|
+
authToken: authToken ? enc3.encode(authToken) : new Uint8Array(),
|
|
3364
|
+
nowUnix: BigInt(nowUnix),
|
|
3365
|
+
authorSecret: authorSecret ? bytesFromB64(authorSecret) : new Uint8Array(),
|
|
3366
|
+
keys: keys.map((key) => create(InjectedKeySchema, {
|
|
3367
|
+
scope: key.scope,
|
|
3368
|
+
epoch: BigInt(key.epoch),
|
|
3369
|
+
key: bytesFromB64(key.key)
|
|
3370
|
+
}))
|
|
3371
|
+
});
|
|
3372
|
+
repoArgOfGitdir = (gitdir) => gitdir.replace(/\/nomos\.git$/, "");
|
|
3373
|
+
bytesFromB64 = (b64) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
3374
|
+
kgit = {
|
|
3375
|
+
// resolveRef → tip oid hex, or null if the ref is absent (replaces git.resolveRef(...).catch(()=>null)).
|
|
3376
|
+
resolveRef: (eng, gitdir, ref) => custodyProtoCase(eng, {
|
|
3377
|
+
case: "resolveRef",
|
|
3378
|
+
value: create(ResolveRefRequestSchema, { repo: repoArgOfGitdir(gitdir), reference: ref })
|
|
3379
|
+
}, "resolveRef").oid ?? "",
|
|
3380
|
+
// readBlob → the blob bytes at `path` inside commit `oid`, or null if not found (no throw).
|
|
3381
|
+
readBlob: (eng, gitdir, oid, path) => {
|
|
3382
|
+
const result = custodyProtoCase(eng, {
|
|
3383
|
+
case: "readBlob",
|
|
3384
|
+
value: create(ReadBlobRequestSchema, { repo: repoArgOfGitdir(gitdir), oid, path })
|
|
3385
|
+
}, "readBlob");
|
|
3386
|
+
return result.found ? result.blob : null;
|
|
3387
|
+
},
|
|
3388
|
+
// intentsAbove → [{ oid, changeB64 }] oldest→newest over (base, head] (replaces log + readBlob intent.json).
|
|
3389
|
+
// `limit` (0 = all) caps to the most-recent N intent commits (replaces git.log depth).
|
|
3390
|
+
intentsAbove: (eng, gitdir, head, base = "", limit = 0, completeLogical = false) => custodyProtoCase(eng, {
|
|
3391
|
+
case: "intentsAbove",
|
|
3392
|
+
value: create(IntentsAboveRequestSchema, {
|
|
3393
|
+
repo: repoArgOfGitdir(gitdir),
|
|
3394
|
+
head: head || void 0,
|
|
3395
|
+
base: base || void 0,
|
|
3396
|
+
branch: BRANCH,
|
|
3397
|
+
limit: BigInt(limit),
|
|
3398
|
+
completeLogical
|
|
3399
|
+
})
|
|
3400
|
+
}, "intentsAbove").intents.map((intent) => ({
|
|
3401
|
+
oid: intent.oid,
|
|
3402
|
+
id: intent.intentId,
|
|
3403
|
+
domain: intent.domain,
|
|
3404
|
+
directiveId: intent.directive,
|
|
3405
|
+
changeB64: b64Bytes(intent.changeUsda),
|
|
3406
|
+
intent: jsStruct(intent.semantic)
|
|
3407
|
+
})),
|
|
3408
|
+
// inspectChange → compact semantic view decoded by the kernel; the adapter never parses USDA.
|
|
3409
|
+
inspectChange: (eng, bytes) => jsStruct(custodyProtoCase(eng, {
|
|
3410
|
+
case: "inspectChange",
|
|
3411
|
+
value: create(InspectChangeRequestSchema, { changeUsda: bytes })
|
|
3412
|
+
}, "inspectChange").semantic),
|
|
3413
|
+
// Open structured custody sidecars are USDA too. The kernel owns their syntax and validation;
|
|
3414
|
+
// the adapter only relays transient values and opaque bytes.
|
|
3415
|
+
encodeDocument: (eng, value) => custodyProtoCase(eng, {
|
|
3416
|
+
case: "encodeDocument",
|
|
3417
|
+
value: create(EncodeDocumentRequestSchema, { document: protoValue(value) })
|
|
3418
|
+
}, "encodeDocument").documentUsda,
|
|
3419
|
+
inspectDocument: (eng, bytes) => jsValue(custodyProtoCase(eng, {
|
|
3420
|
+
case: "inspectDocument",
|
|
3421
|
+
value: create(InspectDocumentRequestSchema, { documentUsda: bytes })
|
|
3422
|
+
}, "inspectDocument").document),
|
|
3423
|
+
// listRefs → [{ ref, oid }] under prefix (replaces git.listRefs for LOCAL refs).
|
|
3424
|
+
listRefs: (eng, gitdir, prefix) => custodyProtoCase(eng, {
|
|
3425
|
+
case: "listRefs",
|
|
3426
|
+
value: create(ListRefsRequestSchema, { repo: repoArgOfGitdir(gitdir), prefix })
|
|
3427
|
+
}, "listRefs").refs.map(({ reference, oid }) => ({ ref: reference, oid })),
|
|
3428
|
+
// writeRef → force-point a ref (plain oid or `ref:`-symbolic) (replaces git.writeRef).
|
|
3429
|
+
writeRef: (eng, gitdir, ref, value) => {
|
|
3430
|
+
custodyProtoCase(eng, {
|
|
3431
|
+
case: "writeRef",
|
|
3432
|
+
value: create(WriteRefRequestSchema, { repo: repoArgOfGitdir(gitdir), reference: ref, target: value })
|
|
3433
|
+
}, "writeRef");
|
|
3434
|
+
return { ok: true };
|
|
3435
|
+
},
|
|
3436
|
+
// restoreMain → promote already-imported custody only after the kernel re-admits the complete chain.
|
|
3437
|
+
// Unlike writeRef this is allowed to establish an absent main; it can never advance an existing one.
|
|
3438
|
+
restoreMain: (eng, ws, head) => custodyProtoCase(eng, {
|
|
3439
|
+
case: "restoreMain",
|
|
3440
|
+
value: create(RestoreMainRequestSchema, {
|
|
3441
|
+
target: create(WorkspaceTargetSchema, { repo: repoArgOf(ws), workspace: ws, branch: BRANCH }),
|
|
3442
|
+
head
|
|
3443
|
+
})
|
|
3444
|
+
}, "restoreMain"),
|
|
3445
|
+
// deleteRef → remove a local ref, idempotent (replaces git.deleteRef).
|
|
3446
|
+
deleteRef: (eng, gitdir, ref) => {
|
|
3447
|
+
custodyProtoCase(eng, {
|
|
3448
|
+
case: "deleteRef",
|
|
3449
|
+
value: create(DeleteRefRequestSchema, { repo: repoArgOfGitdir(gitdir), reference: ref })
|
|
3450
|
+
}, "deleteRef");
|
|
3451
|
+
return { ok: true };
|
|
3452
|
+
},
|
|
3453
|
+
// applyPack → ingest a pack's objects into ws's repo (kernel apply_pack; refs are the caller's job).
|
|
3454
|
+
applyPack: (eng, ws, packBytes) => applyPackInto(eng, ws, packBytes),
|
|
3455
|
+
// repoStats → kernel-owned physical custody accounting (host never walks Git's loose/pack layout).
|
|
3456
|
+
repoStats: (eng, ws) => {
|
|
3457
|
+
const stats2 = custodyProtoCase(eng, {
|
|
3458
|
+
case: "repoStats",
|
|
3459
|
+
value: create(RepoStatsRequestSchema, { repo: repoArgOf(ws) })
|
|
3460
|
+
}, "repoStats");
|
|
3461
|
+
return {
|
|
3462
|
+
ok: true,
|
|
3463
|
+
totalBytes: Number(stats2.totalBytes),
|
|
3464
|
+
objectBytes: Number(stats2.objectBytes),
|
|
3465
|
+
looseObjects: Number(stats2.looseObjects),
|
|
3466
|
+
looseBytes: Number(stats2.looseBytes),
|
|
3467
|
+
packFiles: Number(stats2.packFiles),
|
|
3468
|
+
packBytes: Number(stats2.packBytes),
|
|
3469
|
+
indexBytes: Number(stats2.indexBytes)
|
|
3470
|
+
};
|
|
3471
|
+
},
|
|
3472
|
+
// writeMetaCommit → blobs→tree→commit→ref for a CUSTODY-META fact (checkpoint/refused/outbox/shape).
|
|
3473
|
+
// `files`: [{ path, bytes:Uint8Array }]; returns the commit oid (replaces writeBlob+writeTree+writeCommit[+writeRef]).
|
|
3474
|
+
writeMetaCommit: (eng, gitdir, { parents = [], files, message = "nomos custody meta", timeSecs = 0, ref = "" }) => custodyProtoCase(eng, {
|
|
3475
|
+
case: "writeMetaCommit",
|
|
3476
|
+
value: create(WriteMetaCommitRequestSchema, {
|
|
3477
|
+
repo: repoArgOfGitdir(gitdir),
|
|
3478
|
+
parents,
|
|
3479
|
+
files: files.map((file) => ({ path: file.path, content: file.bytes })),
|
|
3480
|
+
message,
|
|
3481
|
+
timeSeconds: BigInt(timeSecs),
|
|
3482
|
+
reference: ref || void 0
|
|
3483
|
+
})
|
|
3484
|
+
}, "writeMetaCommit").oid
|
|
3485
|
+
};
|
|
3486
|
+
closureInstallPayload = (hash, installedBy, options = {}) => ({
|
|
3487
|
+
domainHash: hash,
|
|
3488
|
+
installedBy,
|
|
3489
|
+
dependencies: [],
|
|
3490
|
+
...options.supersedes ? { supersedes: options.supersedes } : {},
|
|
3491
|
+
...options.dispositions ? { dispositions: options.dispositions } : {},
|
|
3492
|
+
finalizers: []
|
|
3493
|
+
});
|
|
3494
|
+
routeTagHexOfHomeKey = async (homeKey) => (await sha256hex(`nomos-route:${homeKey}`)).slice(0, 12);
|
|
3495
|
+
SUMMARY_SEP = "";
|
|
3496
|
+
summaryKey = (readId, group) => `${readId}${SUMMARY_SEP}${group}`;
|
|
3497
|
+
splitSummaryKey = (key) => {
|
|
3498
|
+
const i = key.indexOf(SUMMARY_SEP);
|
|
3499
|
+
return [key.slice(0, i), key.slice(i + 1)];
|
|
3500
|
+
};
|
|
3501
|
+
NOMOS_SHARD_ROWS_READ = "nomosShardRows";
|
|
3502
|
+
groupOf = (read, data) => {
|
|
3503
|
+
if (read.by === null) return "";
|
|
3504
|
+
const v = data ? data[read.by] : void 0;
|
|
3505
|
+
return v === void 0 || v === null ? void 0 : String(v);
|
|
3506
|
+
};
|
|
3507
|
+
tallyOf = (eng, ws, read, group) => read.kind === "count" ? count(eng, ws, read.id, group).count : read.kind === "sum" ? sum(eng, ws, read.id, group).sum : extremum(eng, ws, read.id, read.kind, group).value;
|
|
3508
|
+
isExtremumRead = (read) => read.kind === "min" || read.kind === "max";
|
|
3509
|
+
extremumMonotone = (read, prev, next) => next === null && prev === null || next !== null && (prev === null || (read.kind === "min" ? next <= prev : next >= prev));
|
|
3510
|
+
CKPT_REF = (lawHash) => `refs/meta/checkpoint/${lawHash}`;
|
|
3511
|
+
pushVia = (ledger, fn) => ledger && ledger.pushLane ? ledger.pushLane(fn) : fn();
|
|
3512
|
+
fullRef = (r) => r === "HEAD" || r.startsWith("refs/") ? r : `refs/heads/${r}`;
|
|
3513
|
+
applyPackInto = (eng, ws, pack, head = null) => {
|
|
3514
|
+
if (!pack || !pack.length) return;
|
|
3515
|
+
custodyProtoCase(eng, {
|
|
3516
|
+
case: "applyPack",
|
|
3517
|
+
value: create(ApplyPackRequestSchema, {
|
|
3518
|
+
repo: repoArgOf(ws),
|
|
3519
|
+
source: { case: "pack", value: pack },
|
|
3520
|
+
head: head || void 0
|
|
3521
|
+
})
|
|
3522
|
+
}, "applyPack");
|
|
3523
|
+
};
|
|
3524
|
+
importCustodyObjects = (eng, ws, pack, head) => applyPackInto(eng, ws, pack, head);
|
|
3525
|
+
syncCandidate = (eng, ws, fromBase, toHead) => (() => {
|
|
3526
|
+
const response = callProto(eng.ex, {
|
|
3527
|
+
case: "sync",
|
|
3528
|
+
value: create(SyncRequestSchema, { target: protoTarget(ws), fromBase, toHead })
|
|
3529
|
+
}, eng.STDERR);
|
|
3530
|
+
if (response.outcome.case !== "sync") {
|
|
3531
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for sync request`);
|
|
3532
|
+
}
|
|
3533
|
+
return jsStruct(response.outcome.value.result);
|
|
3534
|
+
})();
|
|
3535
|
+
custodyLsRefs = (ledger, prefix = null) => lsRefs(ledger.remote, ledger.headers || {}, { service: "git-upload-pack", prefix });
|
|
3536
|
+
queryArguments = (paramsJson) => {
|
|
3537
|
+
const value = JSON.parse(paramsJson || "{}");
|
|
3538
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
3539
|
+
throw new Error("query arguments must be a JSON object");
|
|
3540
|
+
}
|
|
3541
|
+
return value;
|
|
3542
|
+
};
|
|
3543
|
+
queryAuthorityOptions = (principal, keys, authToken, nowUnix, authorSecret) => ({ principal, keys, authToken, nowUnix, authorSecret });
|
|
3544
|
+
qById = (eng, ws, id, principal = "", keys = [], authToken = "", nowUnix = 0, authorSecret = "") => applicationQueryProto(eng, ws, {
|
|
3545
|
+
case: "byId",
|
|
3546
|
+
value: create(ByIdQuerySchema, { aggregateId: id, principal })
|
|
3547
|
+
}, queryAuthorityOptions(principal, keys, authToken, nowUnix, authorSecret));
|
|
3548
|
+
query = (eng, ws, queryId, paramsJson, principal = "", keys = [], authToken = "", nowUnix = 0, authorSecret = "") => applicationQueryProto(eng, ws, {
|
|
3549
|
+
case: "rows",
|
|
3550
|
+
value: create(RowsQuerySchema, { id: queryId, arguments: protoStruct(queryArguments(paramsJson)), principal })
|
|
3551
|
+
}, queryAuthorityOptions(principal, keys, authToken, nowUnix, authorSecret));
|
|
3552
|
+
queryPage = (eng, ws, queryId, paramsJson, page = {}, principal = "", keys = [], authToken = "", nowUnix = 0, authorSecret = "") => applicationQueryProto(eng, ws, {
|
|
3553
|
+
case: "page",
|
|
3554
|
+
value: create(PageQuerySchema, {
|
|
3555
|
+
id: queryId,
|
|
3556
|
+
arguments: protoStruct(queryArguments(paramsJson)),
|
|
3557
|
+
limit: page.pageSize ?? 100,
|
|
3558
|
+
after: page.cursor ?? "",
|
|
3559
|
+
principal
|
|
3560
|
+
})
|
|
3561
|
+
}, queryAuthorityOptions(principal, keys, authToken, nowUnix, authorSecret));
|
|
3562
|
+
queryProfile = (eng, ws, queryId, paramsJson, principal = "", keys = [], authToken = "", nowUnix = 0, authorSecret = "") => {
|
|
3563
|
+
const value = applicationQueryProto(eng, ws, {
|
|
3564
|
+
case: "rows",
|
|
3565
|
+
value: create(RowsQuerySchema, { id: queryId, arguments: protoStruct(queryArguments(paramsJson)), principal })
|
|
3566
|
+
}, { ...queryAuthorityOptions(principal, keys, authToken, nowUnix, authorSecret), spans: true });
|
|
3567
|
+
const profile = namedQueryProto(eng, ws, QueryOperation.DEVELOPER_SPANS);
|
|
3568
|
+
return { ok: true, value, kernelSpans: profile.kernelSpans };
|
|
3569
|
+
};
|
|
3570
|
+
authorizationAddress = (address) => {
|
|
3571
|
+
const colon = address.indexOf(":");
|
|
3572
|
+
if (colon <= 0 || colon === address.length - 1) throw new Error(`invalid authorization address '${address}'`);
|
|
3573
|
+
return { type: address.slice(0, colon), id: address.slice(colon + 1) };
|
|
3574
|
+
};
|
|
3575
|
+
authorizationSubject = (address) => {
|
|
3576
|
+
const hash = address.lastIndexOf("#");
|
|
3577
|
+
const object = authorizationAddress(hash < 0 ? address : address.slice(0, hash));
|
|
3578
|
+
return create(AuthorizationSubjectSchema, {
|
|
3579
|
+
...object,
|
|
3580
|
+
relation: hash < 0 ? void 0 : address.slice(hash + 1)
|
|
3581
|
+
});
|
|
3582
|
+
};
|
|
3583
|
+
currentAuthorizationFrontier = () => create(AuthorizationConsistencySchema, {
|
|
3584
|
+
requirement: { case: "currentVerifiedFrontier", value: true }
|
|
3585
|
+
});
|
|
3586
|
+
check = (eng, ws, object, relation, subject) => {
|
|
3587
|
+
const response = callProto(eng.ex, {
|
|
3588
|
+
case: "query",
|
|
3589
|
+
value: create(QueryRequestSchema, {
|
|
3590
|
+
target: protoTarget(ws),
|
|
3591
|
+
query: {
|
|
3592
|
+
case: "authorizationCheck",
|
|
3593
|
+
value: create(AuthorizationCheckRequestSchema, {
|
|
3594
|
+
resource: create(AuthorizationObjectSchema, authorizationAddress(object)),
|
|
3595
|
+
permission: relation,
|
|
3596
|
+
subject: authorizationSubject(subject),
|
|
3597
|
+
consistency: currentAuthorizationFrontier()
|
|
3598
|
+
})
|
|
3599
|
+
}
|
|
3600
|
+
})
|
|
3601
|
+
}, eng.STDERR);
|
|
3602
|
+
if (response.outcome.case !== "query" || response.outcome.value.result.case !== "authorizationCheck") {
|
|
3603
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for authorization check`);
|
|
3604
|
+
}
|
|
3605
|
+
return { ok: true, allowed: response.outcome.value.result.value.allowed, basis: response.outcome.value.result.value.basis };
|
|
3606
|
+
};
|
|
3607
|
+
expand = (eng, ws, object, relation) => {
|
|
3608
|
+
const response = callProto(eng.ex, {
|
|
3609
|
+
case: "query",
|
|
3610
|
+
value: create(QueryRequestSchema, {
|
|
3611
|
+
target: protoTarget(ws),
|
|
3612
|
+
query: {
|
|
3613
|
+
case: "authorizationExpand",
|
|
3614
|
+
value: create(AuthorizationExpandRequestSchema, {
|
|
3615
|
+
resource: create(AuthorizationObjectSchema, authorizationAddress(object)),
|
|
3616
|
+
permission: relation,
|
|
3617
|
+
consistency: currentAuthorizationFrontier(),
|
|
3618
|
+
limit: 1e4
|
|
3619
|
+
})
|
|
3620
|
+
}
|
|
3621
|
+
})
|
|
3622
|
+
}, eng.STDERR);
|
|
3623
|
+
if (response.outcome.case !== "query" || response.outcome.value.result.case !== "authorizationExpand") {
|
|
3624
|
+
throw new Error(`kernel returned ${response.outcome.case || "empty"} for authorization expand`);
|
|
3625
|
+
}
|
|
3626
|
+
return {
|
|
3627
|
+
ok: true,
|
|
3628
|
+
subjects: response.outcome.value.result.value.subjects.map((value) => `${value.type}:${value.id}${value.relation ? `#${value.relation}` : ""}`),
|
|
3629
|
+
basis: response.outcome.value.result.value.basis,
|
|
3630
|
+
next: response.outcome.value.result.value.next
|
|
3631
|
+
};
|
|
3632
|
+
};
|
|
3633
|
+
cryptoSealField = (eng, { scopeKey, scope, epoch, aggSid, fieldSid, plaintext }) => namedQueryProto(eng, "root", QueryOperation.CRYPTO_SEAL_FIELD, { scopeKey, scope, epoch, aggSid, fieldSid, plaintext }).envelope;
|
|
3634
|
+
cryptoOwnedScopeKey = (eng, workspace, authorSecret, scope, principal = "", requireSeat = true, record, recordEpoch = 0, recordWrap) => {
|
|
3635
|
+
const recordObject = record === void 0 ? void 0 : `${record.type}:${record.id}`;
|
|
3636
|
+
const derived = namedQueryProto(eng, workspace, QueryOperation.CRYPTO_OWNED_SCOPE_KEY, {
|
|
3637
|
+
custodyWorkspace: workspace,
|
|
3638
|
+
principal,
|
|
3639
|
+
authorSecret,
|
|
3640
|
+
scope,
|
|
3641
|
+
...recordObject === void 0 ? {} : { recordObject, recordEpoch },
|
|
3642
|
+
...recordWrap === void 0 ? {} : { recordWrap }
|
|
3643
|
+
});
|
|
3644
|
+
const ownedKeySubject = String(derived.ownedKeySubject || "");
|
|
3645
|
+
if (!requireSeat) {
|
|
3646
|
+
return {
|
|
3647
|
+
scope: String(derived.scope || scope),
|
|
3648
|
+
epoch: Number(derived.epoch) || 0,
|
|
3649
|
+
key: String(derived.scopeKey || ""),
|
|
3650
|
+
ownedKeySubject,
|
|
3651
|
+
ownedCustody: typeof derived.ownedCustody === "string" ? derived.ownedCustody : void 0,
|
|
3652
|
+
keyCommitment: typeof derived.keyCommitment === "string" ? derived.keyCommitment : void 0,
|
|
3653
|
+
principalWrappingPublic: typeof derived.principalWrappingPublic === "string" ? derived.principalWrappingPublic : void 0
|
|
3654
|
+
};
|
|
3655
|
+
}
|
|
3656
|
+
if (principal) {
|
|
3657
|
+
let hex = "";
|
|
3658
|
+
for (const byte of enc3.encode(principal)) hex += byte.toString(16).padStart(2, "0");
|
|
3659
|
+
const object = `nomos-owned-principal:${hex || "00"}`;
|
|
3660
|
+
const rows = qById(eng, workspace, `reltuple-${object}-nomos_internal_owned_device_key_7c1f5e`);
|
|
3661
|
+
const row = Array.isArray(rows) ? rows[0] : rows?.rows?.[0];
|
|
3662
|
+
const leaves = row?.data?.subjects ?? row?.subjects ?? {};
|
|
3663
|
+
const leaf = (raw) => {
|
|
3664
|
+
if (raw && typeof raw === "object") return raw;
|
|
3665
|
+
try {
|
|
3666
|
+
return typeof raw === "string" ? JSON.parse(raw) : {};
|
|
3667
|
+
} catch {
|
|
3668
|
+
return {};
|
|
3669
|
+
}
|
|
3670
|
+
};
|
|
3671
|
+
const active = Object.entries(leaves).filter(([, raw]) => leaf(raw).status === "active").map(([subject]) => subject);
|
|
3672
|
+
if (active.length === 0 && Object.keys(leaves).length === 0) {
|
|
3673
|
+
return {
|
|
3674
|
+
scope: String(derived.scope || scope),
|
|
3675
|
+
epoch: Number(derived.epoch) || 0,
|
|
3676
|
+
key: String(derived.scopeKey || ""),
|
|
3677
|
+
ownedKeySubject,
|
|
3678
|
+
ownedCustody: typeof derived.ownedCustody === "string" ? derived.ownedCustody : void 0,
|
|
3679
|
+
keyCommitment: typeof derived.keyCommitment === "string" ? derived.keyCommitment : void 0,
|
|
3680
|
+
principalWrappingPublic: typeof derived.principalWrappingPublic === "string" ? derived.principalWrappingPublic : void 0
|
|
3681
|
+
};
|
|
3682
|
+
}
|
|
3683
|
+
if (!active.includes(ownedKeySubject)) {
|
|
3684
|
+
throw new Error(
|
|
3685
|
+
"this device is waiting for approval \u2014 approve its opaque request on an already-working device"
|
|
3686
|
+
);
|
|
3687
|
+
}
|
|
3688
|
+
const custody = String(leaf(leaves[ownedKeySubject]).ownedCustody || "");
|
|
3689
|
+
if (!custody) throw new Error("the approved device has no owned-data handoff");
|
|
3690
|
+
const opened = namedQueryProto(eng, workspace, QueryOperation.CRYPTO_OWNED_SCOPE_KEY, {
|
|
3691
|
+
workspace,
|
|
3692
|
+
principal,
|
|
3693
|
+
authorSecret,
|
|
3694
|
+
scope,
|
|
3695
|
+
ownedCustody: custody,
|
|
3696
|
+
...recordObject === void 0 ? {} : { recordObject, recordEpoch },
|
|
3697
|
+
...recordWrap === void 0 ? {} : { recordWrap }
|
|
3698
|
+
});
|
|
3699
|
+
return {
|
|
3700
|
+
scope: String(opened.scope || scope),
|
|
3701
|
+
epoch: Number(opened.epoch) || 0,
|
|
3702
|
+
key: String(opened.scopeKey || ""),
|
|
3703
|
+
ownedKeySubject,
|
|
3704
|
+
keyCommitment: typeof opened.keyCommitment === "string" ? opened.keyCommitment : void 0,
|
|
3705
|
+
principalWrappingPublic: typeof opened.principalWrappingPublic === "string" ? opened.principalWrappingPublic : void 0
|
|
3706
|
+
};
|
|
3707
|
+
}
|
|
3708
|
+
return {
|
|
3709
|
+
scope: String(derived.scope || scope),
|
|
3710
|
+
epoch: Number(derived.epoch) || 0,
|
|
3711
|
+
key: String(derived.scopeKey || ""),
|
|
3712
|
+
ownedKeySubject,
|
|
3713
|
+
ownedCustody: typeof derived.ownedCustody === "string" ? derived.ownedCustody : void 0,
|
|
3714
|
+
keyCommitment: typeof derived.keyCommitment === "string" ? derived.keyCommitment : void 0,
|
|
3715
|
+
principalWrappingPublic: typeof derived.principalWrappingPublic === "string" ? derived.principalWrappingPublic : void 0
|
|
3716
|
+
};
|
|
3717
|
+
};
|
|
3718
|
+
cryptoOwnedDeviceRequest = (eng, workspace, principal, authorSecret, scope) => String(namedQueryProto(eng, workspace, QueryOperation.CRYPTO_OWNED_DEVICE_REQUEST, {
|
|
3719
|
+
workspace,
|
|
3720
|
+
principal,
|
|
3721
|
+
authorSecret,
|
|
3722
|
+
scope
|
|
3723
|
+
}).request || "");
|
|
3724
|
+
cryptoOwnedPrepareApproval = (eng, args) => namedQueryProto(eng, args.workspace, QueryOperation.CRYPTO_OWNED_PREPARE_APPROVAL, args);
|
|
3725
|
+
cryptoOwnedPrepareRecovery = (eng, args) => namedQueryProto(eng, args.workspace, QueryOperation.CRYPTO_OWNED_PREPARE_RECOVERY, args);
|
|
3726
|
+
cryptoKeygen = (eng) => namedQueryProto(eng, "root", QueryOperation.CRYPTO_KEYGEN);
|
|
3727
|
+
authorKeygen = (eng) => namedQueryProto(eng, "root", QueryOperation.AUTHOR_KEYGEN);
|
|
3728
|
+
eraCertSign = (eng, args) => namedQueryProto(eng, "root", QueryOperation.ERA_CERT_SIGN, args);
|
|
3729
|
+
delegationCertSign = (eng, { secret, grantorId, relation, subject, epoch, certChain }) => namedQueryProto(eng, "root", QueryOperation.DELEGATION_CERT_SIGN, { secret, grantorId, relation, subject, epoch, ...certChain ? { certChain } : {} });
|
|
3730
|
+
attestationSign = (eng, { secret, asserterWorkspace, object, relation, subject, attestedAt }) => namedQueryProto(eng, asserterWorkspace, QueryOperation.ATTESTATION_SIGN, { secret, asserterWorkspace, object, relation, subject, attestedAt });
|
|
3731
|
+
certSign = (eng, {
|
|
3732
|
+
child,
|
|
3733
|
+
founder,
|
|
3734
|
+
verified,
|
|
3735
|
+
parentKey,
|
|
3736
|
+
parentId,
|
|
3737
|
+
epoch,
|
|
3738
|
+
secret,
|
|
3739
|
+
verifiedVia,
|
|
3740
|
+
idpToken,
|
|
3741
|
+
capturedClock,
|
|
3742
|
+
authProviderIssuer,
|
|
3743
|
+
authProviderJwks,
|
|
3744
|
+
authProviderAudience
|
|
3745
|
+
}) => namedQueryProto(eng, "root", QueryOperation.CERT_SIGN, {
|
|
3746
|
+
child,
|
|
3747
|
+
founder,
|
|
3748
|
+
verified,
|
|
3749
|
+
parentKey,
|
|
3750
|
+
parentId,
|
|
3751
|
+
epoch,
|
|
3752
|
+
secret,
|
|
3753
|
+
// forwarded only when present (the op reads them optionally; absent ⇒ classic cert bytes).
|
|
3754
|
+
...verifiedVia !== void 0 ? { verifiedVia } : {},
|
|
3755
|
+
...idpToken !== void 0 ? { idpToken } : {},
|
|
3756
|
+
...capturedClock !== void 0 ? { capturedClock } : {},
|
|
3757
|
+
...authProviderIssuer !== void 0 ? { authProviderIssuer } : {},
|
|
3758
|
+
...authProviderJwks !== void 0 ? { authProviderJwks } : {},
|
|
3759
|
+
...authProviderAudience !== void 0 ? { authProviderAudience } : {}
|
|
3760
|
+
}).cert;
|
|
3761
|
+
cryptoWrapKey = (eng, { recipientPub, scopeKey }) => namedQueryProto(eng, "root", QueryOperation.CRYPTO_WRAP_KEY, { recipientPub, scopeKey });
|
|
3762
|
+
cryptoUnwrapKey = (eng, { secret, hpkeEpk, ct }) => namedQueryProto(eng, "root", QueryOperation.CRYPTO_UNWRAP_KEY, { secret, hpkeEpk, ct }).scopeKey;
|
|
3763
|
+
readPosture = (eng, ws, principal = "", authToken = "", nowUnix = 0, authorSecret = "") => namedQueryProto(
|
|
3764
|
+
eng,
|
|
3765
|
+
ws,
|
|
3766
|
+
QueryOperation.READ_POSTURE,
|
|
3767
|
+
{},
|
|
3768
|
+
queryAuthorityOptions(principal, [], authToken, nowUnix, authorSecret)
|
|
3769
|
+
);
|
|
3770
|
+
count = (eng, ws, countId, groupKey, principal = "", authToken = "", nowUnix = 0, authorSecret = "") => applicationQueryProto(eng, ws, {
|
|
3771
|
+
case: "count",
|
|
3772
|
+
value: create(TallyQuerySchema, { id: countId, arguments: protoStruct({ groupKey: groupKey ?? null }), principal })
|
|
3773
|
+
}, queryAuthorityOptions(principal, [], authToken, nowUnix, authorSecret));
|
|
3774
|
+
sum = (eng, ws, sumId, groupKey, principal = "", authToken = "", nowUnix = 0, authorSecret = "") => applicationQueryProto(eng, ws, {
|
|
3775
|
+
case: "sum",
|
|
3776
|
+
value: create(TallyQuerySchema, { id: sumId, arguments: protoStruct({ groupKey: groupKey ?? null }), principal })
|
|
3777
|
+
}, queryAuthorityOptions(principal, [], authToken, nowUnix, authorSecret));
|
|
3778
|
+
pendingConflicts = (eng, ws, principal = "", aggregateType = "", authToken = "", nowUnix = 0, authorSecret = "") => namedQueryProto(
|
|
3779
|
+
eng,
|
|
3780
|
+
ws,
|
|
3781
|
+
QueryOperation.PENDING_CONFLICTS,
|
|
3782
|
+
{ aggregateType },
|
|
3783
|
+
queryAuthorityOptions(principal, [], authToken, nowUnix, authorSecret)
|
|
3784
|
+
);
|
|
3785
|
+
pendingConflictSummary = (eng, ws, principal = "", authToken = "", nowUnix = 0, authorSecret = "") => namedQueryProto(
|
|
3786
|
+
eng,
|
|
3787
|
+
ws,
|
|
3788
|
+
QueryOperation.PENDING_CONFLICT_SUMMARY,
|
|
3789
|
+
{},
|
|
3790
|
+
queryAuthorityOptions(principal, [], authToken, nowUnix, authorSecret)
|
|
3791
|
+
);
|
|
3792
|
+
spatialBboxParams = (bbox) => {
|
|
3793
|
+
const minX = bbox.minX ?? bbox.minLng, minY = bbox.minY ?? bbox.minLat, maxX = bbox.maxX ?? bbox.maxLng, maxY = bbox.maxY ?? bbox.maxLat;
|
|
3794
|
+
return { minX, minY, maxX, maxY, minLng: minX, minLat: minY, maxLng: maxX, maxLat: maxY };
|
|
3795
|
+
};
|
|
3796
|
+
spatialWithin = (eng, ws, spatialId, bbox, principal = "", authToken = "", nowUnix = 0, authorSecret = "") => applicationQueryProto(eng, ws, {
|
|
3797
|
+
case: "spatial",
|
|
3798
|
+
value: create(SpatialQuerySchema, { id: spatialId, arguments: protoStruct(spatialBboxParams(bbox)), principal })
|
|
3799
|
+
}, queryAuthorityOptions(principal, [], authToken, nowUnix, authorSecret));
|
|
3800
|
+
extremum = (eng, ws, extremumId, kind, groupKey, principal = "", authToken = "", nowUnix = 0, authorSecret = "") => namedQueryProto(
|
|
3801
|
+
eng,
|
|
3802
|
+
ws,
|
|
3803
|
+
QueryOperation.EXTREMUM,
|
|
3804
|
+
{ extremumId, kind, groupKey: groupKey ?? "" },
|
|
3805
|
+
queryAuthorityOptions(principal, [], authToken, nowUnix, authorSecret)
|
|
3806
|
+
);
|
|
3807
|
+
nomosActive = (eng, ws) => qById(eng, ws, `domain-installation:${eng.hashes.nomos}`).length > 0;
|
|
3808
|
+
refusedRefName = (offerId) => `refs/heads/refused/${String(offerId || "unknown").replace(/[^A-Za-z0-9._-]/g, "_")}`;
|
|
3809
|
+
outboxRefName = (requestId) => `refs/heads/outbox/${String(requestId || "unknown").replace(/[^A-Za-z0-9._-]/g, "_")}`;
|
|
3810
|
+
GENESIS_WARRANT_ID = "genesis-warrant:self";
|
|
3811
|
+
isWarranted = (eng, ws) => qById(eng, ws, GENESIS_WARRANT_ID).length > 0;
|
|
3812
|
+
projectionStats = (eng, ws) => namedQueryProto(eng, ws || "root", QueryOperation.PROJECTION_STATS);
|
|
3813
|
+
memoryDropProbe = (eng, ws) => namedQueryProto(eng, ws, QueryOperation.MEMORY_DROP_PROBE);
|
|
3814
|
+
readiness = (eng, ws) => namedQueryProto(eng, ws, QueryOperation.READINESS);
|
|
3815
|
+
}
|
|
3816
|
+
});
|
|
3817
|
+
|
|
3818
|
+
// src/local_holon.ts
|
|
3819
|
+
var local_holon_exports = {};
|
|
3820
|
+
__export(local_holon_exports, {
|
|
3821
|
+
fetchRuntime: () => fetchRuntime,
|
|
3822
|
+
holonEngine: () => holonEngine,
|
|
3823
|
+
inspectLawArchive: () => inspectLawArchive,
|
|
3824
|
+
mountFresh: () => mountFresh,
|
|
3825
|
+
printVerdict: () => printVerdict,
|
|
3826
|
+
readLawArchive: () => readLawArchive,
|
|
3827
|
+
readTreeFromDisk: () => readTreeFromDisk,
|
|
3828
|
+
refreshRuntimeDir: () => refreshRuntimeDir,
|
|
3829
|
+
sealedIntentOf: () => sealedIntentOf,
|
|
3830
|
+
selectedRuntimeDir: () => selectedRuntimeDir,
|
|
3831
|
+
writeTreeToDisk: () => writeTreeToDisk
|
|
3832
|
+
});
|
|
3833
|
+
import { randomBytes } from "node:crypto";
|
|
3834
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
3835
|
+
import { dirname, join as join2, resolve } from "node:path";
|
|
3836
|
+
import { File as File2, Directory as Directory2 } from "@bjorn3/browser_wasi_shim";
|
|
3837
|
+
async function fetchBytesCached(url, cacheFile) {
|
|
3838
|
+
try {
|
|
3839
|
+
const r = await fetch(url);
|
|
3840
|
+
if (!r.ok) throw new Error(`${url} \u2192 ${r.status}`);
|
|
3841
|
+
const bytes = new Uint8Array(await r.arrayBuffer());
|
|
3842
|
+
mkdirSync(dirname(cacheFile), { recursive: true });
|
|
3843
|
+
writeFileSync(cacheFile, bytes);
|
|
3844
|
+
return bytes;
|
|
3845
|
+
} catch (e) {
|
|
3846
|
+
if (existsSync(cacheFile)) return new Uint8Array(readFileSync(cacheFile));
|
|
3847
|
+
throw e;
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
function selectedRuntimeDir() {
|
|
3851
|
+
return process.env["NOMOS_CANDIDATE_RUNTIME"] || process.env["NOMOS_OFFLINE_RUNTIME"] || join2(configDir(), "runtime");
|
|
3852
|
+
}
|
|
3853
|
+
async function fetchRuntime(cloud, kind = "production") {
|
|
3854
|
+
const cache = selectedRuntimeDir();
|
|
3855
|
+
let wasmBytes;
|
|
3856
|
+
const wasmName = kind === "test-mint" ? "holon-testmint.wasm" : "holon.wasm";
|
|
3857
|
+
const wasmUrl = kind === "test-mint" ? "holon-testmint.wasm" : "holon.wasm";
|
|
3858
|
+
const wasmCache = join2(cache, wasmName);
|
|
3859
|
+
const bootstrapCache = join2(cache, "bootstrap.law.usdz");
|
|
3860
|
+
const nomosCache = join2(cache, "nomos.law.usdz");
|
|
3861
|
+
const refresh = String(
|
|
3862
|
+
process.env["NOMOS_RUNTIME_REFRESH"] || (process.env["NOMOS_CANDIDATE_RUNTIME"] ? "never" : "auto")
|
|
3863
|
+
).toLowerCase();
|
|
3864
|
+
if (refresh === "never") {
|
|
3865
|
+
if (!existsSync(wasmCache) || !existsSync(bootstrapCache) || !existsSync(nomosCache)) {
|
|
3866
|
+
throw new Error(
|
|
3867
|
+
`offline runtime cache missing at ${cache} (${wasmName} + bootstrap.law.usdz + nomos.law.usdz); build or warm that exact runtime before running with NOMOS_RUNTIME_REFRESH=never`
|
|
3868
|
+
);
|
|
3869
|
+
}
|
|
3870
|
+
return {
|
|
3871
|
+
wasmBytes: new Uint8Array(readFileSync(wasmCache)),
|
|
3872
|
+
bootstrapLawUsdz: new Uint8Array(readFileSync(bootstrapCache)),
|
|
3873
|
+
nomosLawUsdz: new Uint8Array(readFileSync(nomosCache))
|
|
3874
|
+
};
|
|
3875
|
+
}
|
|
3876
|
+
const localWasm = process.env["NOMOS_LOCAL_WASM"];
|
|
3877
|
+
if (localWasm) {
|
|
3878
|
+
const bytes = new Uint8Array(readFileSync(localWasm));
|
|
3879
|
+
const [bootstrapLawUsdz2, nomosLawUsdz2] = await Promise.all([
|
|
3880
|
+
fetchBytesCached(`${cloud}/v1/runtime/bootstrap.law.usdz`, bootstrapCache),
|
|
3881
|
+
fetchBytesCached(`${cloud}/v1/runtime/nomos.law.usdz`, nomosCache)
|
|
3882
|
+
]);
|
|
3883
|
+
return { wasmBytes: bytes, bootstrapLawUsdz: bootstrapLawUsdz2, nomosLawUsdz: nomosLawUsdz2 };
|
|
3884
|
+
}
|
|
3885
|
+
try {
|
|
3886
|
+
const r = await fetch(`${cloud}/v1/runtime/${wasmUrl}`);
|
|
3887
|
+
if (!r.ok) throw new Error(`runtime wasm \u2192 ${r.status}`);
|
|
3888
|
+
wasmBytes = new Uint8Array(await r.arrayBuffer());
|
|
3889
|
+
mkdirSync(cache, { recursive: true });
|
|
3890
|
+
writeFileSync(wasmCache, wasmBytes);
|
|
3891
|
+
} catch (e) {
|
|
3892
|
+
if (!existsSync(wasmCache)) throw e;
|
|
3893
|
+
wasmBytes = new Uint8Array(readFileSync(wasmCache));
|
|
3894
|
+
}
|
|
3895
|
+
const [bootstrapLawUsdz, nomosLawUsdz] = await Promise.all([
|
|
3896
|
+
fetchBytesCached(`${cloud}/v1/runtime/bootstrap.law.usdz`, bootstrapCache),
|
|
3897
|
+
fetchBytesCached(`${cloud}/v1/runtime/nomos.law.usdz`, nomosCache)
|
|
3898
|
+
]);
|
|
3899
|
+
return { wasmBytes, bootstrapLawUsdz, nomosLawUsdz };
|
|
3900
|
+
}
|
|
3901
|
+
function atomicWriteRuntime(target, data) {
|
|
3902
|
+
const tmp = `${target}.tmp-${Math.random().toString(16).slice(2)}${Math.random().toString(16).slice(2)}`;
|
|
3903
|
+
writeFileSync(tmp, data);
|
|
3904
|
+
renameSync(tmp, target);
|
|
3905
|
+
}
|
|
3906
|
+
function runtimeDirIsWarm(runtimeDir) {
|
|
3907
|
+
try {
|
|
3908
|
+
const w = statSync(join2(runtimeDir, "holon.wasm")).mtimeMs;
|
|
3909
|
+
const t = statSync(join2(runtimeDir, "holon-testmint.wasm")).mtimeMs;
|
|
3910
|
+
const b = statSync(join2(runtimeDir, "bootstrap.law.usdz")).mtimeMs;
|
|
3911
|
+
const n = statSync(join2(runtimeDir, "nomos.law.usdz")).mtimeMs;
|
|
3912
|
+
return Date.now() - Math.min(w, t, b, n) < RUNTIME_FRESH_MS;
|
|
3913
|
+
} catch {
|
|
3914
|
+
return false;
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
async function refreshRuntimeDir(cloud, runtimeDir) {
|
|
3918
|
+
const candidate = process.env["NOMOS_CANDIDATE_RUNTIME"];
|
|
3919
|
+
if (candidate && resolve(runtimeDir) === resolve(candidate)) return false;
|
|
3920
|
+
const mode = String(process.env["NOMOS_RUNTIME_REFRESH"] || "auto").toLowerCase();
|
|
3921
|
+
if (mode === "never") return false;
|
|
3922
|
+
if (mode !== "always") {
|
|
3923
|
+
if (_refreshedDirsThisProcess.has(runtimeDir)) return false;
|
|
3924
|
+
if (runtimeDirIsWarm(runtimeDir)) return false;
|
|
3925
|
+
}
|
|
3926
|
+
try {
|
|
3927
|
+
const r = await fetch(`${cloud}/v1/runtime/holon.wasm`);
|
|
3928
|
+
if (!r.ok) throw new Error(`runtime wasm \u2192 ${r.status}`);
|
|
3929
|
+
const wasmBytes = new Uint8Array(await r.arrayBuffer());
|
|
3930
|
+
const testmint = await fetch(`${cloud}/v1/runtime/holon-testmint.wasm`);
|
|
3931
|
+
if (!testmint.ok) throw new Error(`test-mint runtime wasm \u2192 ${testmint.status}`);
|
|
3932
|
+
const testmintBytes = new Uint8Array(await testmint.arrayBuffer());
|
|
3933
|
+
const bootstrap = await fetch(`${cloud}/v1/runtime/bootstrap.law.usdz`);
|
|
3934
|
+
if (!bootstrap.ok) throw new Error(`bootstrap law \u2192 ${bootstrap.status}`);
|
|
3935
|
+
const bootstrapBytes = new Uint8Array(await bootstrap.arrayBuffer());
|
|
3936
|
+
const nomos = await fetch(`${cloud}/v1/runtime/nomos.law.usdz`);
|
|
3937
|
+
if (!nomos.ok) throw new Error(`Nomos law \u2192 ${nomos.status}`);
|
|
3938
|
+
const nomosBytes = new Uint8Array(await nomos.arrayBuffer());
|
|
3939
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
3940
|
+
atomicWriteRuntime(join2(runtimeDir, "holon.wasm"), wasmBytes);
|
|
3941
|
+
atomicWriteRuntime(join2(runtimeDir, "holon-testmint.wasm"), testmintBytes);
|
|
3942
|
+
atomicWriteRuntime(join2(runtimeDir, "bootstrap.law.usdz"), bootstrapBytes);
|
|
3943
|
+
atomicWriteRuntime(join2(runtimeDir, "nomos.law.usdz"), nomosBytes);
|
|
3944
|
+
_refreshedDirsThisProcess.add(runtimeDir);
|
|
3945
|
+
return true;
|
|
3946
|
+
} catch {
|
|
3947
|
+
return false;
|
|
3948
|
+
}
|
|
3949
|
+
}
|
|
3950
|
+
function readLawArchive(lawUsdzFile) {
|
|
3951
|
+
if (!lawUsdzFile.endsWith(".law.usdz")) {
|
|
3952
|
+
throw new Error(`${lawUsdzFile} is not a canonical .law.usdz archive`);
|
|
3953
|
+
}
|
|
3954
|
+
if (!existsSync(lawUsdzFile)) {
|
|
3955
|
+
throw new Error(`law archive not found: ${lawUsdzFile} \u2014 run \`githolon compile\` first`);
|
|
3956
|
+
}
|
|
3957
|
+
const bytes = new Uint8Array(readFileSync(lawUsdzFile));
|
|
3958
|
+
if (bytes.byteLength < 4 || bytes[0] !== 80 || bytes[1] !== 75 || bytes[2] !== 3 || bytes[3] !== 4) {
|
|
3959
|
+
throw new Error(`${lawUsdzFile} is not a USDZ ZIP archive`);
|
|
3960
|
+
}
|
|
3961
|
+
return bytes;
|
|
3962
|
+
}
|
|
3963
|
+
function inspectLawArchive(eng, lawUsdzFile) {
|
|
3964
|
+
const lawUsdz = readLawArchive(lawUsdzFile);
|
|
3965
|
+
const staged = stageLawClosure(eng, lawUsdz, lawUsdzFile.split(/[\\/]/).pop() ?? "candidate-law");
|
|
3966
|
+
if (!/^[0-9a-f]{64}$/.test(staged.identity)) {
|
|
3967
|
+
throw new Error(`kernel returned invalid law closure identity for ${lawUsdzFile}`);
|
|
3968
|
+
}
|
|
3969
|
+
return {
|
|
3970
|
+
identity: staged.identity,
|
|
3971
|
+
domainKeys: staged.domainKeys,
|
|
3972
|
+
rootLogicalPath: staged.rootLogicalPath,
|
|
3973
|
+
assetCount: staged.assetCount,
|
|
3974
|
+
primCount: staged.primCount,
|
|
3975
|
+
lawUsdz
|
|
3976
|
+
};
|
|
3977
|
+
}
|
|
3978
|
+
function writeTreeToDisk(dir, diskPath) {
|
|
3979
|
+
mkdirSync(diskPath, { recursive: true });
|
|
3980
|
+
for (const [name, inode] of dir.contents) {
|
|
3981
|
+
const p = join2(diskPath, name);
|
|
3982
|
+
if (inode.contents instanceof Map) writeTreeToDisk(inode, p);
|
|
3983
|
+
else writeFileSync(p, inode.data ?? new Uint8Array(0));
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
function readTreeFromDisk(diskPath) {
|
|
3987
|
+
const contents = /* @__PURE__ */ new Map();
|
|
3988
|
+
for (const name of readdirSync(diskPath)) {
|
|
3989
|
+
const p = join2(diskPath, name);
|
|
3990
|
+
if (statSync(p).isDirectory()) contents.set(name, readTreeFromDisk(p));
|
|
3991
|
+
else contents.set(name, new File2(readFileSync(p)));
|
|
3992
|
+
}
|
|
3993
|
+
return new Directory2(contents);
|
|
3994
|
+
}
|
|
3995
|
+
async function holonEngine(cloud, installedBy, runtimeKind = "production", suppliedRuntime) {
|
|
3996
|
+
const runtime = suppliedRuntime ?? await fetchRuntime(cloud, runtimeKind);
|
|
3997
|
+
const replica = BigInt(`0x${randomBytes(8).toString("hex")}`) & (1n << 63n) - 1n;
|
|
3998
|
+
const eng = await createEngine({
|
|
3999
|
+
wasmModule: await WebAssembly.compile(runtime.wasmBytes),
|
|
4000
|
+
bootstrapLawUsdz: runtime.bootstrapLawUsdz,
|
|
4001
|
+
nomosLawUsdz: runtime.nomosLawUsdz,
|
|
4002
|
+
replica,
|
|
4003
|
+
installedBy
|
|
4004
|
+
});
|
|
4005
|
+
return { eng, runtime };
|
|
4006
|
+
}
|
|
4007
|
+
async function mountFresh(eng, ws) {
|
|
4008
|
+
await mountWorkspace(eng, ws, { remote: "https://unborn.invalid/", headers: {} });
|
|
4009
|
+
}
|
|
4010
|
+
function sealedIntentOf(eng, ws, res) {
|
|
4011
|
+
if (typeof res.intentOut !== "string") return void 0;
|
|
4012
|
+
const f = eng.preopen.dir.contents.get("ws").contents.get(ws)?.contents.get(res.intentOut);
|
|
4013
|
+
if (f === void 0 || !(f.data instanceof Uint8Array)) return void 0;
|
|
4014
|
+
try {
|
|
4015
|
+
return kgit.inspectChange(eng, f.data);
|
|
4016
|
+
} catch {
|
|
4017
|
+
return void 0;
|
|
4018
|
+
}
|
|
4019
|
+
}
|
|
4020
|
+
function printVerdict(v) {
|
|
4021
|
+
if (v["valid"] === true) {
|
|
4022
|
+
out(`\u2713 chain VALID \u2014 head ${String(v["head"]).slice(0, 12)}\u2026, ${v["intents"]} intent(s), ${v["plansRerun"]} plan(s) re-run`);
|
|
4023
|
+
out(` controller ${String(v["controllerHash"]).slice(0, 12)}\u2026 | installed: ${v["installedDomains"]?.map((h) => h.slice(0, 12) + "\u2026").join(", ") ?? "\u2014"}`);
|
|
4024
|
+
return true;
|
|
4025
|
+
}
|
|
4026
|
+
err(`chain INVALID at ${v["check"]}${v["atIndex"] !== void 0 ? ` (intent ${v["atIndex"]})` : ""}: ${v["error"]}`);
|
|
4027
|
+
return false;
|
|
4028
|
+
}
|
|
4029
|
+
var out, err, RUNTIME_FRESH_MS, _refreshedDirsThisProcess;
|
|
4030
|
+
var init_local_holon = __esm({
|
|
4031
|
+
"src/local_holon.ts"() {
|
|
4032
|
+
"use strict";
|
|
4033
|
+
init_engine();
|
|
4034
|
+
init_cloud();
|
|
4035
|
+
out = (s) => void process.stdout.write(s + "\n");
|
|
4036
|
+
err = (s) => void process.stderr.write("error: " + s + "\n");
|
|
4037
|
+
RUNTIME_FRESH_MS = 15 * 60 * 1e3;
|
|
4038
|
+
_refreshedDirsThisProcess = /* @__PURE__ */ new Set();
|
|
4039
|
+
}
|
|
4040
|
+
});
|
|
4041
|
+
|
|
4042
|
+
// src/compile_mountability_entry.ts
|
|
4043
|
+
init_cloud();
|
|
4044
|
+
|
|
4045
|
+
// src/mountability.ts
|
|
4046
|
+
import { createHash } from "node:crypto";
|
|
4047
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, rmSync } from "node:fs";
|
|
4048
|
+
import { join as join3 } from "node:path";
|
|
4049
|
+
import { fileURLToPath } from "node:url";
|
|
4050
|
+
import { readKeyProofUsda, writeKeyProofUsda } from "@githolon/dsl/compile-proof";
|
|
4051
|
+
async function assertCompiledMountable(cwd, cloud) {
|
|
4052
|
+
const buildDir = join3(cwd, "build");
|
|
4053
|
+
if (!existsSync2(buildDir)) return { ok: true, checked: [] };
|
|
4054
|
+
const laws = readdirSync2(buildDir).filter((f) => f.endsWith(".law.usdz"));
|
|
4055
|
+
if (laws.length === 0) return { ok: true, checked: [] };
|
|
4056
|
+
let mount;
|
|
4057
|
+
let engine;
|
|
4058
|
+
try {
|
|
4059
|
+
mount = await Promise.resolve().then(() => (init_local_holon(), local_holon_exports));
|
|
4060
|
+
engine = await Promise.resolve().then(() => (init_engine(), engine_exports));
|
|
4061
|
+
} catch {
|
|
4062
|
+
return { ok: true, checked: [], skipped: "the vendored kernel engine is not present \u2014 mountability gate skipped (compile still emitted the package)" };
|
|
4063
|
+
}
|
|
4064
|
+
const { fetchRuntime: fetchRuntime2, holonEngine: holonEngine2, inspectLawArchive: inspectLawArchive2, mountFresh: mountFresh2 } = mount;
|
|
4065
|
+
const { author: author2, closureInstallPayload: closureInstallPayload2 } = engine;
|
|
4066
|
+
const candidates = [];
|
|
4067
|
+
for (const f of laws) {
|
|
4068
|
+
const lawUsdzFile = join3(buildDir, f);
|
|
4069
|
+
candidates.push({
|
|
4070
|
+
lawUsdz: new Uint8Array(readFileSync2(lawUsdzFile)),
|
|
4071
|
+
lawUsdzFile,
|
|
4072
|
+
name: f.replace(/\.law\.usdz$/, "")
|
|
4073
|
+
});
|
|
4074
|
+
}
|
|
4075
|
+
if (candidates.length === 0) return { ok: true, checked: [] };
|
|
4076
|
+
const runtime = await fetchRuntime2(cloud);
|
|
4077
|
+
const proofHash = createHash("sha256").update("nomos.mountability-proof.v1\0").update(readFileSync2(fileURLToPath(import.meta.url))).update(runtime.wasmBytes).update(runtime.bootstrapLawUsdz).update(runtime.nomosLawUsdz);
|
|
4078
|
+
for (const candidate of candidates) {
|
|
4079
|
+
proofHash.update("\0").update(candidate.name).update("\0").update(candidate.lawUsdz);
|
|
4080
|
+
}
|
|
4081
|
+
const proofKey = proofHash.digest("hex");
|
|
4082
|
+
const proofPath = join3(buildDir, ".nomos-mountability-proof.usda");
|
|
4083
|
+
const retiredJsonProof = join3(buildDir, ".nomos-mountability-proof.json");
|
|
4084
|
+
if (existsSync2(retiredJsonProof)) {
|
|
4085
|
+
rmSync(retiredJsonProof, { force: true });
|
|
4086
|
+
}
|
|
4087
|
+
if (readKeyProofUsda(proofPath, "nomos.mountability-proof.v1") === proofKey) {
|
|
4088
|
+
return { ok: true, checked: candidates.map((candidate) => candidate.name), cached: true };
|
|
4089
|
+
}
|
|
4090
|
+
const checked = [];
|
|
4091
|
+
for (const { lawUsdzFile, name } of candidates) {
|
|
4092
|
+
const ws = `mountcheck-${name}`.replace(/[^A-Za-z0-9_-]/g, "-").slice(0, 100);
|
|
4093
|
+
try {
|
|
4094
|
+
const { eng } = await holonEngine2(cloud, `${ws}-eng`, "production", runtime);
|
|
4095
|
+
const { identity, lawUsdz } = inspectLawArchive2(eng, lawUsdzFile);
|
|
4096
|
+
await mountFresh2(eng, ws);
|
|
4097
|
+
const framework = author2(
|
|
4098
|
+
eng,
|
|
4099
|
+
ws,
|
|
4100
|
+
"bootstrap",
|
|
4101
|
+
"installDomain",
|
|
4102
|
+
closureInstallPayload2(eng.hashes.nomos, `${ws}-eng`),
|
|
4103
|
+
"",
|
|
4104
|
+
{ lawUsdz: eng.nomosLawUsdz }
|
|
4105
|
+
);
|
|
4106
|
+
if (framework && framework.ok === false) {
|
|
4107
|
+
return {
|
|
4108
|
+
ok: false,
|
|
4109
|
+
checked,
|
|
4110
|
+
error: `${name}: incoherent runtime bundle \u2014 the selected kernel refused its bundled Nomos framework law before tenant law was mounted: ${framework.error ?? "framework install refused"}`
|
|
4111
|
+
};
|
|
4112
|
+
}
|
|
4113
|
+
const r = author2(
|
|
4114
|
+
eng,
|
|
4115
|
+
ws,
|
|
4116
|
+
"nomos",
|
|
4117
|
+
"installDomain",
|
|
4118
|
+
{
|
|
4119
|
+
domainHash: identity,
|
|
4120
|
+
installedBy: `${ws}-eng`,
|
|
4121
|
+
dependencies: [],
|
|
4122
|
+
finalizers: []
|
|
4123
|
+
},
|
|
4124
|
+
eng.hashes.nomos,
|
|
4125
|
+
{ lawUsdz }
|
|
4126
|
+
);
|
|
4127
|
+
if (r && r.ok === false) {
|
|
4128
|
+
return { ok: false, checked, error: `${name}: the read router REFUSED the compiled law at mount \u2014 ${r.error ?? "install refused"}` };
|
|
4129
|
+
}
|
|
4130
|
+
checked.push(name);
|
|
4131
|
+
} catch (e) {
|
|
4132
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
4133
|
+
return { ok: false, checked, error: `${name}: the compiled package is NOT mountable on the real kernel \u2014 ${msg}` };
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
writeKeyProofUsda(proofPath, "nomos.mountability-proof.v1", proofKey);
|
|
4137
|
+
return { ok: true, checked };
|
|
4138
|
+
}
|
|
4139
|
+
|
|
4140
|
+
// src/compile_mountability_entry.ts
|
|
4141
|
+
async function assertPublicCompileMountable(cwd) {
|
|
4142
|
+
return assertCompiledMountable(cwd, cloudBase());
|
|
4143
|
+
}
|
|
4144
|
+
export {
|
|
4145
|
+
assertPublicCompileMountable
|
|
4146
|
+
};
|