githolon 0.84.1 → 0.86.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 +11 -1
- package/dist/dev-server.mjs +312 -4
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -1778,7 +1778,17 @@ function servePack(eng, ws, base = "") {
|
|
|
1778
1778
|
try {
|
|
1779
1779
|
r = JSON.parse(call(eng.ex, "pack_delta", { repoArg: repoArgOf(ws), workspace: ws, base, branch: BRANCH }, eng.STDERR));
|
|
1780
1780
|
} catch (e) {
|
|
1781
|
-
|
|
1781
|
+
const msg = String(e);
|
|
1782
|
+
if (/nothing to pack|head == base/.test(msg)) return { packB64: "", bytes: 0, upToDate: true, ...head ? { head } : {} };
|
|
1783
|
+
if (base && /reached root|before base|not found|unknown|no (?:merge )?base|missing|invalid/i.test(msg)) {
|
|
1784
|
+
try {
|
|
1785
|
+
const full = JSON.parse(call(eng.ex, "pack_delta", { repoArg: repoArgOf(ws), workspace: ws, base: "", branch: BRANCH }, eng.STDERR));
|
|
1786
|
+
if (full && full.ok === true && typeof full.packB64 === "string") {
|
|
1787
|
+
return { packB64: full.packB64, bytes: full.bytes, divergent: true, ...head ? { head } : {} };
|
|
1788
|
+
}
|
|
1789
|
+
} catch {
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1782
1792
|
throw e;
|
|
1783
1793
|
}
|
|
1784
1794
|
if (!r || r.ok !== true || typeof r.packB64 !== "string") throw new Error("servePack: kernel produced no pack");
|
package/dist/dev-server.mjs
CHANGED
|
@@ -594,6 +594,126 @@ function summaryOfCapture(ctx, fromOid, toOid) {
|
|
|
594
594
|
rowsByHome: Object.fromEntries([...ctx.rowsByHome.entries()].sort((a, b) => a[0] < b[0] ? -1 : 1))
|
|
595
595
|
};
|
|
596
596
|
}
|
|
597
|
+
async function admitIntentOffers(eng, ws, ledger, offers, { receiptFence = null, shardRouting = null, clientBase = null, defer = false } = {}) {
|
|
598
|
+
const main = await mainIntentIds(eng, ws);
|
|
599
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
600
|
+
const deadLetters = [];
|
|
601
|
+
let admittedTotal = 0;
|
|
602
|
+
const born = [];
|
|
603
|
+
const birthOutcomes = [];
|
|
604
|
+
const timings = { spans: [], intents: 0, sessions: 0 };
|
|
605
|
+
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;
|
|
606
|
+
if (summaryCtx) {
|
|
607
|
+
try {
|
|
608
|
+
for (const r of query(eng, ws, "aggregatesByType", JSON.stringify({ __type: "NomosHomeReceipt" }))) {
|
|
609
|
+
const hk = r.data && typeof r.data.homeKey === "string" ? r.data.homeKey : null;
|
|
610
|
+
if (!hk) continue;
|
|
611
|
+
summaryCtx.homeKeySet.add(hk);
|
|
612
|
+
summaryCtx.homeTags.set(await routeTagHexOfHomeKey(hk), hk);
|
|
613
|
+
}
|
|
614
|
+
} catch (e) {
|
|
615
|
+
log("home-tag-table-error", { ws, error: String(e).slice(0, 200) });
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
const gitdir0 = gitdirOf(ws);
|
|
619
|
+
const headBefore = summaryCtx ? kgit.resolveRef(eng, gitdir0, BRANCH) : null;
|
|
620
|
+
const t0 = Date.now();
|
|
621
|
+
let seq = 0;
|
|
622
|
+
const span = (name, kind, depth = 1, extra = {}) => {
|
|
623
|
+
const s0 = Date.now();
|
|
624
|
+
return (end = {}) => timings.spans.push({ id: `intent-offer-${t0}-${seq++}`, track: "cloud", name, kind, depth, t0: s0, t1: Date.now(), ...extra, ...end });
|
|
625
|
+
};
|
|
626
|
+
for (const offer of Array.isArray(offers) ? offers : []) {
|
|
627
|
+
const cid = typeof offer?.session === "string" && offer.session ? offer.session : "direct";
|
|
628
|
+
const rec = sessions.get(cid) || { session: cid, admitted: [], rejected: [], skipped: [] };
|
|
629
|
+
sessions.set(cid, rec);
|
|
630
|
+
const done = span(`intent offer ${cid.slice(0, 14)}`, "cadmit", 1, { client: cid });
|
|
631
|
+
let blob = offer?.blob instanceof Uint8Array ? offer.blob : null;
|
|
632
|
+
try {
|
|
633
|
+
if (!blob && typeof offer?.intentB64 === "string") blob = Uint8Array.from(atob(offer.intentB64), (c) => c.charCodeAt(0));
|
|
634
|
+
const maxOfferBytes = offer?.staged ? 64 * 1024 * 1024 : 8 * 1024 * 1024;
|
|
635
|
+
if (!blob || blob.byteLength === 0 || blob.byteLength > maxOfferBytes) {
|
|
636
|
+
rec.rejected.push({ oid: String(offer?.oid || "").slice(0, 10), error: `intent offer must carry intentB64 <= ${maxOfferBytes / (1024 * 1024)} MiB` });
|
|
637
|
+
continue;
|
|
638
|
+
}
|
|
639
|
+
let doc = null;
|
|
640
|
+
try {
|
|
641
|
+
doc = JSON.parse(dec3.decode(blob));
|
|
642
|
+
} catch {
|
|
643
|
+
}
|
|
644
|
+
const intentId = typeof doc?.id === "string" ? doc.id : null;
|
|
645
|
+
const dom = typeof doc?.payload?.domain === "string" ? doc.payload.domain : null;
|
|
646
|
+
const dirId = typeof doc?.payload?.directiveId === "string" ? doc.payload.directiveId : null;
|
|
647
|
+
const oid = String(offer?.oid || intentId || "").slice(0, 10);
|
|
648
|
+
if (!dom) {
|
|
649
|
+
rec.rejected.push({ oid, error: "non-authored intent \u2014 governance enters its own admin lane" });
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
if (receiptFence && dirId && Array.isArray(receiptFence[dom]) && receiptFence[dom].includes(dirId)) {
|
|
653
|
+
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`;
|
|
654
|
+
rec.rejected.push({ oid, error, deadLettered: true });
|
|
655
|
+
deadLetters.push({ intentId, oid, session: cid, error, blob, domain: dom, directiveId: dirId });
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
if (intentId && main.ids.has(intentId)) {
|
|
659
|
+
rec.skipped.push({ oid, intent: intentId.slice(0, 12), alreadyOnMain: true });
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
const cap = summaryCtx ? beginSummaryCapture(eng, ws, summaryCtx, blob) : null;
|
|
663
|
+
const _tOffer = Date.now();
|
|
664
|
+
const res = offerAdmit(eng, ws, blob, { defer: !summaryCtx });
|
|
665
|
+
log("offer-admit-ms", { ws, ms: Date.now() - _tOffer, deferred: !summaryCtx, ok: res.ok });
|
|
666
|
+
if (res.ok) {
|
|
667
|
+
if (intentId) main.ids.add(intentId);
|
|
668
|
+
main.oids.add(res.head);
|
|
669
|
+
main.head = res.head;
|
|
670
|
+
rec.admitted.push({ oid, head: res.head });
|
|
671
|
+
admittedTotal += 1;
|
|
672
|
+
if (Array.isArray(res.born) && res.born.length) born.push(...res.born);
|
|
673
|
+
if (Array.isArray(res.birthOutcomes) && res.birthOutcomes.length) birthOutcomes.push(...res.birthOutcomes);
|
|
674
|
+
if (cap) finishSummaryCapture(eng, ws, summaryCtx, cap, res.head, intentId);
|
|
675
|
+
} else {
|
|
676
|
+
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`;
|
|
677
|
+
rec.rejected.push({ oid, error, deadLettered: true });
|
|
678
|
+
deadLetters.push({ intentId, oid, session: cid, error, blob, domain: dom, directiveId: dirId });
|
|
679
|
+
}
|
|
680
|
+
} catch (e) {
|
|
681
|
+
rec.rejected.push({ oid: String(offer?.oid || "").slice(0, 10), error: String(e).slice(0, 200) });
|
|
682
|
+
} finally {
|
|
683
|
+
done();
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
timings.sessions = sessions.size;
|
|
687
|
+
timings.intents = admittedTotal;
|
|
688
|
+
if (admittedTotal && !summaryCtx) (eng.pendingProjection ??= /* @__PURE__ */ new Set()).add(ws);
|
|
689
|
+
if (deadLetters.length) {
|
|
690
|
+
try {
|
|
691
|
+
await materializeRefused(eng, ws, ledger, deadLetters);
|
|
692
|
+
} catch (e) {
|
|
693
|
+
log("refused-materialize-failed", { ws, error: String(e).slice(0, 200) });
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
const deferDurability = defer && !summaryCtx;
|
|
697
|
+
if (admittedTotal && !deferDurability) {
|
|
698
|
+
const sealDone = span("seal offered intents", "cseal", 1, { admitted: admittedTotal });
|
|
699
|
+
await commitAndPush(eng, ws, ledger);
|
|
700
|
+
sealDone();
|
|
701
|
+
}
|
|
702
|
+
const gitdir = gitdirOf(ws);
|
|
703
|
+
const head = kgit.resolveRef(eng, gitdir, BRANCH) ?? main.head;
|
|
704
|
+
const summary = summaryCtx ? summaryOfCapture(summaryCtx, headBefore, head) : null;
|
|
705
|
+
let resultPackB64 = null;
|
|
706
|
+
if (admittedTotal && head && /^[0-9a-f]{40}$/i.test(clientBase || "") && clientBase !== head) {
|
|
707
|
+
try {
|
|
708
|
+
const p = servePack(eng, ws, clientBase);
|
|
709
|
+
if (p && p.packB64 && p.bytes && p.bytes <= RESULT_PACK_INLINE_MAX) resultPackB64 = p.packB64;
|
|
710
|
+
} catch {
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
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" });
|
|
714
|
+
const bornPacked = born.length ? packBornChildren(eng, born) : born;
|
|
715
|
+
return { sessions: [...sessions.values()].map((s) => ({ ...s, ...s.skipped.length ? {} : { skipped: void 0 } })), main: head, deadLetters, timings, ...summary ? { summary } : {}, ...bornPacked.length ? { born: bornPacked } : {}, ...birthOutcomes.length ? { birthOutcomes } : {}, ...resultPackB64 ? { resultPackB64, resultBase: clientBase } : {}, ...deferDurability && admittedTotal && head ? { deferred: true, head } : {} };
|
|
716
|
+
}
|
|
597
717
|
async function authorOn(eng, ws, ledger, domain, directiveId, payload, lawHash, opts = {}) {
|
|
598
718
|
await mountWorkspace(eng, ws, ledger);
|
|
599
719
|
let res;
|
|
@@ -794,7 +914,17 @@ function servePack(eng, ws, base = "") {
|
|
|
794
914
|
try {
|
|
795
915
|
r = JSON.parse(call(eng.ex, "pack_delta", { repoArg: repoArgOf(ws), workspace: ws, base, branch: BRANCH }, eng.STDERR));
|
|
796
916
|
} catch (e) {
|
|
797
|
-
|
|
917
|
+
const msg = String(e);
|
|
918
|
+
if (/nothing to pack|head == base/.test(msg)) return { packB64: "", bytes: 0, upToDate: true, ...head ? { head } : {} };
|
|
919
|
+
if (base && /reached root|before base|not found|unknown|no (?:merge )?base|missing|invalid/i.test(msg)) {
|
|
920
|
+
try {
|
|
921
|
+
const full = JSON.parse(call(eng.ex, "pack_delta", { repoArg: repoArgOf(ws), workspace: ws, base: "", branch: BRANCH }, eng.STDERR));
|
|
922
|
+
if (full && full.ok === true && typeof full.packB64 === "string") {
|
|
923
|
+
return { packB64: full.packB64, bytes: full.bytes, divergent: true, ...head ? { head } : {} };
|
|
924
|
+
}
|
|
925
|
+
} catch {
|
|
926
|
+
}
|
|
927
|
+
}
|
|
798
928
|
throw e;
|
|
799
929
|
}
|
|
800
930
|
if (!r || r.ok !== true || typeof r.packB64 !== "string") throw new Error("servePack: kernel produced no pack");
|
|
@@ -1166,6 +1296,35 @@ async function writeRefusedRef(eng, ws, dl) {
|
|
|
1166
1296
|
});
|
|
1167
1297
|
return ref;
|
|
1168
1298
|
}
|
|
1299
|
+
async function listRefusedRefs(eng, ws) {
|
|
1300
|
+
const gitdir = gitdirOf(ws);
|
|
1301
|
+
const refs = kgit.listRefs(eng, gitdir, "refs/heads/refused/");
|
|
1302
|
+
const out = [];
|
|
1303
|
+
for (const { ref, oid } of refs) {
|
|
1304
|
+
try {
|
|
1305
|
+
const vb = kgit.readBlob(eng, gitdir, oid, "verdict.json");
|
|
1306
|
+
const ib = kgit.readBlob(eng, gitdir, oid, "intent.json");
|
|
1307
|
+
const v = JSON.parse(dec3.decode(vb));
|
|
1308
|
+
out.push({ ref, ...v, intentB64: b64Bytes(ib) });
|
|
1309
|
+
} catch {
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
return out;
|
|
1313
|
+
}
|
|
1314
|
+
async function refusedSummary(eng, ws) {
|
|
1315
|
+
const gitdir = gitdirOf(ws);
|
|
1316
|
+
const refs = kgit.listRefs(eng, gitdir, "refs/heads/refused/");
|
|
1317
|
+
let count2 = 0, latestParkedAt = null;
|
|
1318
|
+
for (const { oid } of refs) {
|
|
1319
|
+
try {
|
|
1320
|
+
const v = JSON.parse(dec3.decode(kgit.readBlob(eng, gitdir, oid, "verdict.json")));
|
|
1321
|
+
count2++;
|
|
1322
|
+
if (v && typeof v.parkedAt === "string" && (!latestParkedAt || v.parkedAt > latestParkedAt)) latestParkedAt = v.parkedAt;
|
|
1323
|
+
} catch {
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
return { count: count2, latestParkedAt };
|
|
1327
|
+
}
|
|
1169
1328
|
async function materializeRefused(eng, ws, ledger, deadLetters) {
|
|
1170
1329
|
const refs = [];
|
|
1171
1330
|
const unparkedSessions = /* @__PURE__ */ new Set();
|
|
@@ -1181,6 +1340,20 @@ async function materializeRefused(eng, ws, ledger, deadLetters) {
|
|
|
1181
1340
|
}
|
|
1182
1341
|
return { refs, unparkedSessions };
|
|
1183
1342
|
}
|
|
1343
|
+
async function deleteRefusedRef(eng, ws, ledger, offerId) {
|
|
1344
|
+
const gitdir = gitdirOf(ws);
|
|
1345
|
+
const ref = refusedRefName(offerId);
|
|
1346
|
+
try {
|
|
1347
|
+
kgit.deleteRef(eng, gitdir, ref);
|
|
1348
|
+
} catch {
|
|
1349
|
+
}
|
|
1350
|
+
try {
|
|
1351
|
+
await custodyPush(eng, ws, ledger, { remoteRef: ref, del: true });
|
|
1352
|
+
} catch (e) {
|
|
1353
|
+
log("refused-ref-delete-push-failed", { ws, ref, error: String(e).slice(0, 200) });
|
|
1354
|
+
}
|
|
1355
|
+
return ref;
|
|
1356
|
+
}
|
|
1184
1357
|
async function boot(eng, ws, ledger) {
|
|
1185
1358
|
const m = await mountWorkspace(eng, ws, ledger);
|
|
1186
1359
|
if (nomosActive(eng, ws)) {
|
|
@@ -1578,6 +1751,34 @@ function receivePackCommands(raw) {
|
|
|
1578
1751
|
// ../cloud/dev-server/server.mjs
|
|
1579
1752
|
var DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
1580
1753
|
var REPO_ROOT = path.resolve(DIR, "../..");
|
|
1754
|
+
var RECOGNIZED_UNSUPPORTED = /* @__PURE__ */ new Set([
|
|
1755
|
+
"container-status",
|
|
1756
|
+
"recycle-container",
|
|
1757
|
+
"hostnames",
|
|
1758
|
+
"rebirth-custody",
|
|
1759
|
+
"upload-begin",
|
|
1760
|
+
"upload-gate",
|
|
1761
|
+
"upload-verify",
|
|
1762
|
+
"drain-reclaims",
|
|
1763
|
+
"drain-rebirths",
|
|
1764
|
+
"git-read-lease",
|
|
1765
|
+
"poke-admit",
|
|
1766
|
+
"clear-checkpoint",
|
|
1767
|
+
"domain-package",
|
|
1768
|
+
"capabilities"
|
|
1769
|
+
]);
|
|
1770
|
+
var UNSUPPORTED_WHY = {
|
|
1771
|
+
"container-status": "the heavy container tier is Cloudflare-only (the dev cloud is one in-process engine)",
|
|
1772
|
+
"recycle-container": "the heavy container tier is Cloudflare-only (the dev cloud is one in-process engine)",
|
|
1773
|
+
"hostnames": "platform custom-hostname routing is a multi-tenant edge concern",
|
|
1774
|
+
"rebirth-custody": "the custodian rebirth lane is bound to Cloudflare Artifacts custody",
|
|
1775
|
+
"upload-begin": "the staged-upload birth variant \u2014 push to /v2/workspaces/<ws>/git instead (the upload-birth lane works locally)",
|
|
1776
|
+
"upload-gate": "the staged-upload birth variant \u2014 push to /v2/workspaces/<ws>/git instead",
|
|
1777
|
+
"upload-verify": "the staged-upload birth variant \u2014 push to /v2/workspaces/<ws>/git instead",
|
|
1778
|
+
"drain-reclaims": "an operator lawful-recovery drain (multi-node lifecycle)",
|
|
1779
|
+
"drain-rebirths": "an operator lawful-recovery drain (multi-node lifecycle)",
|
|
1780
|
+
"capabilities": "retired everywhere \u2014 host-side capability storage is gone (capabilities are holon-offered obligations now)"
|
|
1781
|
+
};
|
|
1581
1782
|
var _realFetch = globalThis.fetch;
|
|
1582
1783
|
globalThis.fetch = (input, init) => {
|
|
1583
1784
|
const u = typeof input === "string" ? input : input && input.url || "";
|
|
@@ -1893,13 +2094,101 @@ async function startDevCloud(opts = {}) {
|
|
|
1893
2094
|
sendJson(res, { ok: true, ws, sessions: out.sessions, main: out.main, ...out.timings ? { timings: out.timings } : {} });
|
|
1894
2095
|
});
|
|
1895
2096
|
}
|
|
2097
|
+
if (sub[0] === "intent-offers" && req.method === "POST") {
|
|
2098
|
+
return serialize(async () => {
|
|
2099
|
+
const ledger = ledgerFor(ws);
|
|
2100
|
+
await mountWorkspace(eng, ws, ledger);
|
|
2101
|
+
const body = JSON.parse((await readBody(req)).toString("utf8") || "{}");
|
|
2102
|
+
const offers = Array.isArray(body.offers) ? body.offers.slice(0, 100) : [];
|
|
2103
|
+
if (!offers.length) return sendJson(res, { ok: false, error: "body must be { offers:[{session, oid, intentB64}] }" }, 400);
|
|
2104
|
+
const clientBase = /^[0-9a-f]{40}$/i.test(body.base || "") ? body.base : null;
|
|
2105
|
+
const out = await admitIntentOffers(eng, ws, ledger, offers, { ...clientBase ? { clientBase } : {} });
|
|
2106
|
+
if (Array.isArray(out.born) && out.born.length) await persistBorn(out.born);
|
|
2107
|
+
const bornOut = Array.isArray(out.born) ? out.born.map(({ packB64, packBytes, ...b }) => b) : null;
|
|
2108
|
+
sendJson(res, {
|
|
2109
|
+
ok: true,
|
|
2110
|
+
ws,
|
|
2111
|
+
sessions: out.sessions,
|
|
2112
|
+
main: out.main,
|
|
2113
|
+
...bornOut ? { born: bornOut } : {},
|
|
2114
|
+
...out.birthOutcomes ? { birthOutcomes: out.birthOutcomes } : {},
|
|
2115
|
+
...out.mainDelta ? { mainDelta: out.mainDelta } : {},
|
|
2116
|
+
...out.resultPackB64 ? { resultPackB64: out.resultPackB64, resultBase: out.resultBase } : {},
|
|
2117
|
+
...out.deadLetters && out.deadLetters.length ? { deadLetters: out.deadLetters.map(({ blob, ...m }) => m) } : {}
|
|
2118
|
+
});
|
|
2119
|
+
});
|
|
2120
|
+
}
|
|
2121
|
+
if (sub[0] === "dead-letters" && sub.length === 1 && req.method === "GET") {
|
|
2122
|
+
return serialize(async () => {
|
|
2123
|
+
await mountWorkspace(eng, ws, ledgerFor(ws));
|
|
2124
|
+
sendJson(res, { ok: true, ws, deadLetters: await listRefusedRefs(eng, ws) });
|
|
2125
|
+
});
|
|
2126
|
+
}
|
|
2127
|
+
if (sub[0] === "dlq-summary" && req.method === "GET") {
|
|
2128
|
+
return serialize(async () => {
|
|
2129
|
+
await mountWorkspace(eng, ws, ledgerFor(ws));
|
|
2130
|
+
sendJson(res, { ok: true, ws, ...await refusedSummary(eng, ws) });
|
|
2131
|
+
});
|
|
2132
|
+
}
|
|
2133
|
+
if (sub[0] === "dead-letters" && sub[1] === "retry" && req.method === "POST") {
|
|
2134
|
+
return serialize(async () => {
|
|
2135
|
+
const ledger = ledgerFor(ws);
|
|
2136
|
+
await mountWorkspace(eng, ws, ledger);
|
|
2137
|
+
const body = JSON.parse((await readBody(req)).toString("utf8") || "{}");
|
|
2138
|
+
const only = body.id || null;
|
|
2139
|
+
const refs = await listRefusedRefs(eng, ws);
|
|
2140
|
+
const retried = [], failed = [];
|
|
2141
|
+
for (const e of refs) {
|
|
2142
|
+
if (only && e.offerId !== only && e.oid !== only) continue;
|
|
2143
|
+
if (!e.intentB64) {
|
|
2144
|
+
failed.push({ intentId: e.offerId, error: "refused ref carries no intent bytes" });
|
|
2145
|
+
continue;
|
|
2146
|
+
}
|
|
2147
|
+
try {
|
|
2148
|
+
const r2 = offerAdmit(eng, ws, unb64(e.intentB64));
|
|
2149
|
+
if (r2.ok) retried.push({ intentId: e.offerId, head: r2.head });
|
|
2150
|
+
else failed.push({ intentId: e.offerId, error: String(r2.error || "").slice(0, 300) });
|
|
2151
|
+
} catch (err) {
|
|
2152
|
+
failed.push({ intentId: e.offerId, error: String(err).slice(0, 300) });
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
if (retried.length) await commitAndPush(eng, ws, ledger);
|
|
2156
|
+
for (const r2 of retried) await deleteRefusedRef(eng, ws, ledger, r2.intentId);
|
|
2157
|
+
sendJson(res, { ok: true, ws, retried, failed, remaining: (await listRefusedRefs(eng, ws)).length });
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
if (sub[0] === "dead-letters" && (sub[1] === "discard" || req.method === "DELETE")) {
|
|
2161
|
+
return serialize(async () => {
|
|
2162
|
+
const ledger = ledgerFor(ws);
|
|
2163
|
+
await mountWorkspace(eng, ws, ledger);
|
|
2164
|
+
const body = req.method === "DELETE" ? {} : JSON.parse((await readBody(req)).toString("utf8") || "{}");
|
|
2165
|
+
const only = body.id || url.searchParams.get("id") || null;
|
|
2166
|
+
const targets = (await listRefusedRefs(eng, ws)).filter((e) => !only || e.offerId === only || e.oid === only);
|
|
2167
|
+
for (const e of targets) await deleteRefusedRef(eng, ws, ledger, e.offerId || e.oid);
|
|
2168
|
+
sendJson(res, { ok: true, ws, discarded: targets.length });
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
if (sub[0] === "rotate-secret" && req.method === "POST") {
|
|
2172
|
+
return sendJson(res, { ok: false, retired: true, error: "rotate-secret is retired \u2014 ownership is a ledger fact (sha256 of the push password on the law record); re-own by re-birthing via the upload lane" }, 410);
|
|
2173
|
+
}
|
|
1896
2174
|
if (sub[0] === "pack" && req.method === "GET") {
|
|
1897
2175
|
return serialize(async () => {
|
|
1898
2176
|
await mountWorkspace(eng, ws, ledgerFor(ws));
|
|
1899
2177
|
const have = url.searchParams.get("have") || "";
|
|
1900
|
-
|
|
2178
|
+
let r;
|
|
2179
|
+
try {
|
|
2180
|
+
r = servePack(eng, ws, have);
|
|
2181
|
+
} catch (e) {
|
|
2182
|
+
return sendJson(res, { ok: false, custodyBreak: true, error: String(e && e.message || e).slice(0, 400), have }, 409);
|
|
2183
|
+
}
|
|
1901
2184
|
if (!r.packB64) return sendBytes(res, Buffer.alloc(0), 204, r.head ? { "x-nomos-head": r.head } : {});
|
|
1902
|
-
|
|
2185
|
+
const kind = r.divergent ? "full" : have ? "delta" : "full";
|
|
2186
|
+
sendBytes(res, unb64(r.packB64), 200, {
|
|
2187
|
+
"content-type": "application/x-git-packfile",
|
|
2188
|
+
"x-nomos-pack": kind,
|
|
2189
|
+
...r.divergent ? { "x-nomos-divergent": "1" } : {},
|
|
2190
|
+
...r.head ? { "x-nomos-head": r.head } : {}
|
|
2191
|
+
});
|
|
1903
2192
|
});
|
|
1904
2193
|
}
|
|
1905
2194
|
if (sub[0] === "snapshot" && req.method === "GET") {
|
|
@@ -1930,7 +2219,17 @@ async function startDevCloud(opts = {}) {
|
|
|
1930
2219
|
const resolved = resolveGatewayOperation(spec, opName, method);
|
|
1931
2220
|
if (resolved.ambiguous) return sendJson(res, { ok: false, error: "ambiguous operation", candidates: resolved.ambiguous }, 409);
|
|
1932
2221
|
const x = resolved.op && resolved.op["x-nomos"];
|
|
1933
|
-
if (!x)
|
|
2222
|
+
if (!x) {
|
|
2223
|
+
if (RECOGNIZED_UNSUPPORTED.has(opName)) {
|
|
2224
|
+
return sendJson(res, {
|
|
2225
|
+
ok: false,
|
|
2226
|
+
unsupported: true,
|
|
2227
|
+
route: opName,
|
|
2228
|
+
error: `'${opName}' is a recognized Nomos Cloud route that 'githolon cloud dev' (single-node local) does not serve \u2014 ${UNSUPPORTED_WHY[opName] || "a multi-node / Cloudflare-infra concern"}. This is NOT an app bug; if you need it locally, ask the Nomos devs.`
|
|
2229
|
+
}, 501);
|
|
2230
|
+
}
|
|
2231
|
+
return sendJson(res, { ok: false, error: "unknown operation", see: `GET /v2/workspaces/${ws}` }, 404);
|
|
2232
|
+
}
|
|
1934
2233
|
const principal = principalOf(req);
|
|
1935
2234
|
const authToken = authTokenOf(req);
|
|
1936
2235
|
if (x.kind === "offer" && method === "post") {
|
|
@@ -2044,6 +2343,15 @@ Sec-WebSocket-Accept: ${accept}\r
|
|
|
2044
2343
|
socket.on("error", () => {
|
|
2045
2344
|
});
|
|
2046
2345
|
});
|
|
2346
|
+
if (!globalThis.__nomosDevGuards) {
|
|
2347
|
+
globalThis.__nomosDevGuards = true;
|
|
2348
|
+
process.on("unhandledRejection", (e) => {
|
|
2349
|
+
console.error("[dev-cloud] unhandledRejection (kept alive):", String(e && e.stack || e && e.message || e).slice(0, 500));
|
|
2350
|
+
});
|
|
2351
|
+
process.on("uncaughtException", (e) => {
|
|
2352
|
+
console.error("[dev-cloud] uncaughtException (kept alive):", String(e && e.stack || e && e.message || e).slice(0, 500));
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2047
2355
|
await new Promise((resolve) => server.listen(port, host, resolve));
|
|
2048
2356
|
return { server, origin, dataDir, kernelSha, eng, custody, ledgerFor, serialize, persistBorn, close: () => new Promise((r) => server.close(r)) };
|
|
2049
2357
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "githolon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.86.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "githolon — the Nomos developer CLI: Rails-style generators for @githolon/dsl domains + the package compiler. Kernel-independent.",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@bjorn3/browser_wasi_shim": "0.4.2",
|
|
32
|
-
"@githolon/client": "^0.
|
|
33
|
-
"@githolon/dsl": "^0.
|
|
32
|
+
"@githolon/client": "^0.86.0",
|
|
33
|
+
"@githolon/dsl": "^0.86.0",
|
|
34
34
|
"isomorphic-git": "^1.38.4"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|