@nomosprotocol/sdk 2.5.0 → 2.7.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/README.md +92 -1
- package/dist/index.cjs +465 -13
- package/dist/index.d.cts +161 -2
- package/dist/index.d.ts +161 -2
- package/dist/index.js +463 -13
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
NomosRateLimitError: () => NomosRateLimitError,
|
|
37
37
|
NomosValidationError: () => NomosValidationError,
|
|
38
38
|
NomosWebhookSignatureError: () => NomosWebhookSignatureError,
|
|
39
|
+
RegistrarUnavailable: () => RegistrarUnavailable,
|
|
39
40
|
RegistryError: () => RegistryError,
|
|
40
41
|
RevocationUnavailable: () => RevocationUnavailable,
|
|
41
42
|
WELL_KNOWN: () => WELL_KNOWN,
|
|
@@ -66,6 +67,7 @@ __export(index_exports, {
|
|
|
66
67
|
postgresStore: () => postgresStore,
|
|
67
68
|
presentedCertificates: () => presentedCertificates,
|
|
68
69
|
readAttestation: () => readAttestation,
|
|
70
|
+
registrarSource: () => registrarSource,
|
|
69
71
|
reliedKids: () => reliedKids,
|
|
70
72
|
revocationListCertificates: () => revocationListCertificates,
|
|
71
73
|
revocationSource: () => revocationSource,
|
|
@@ -191,7 +193,7 @@ function isRetryable(status) {
|
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
// src/http-client.ts
|
|
194
|
-
var SDK_VERSION = "2.
|
|
196
|
+
var SDK_VERSION = "2.7.0";
|
|
195
197
|
var HttpClient = class {
|
|
196
198
|
constructor(opts) {
|
|
197
199
|
this.opts = opts;
|
|
@@ -858,6 +860,50 @@ async function canViaChain(artifact, keyCerts, rootPublicKeyPem, facts, action,
|
|
|
858
860
|
if (data?.decision === "MALFORMED") throw new NomosValidationError(message, data, requestId);
|
|
859
861
|
mapHttpError(res.status, data, requestId);
|
|
860
862
|
}
|
|
863
|
+
function normalizeResolutionResult(data) {
|
|
864
|
+
return {
|
|
865
|
+
mode: "resolution",
|
|
866
|
+
allowed: data.verdict === "AUTHORIZED",
|
|
867
|
+
verdict: data.verdict,
|
|
868
|
+
reason: data.reason ?? "",
|
|
869
|
+
resolution: data.resolution ?? { status: "INCOMPLETE", proof: null },
|
|
870
|
+
members: Array.isArray(data.members) ? data.members : [],
|
|
871
|
+
deciding_authorities: Array.isArray(data.deciding_authorities) ? data.deciding_authorities : [],
|
|
872
|
+
escalations: Array.isArray(data.escalations) ? data.escalations : [],
|
|
873
|
+
open_facts: Array.isArray(data.open_facts) ? data.open_facts : [],
|
|
874
|
+
...Array.isArray(data.answered_under) ? { answered_under: data.answered_under } : {},
|
|
875
|
+
...typeof data.coverage === "string" ? { coverage: data.coverage } : {}
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
function resolutionBody(params) {
|
|
879
|
+
const { authority, artifact_id, artifact, key_certs, root_public_key_pem, action, inputs, context, ...flat } = params;
|
|
880
|
+
void authority;
|
|
881
|
+
void artifact_id;
|
|
882
|
+
void artifact;
|
|
883
|
+
void key_certs;
|
|
884
|
+
void root_public_key_pem;
|
|
885
|
+
const facts = inputs && typeof inputs === "object" ? inputs : flat;
|
|
886
|
+
return { context, ...action ? { action } : {}, ...facts };
|
|
887
|
+
}
|
|
888
|
+
async function canViaResolution(params, opts) {
|
|
889
|
+
const base = (opts?.baseUrl ?? DEFAULT_EXCHANGE_BASE).replace(/\/$/, "");
|
|
890
|
+
let res;
|
|
891
|
+
try {
|
|
892
|
+
res = await fetch(`${base}/api/v1/can`, {
|
|
893
|
+
method: "POST",
|
|
894
|
+
headers: { "Content-Type": "application/json", "User-Agent": `nomos-node/${SDK_VERSION}`, ...callerHeaders(opts?.caller) },
|
|
895
|
+
body: JSON.stringify(resolutionBody(params)),
|
|
896
|
+
signal: opts?.signal
|
|
897
|
+
});
|
|
898
|
+
} catch (err) {
|
|
899
|
+
if (err?.name === "AbortError") throw new NomosNetworkError("Request aborted");
|
|
900
|
+
throw new NomosNetworkError(err?.message ?? "Network error");
|
|
901
|
+
}
|
|
902
|
+
const requestId = res.headers.get("x-request-id") ?? "";
|
|
903
|
+
const data = await res.json().catch(() => null);
|
|
904
|
+
if (!res.ok) mapHttpError(res.status, data, requestId);
|
|
905
|
+
return normalizeResolutionResult(data);
|
|
906
|
+
}
|
|
861
907
|
async function can(params, opts) {
|
|
862
908
|
if (params.artifact !== void 0) {
|
|
863
909
|
if (!params.key_certs || !params.root_public_key_pem) {
|
|
@@ -869,8 +915,11 @@ async function can(params, opts) {
|
|
|
869
915
|
if (params.artifact_id) {
|
|
870
916
|
throw new Error("can(): `artifact_id` requires an API key \u2014 use `client.can(...)` on an authenticated Nomos instance, not the free `can()` export.");
|
|
871
917
|
}
|
|
918
|
+
if (!params.authority && params.context && typeof params.context === "object" && !Array.isArray(params.context)) {
|
|
919
|
+
return canViaResolution(params, opts);
|
|
920
|
+
}
|
|
872
921
|
if (!params.authority || typeof params.authority !== "string") {
|
|
873
|
-
throw new Error("can(): `authority` (an Exchange artifact id or slug), `artifact_id` (via client.can()),
|
|
922
|
+
throw new Error("can(): `authority` (an Exchange artifact id or slug), `artifact_id` (via client.can()), `artifact` (chain-of-trust), or `context` (resolution, NOMOS-SPEC-014) is required.");
|
|
874
923
|
}
|
|
875
924
|
const { facts, action } = splitFacts(params);
|
|
876
925
|
return canViaExchange(params.authority, facts, action, opts);
|
|
@@ -885,7 +934,11 @@ async function canAuthenticated(http, params, opts) {
|
|
|
885
934
|
}
|
|
886
935
|
if (params.artifact_id) return canViaArtifact(http, params.artifact_id, facts, action);
|
|
887
936
|
if (params.authority) return canViaExchangeAuthenticated(http, params.authority, facts, action, opts);
|
|
888
|
-
|
|
937
|
+
if (params.context && typeof params.context === "object" && !Array.isArray(params.context)) {
|
|
938
|
+
const data = (await http.post("/api/v1/can", resolutionBody(params), { headers: callerHeaders(opts?.caller) })).data;
|
|
939
|
+
return normalizeResolutionResult(data);
|
|
940
|
+
}
|
|
941
|
+
throw new Error("can(): `authority` (a public Exchange artifact), `artifact_id` (your own artifact), `artifact` (chain-of-trust), or `context` (resolution, NOMOS-SPEC-014) is required.");
|
|
889
942
|
}
|
|
890
943
|
var nomos = { can };
|
|
891
944
|
|
|
@@ -5207,7 +5260,7 @@ function verifyUnsafe(a, o) {
|
|
|
5207
5260
|
const now = (o.now ?? /* @__PURE__ */ new Date()).getTime();
|
|
5208
5261
|
const nowDate = new Date(now);
|
|
5209
5262
|
const revokedKids = o.revokedKids ?? /* @__PURE__ */ new Set(), revokedCerts = o.revokedCerts ?? /* @__PURE__ */ new Set();
|
|
5210
|
-
const localFacts = o.localFacts ?? {},
|
|
5263
|
+
const localFacts = o.localFacts ?? {}, inForce2 = o.inForce ?? {};
|
|
5211
5264
|
const need = ["act_version", "act_id", "nonce", "issued_at", "expires_at", "relying_party", "action", "authority"];
|
|
5212
5265
|
if (!isObject(a) || need.some((k) => !(k in a)) || a.act_version !== "1" || !isObject(a.authority))
|
|
5213
5266
|
return { decision: "MALFORMED", reason_code: "bad_envelope" };
|
|
@@ -5251,9 +5304,9 @@ function verifyUnsafe(a, o) {
|
|
|
5251
5304
|
if (o.revokedArtifacts?.has(seal2.hash))
|
|
5252
5305
|
return { decision: "ARTIFACT_REVOKED", artifact_id: artId };
|
|
5253
5306
|
let inForceSource;
|
|
5254
|
-
if (typeof artId === "string" && Object.prototype.hasOwnProperty.call(
|
|
5255
|
-
if (
|
|
5256
|
-
return { decision: "SUPERSEDED", artifact_id: artId, in_force_seal_hash:
|
|
5307
|
+
if (typeof artId === "string" && Object.prototype.hasOwnProperty.call(inForce2, artId)) {
|
|
5308
|
+
if (inForce2[artId] !== seal2.hash)
|
|
5309
|
+
return { decision: "SUPERSEDED", artifact_id: artId, in_force_seal_hash: inForce2[artId] };
|
|
5257
5310
|
inForceSource = "record";
|
|
5258
5311
|
} else if (o.currencyPolicy === "record") {
|
|
5259
5312
|
return { decision: "VERSION_UNVERIFIED", artifact_id: artId, reason_code: "not_in_record" };
|
|
@@ -5470,6 +5523,288 @@ function verifyRevocationList(list, o) {
|
|
|
5470
5523
|
return out;
|
|
5471
5524
|
}
|
|
5472
5525
|
|
|
5526
|
+
// node_modules/@nomosprotocol/verify/dist/resolution.js
|
|
5527
|
+
var DEFAULT_CLOSURE_MAX_AGE_DAYS = 90;
|
|
5528
|
+
function evaluateScope(condition, context) {
|
|
5529
|
+
if (condition === "always" || condition === "all")
|
|
5530
|
+
return { value: "TRUE", openFacts: [] };
|
|
5531
|
+
let out;
|
|
5532
|
+
try {
|
|
5533
|
+
out = evaluate({
|
|
5534
|
+
logic: {
|
|
5535
|
+
resolution: { conflict_policy: "highest_priority", tie_breaker: "deny_wins", default_outcome: "escalate" },
|
|
5536
|
+
decisions: [
|
|
5537
|
+
{ id: "scope-when-true", when: condition, priority: 1, then: [{ type: "allow" }] },
|
|
5538
|
+
{ id: "scope", when: condition, priority: 2, then: [{ type: "block" }] }
|
|
5539
|
+
]
|
|
5540
|
+
}
|
|
5541
|
+
}, context);
|
|
5542
|
+
} catch {
|
|
5543
|
+
return { value: "UNDECIDED", openFacts: ["__scope_unparseable__"] };
|
|
5544
|
+
}
|
|
5545
|
+
if (out.outcome === "block")
|
|
5546
|
+
return { value: "TRUE", openFacts: [] };
|
|
5547
|
+
if (out.outcome === "undecided")
|
|
5548
|
+
return { value: "UNDECIDED", openFacts: [...out.open_facts] };
|
|
5549
|
+
return { value: "FALSE", openFacts: [] };
|
|
5550
|
+
}
|
|
5551
|
+
var inForce = (c, at) => (!c.from || c.from <= at) && (!c.until || c.until > at);
|
|
5552
|
+
var closureFresh = (c, at) => {
|
|
5553
|
+
const ageMs = Date.parse(at) - Date.parse(c.at);
|
|
5554
|
+
if (!Number.isFinite(ageMs) || ageMs < 0)
|
|
5555
|
+
return false;
|
|
5556
|
+
return ageMs <= (c.max_age_days ?? DEFAULT_CLOSURE_MAX_AGE_DAYS) * 864e5;
|
|
5557
|
+
};
|
|
5558
|
+
var closureReplaced = (c, all, at) => {
|
|
5559
|
+
const t = Date.parse(c.at), now = Date.parse(at);
|
|
5560
|
+
return all.some((d) => d !== c && Date.parse(d.at) > t && Date.parse(d.at) <= now && (d.scope === c.scope || !!c.label && d.label === c.label));
|
|
5561
|
+
};
|
|
5562
|
+
function resolveApplicableSet(world, query, opts = {}) {
|
|
5563
|
+
const at = query.at;
|
|
5564
|
+
const ctx = query.context ?? {};
|
|
5565
|
+
const proof = { at, pins: [...world.pins].sort(), heads: {}, closures: [], conflicts: [], dropped: [] };
|
|
5566
|
+
if (opts.ablate === "C5") {
|
|
5567
|
+
const applicable2 = (opts.presented ?? []).map((a) => ({ authority: a, version: null, registrar: "carrier", scope: "always" })).sort((x, y) => x.authority < y.authority ? -1 : 1);
|
|
5568
|
+
return { status: "RESOLVED", applicable: applicable2, proof };
|
|
5569
|
+
}
|
|
5570
|
+
const openFacts = /* @__PURE__ */ new Set();
|
|
5571
|
+
const unreachable = [];
|
|
5572
|
+
const staleClosures = [];
|
|
5573
|
+
const disagreements = [];
|
|
5574
|
+
const staleHeads = [];
|
|
5575
|
+
const memberAt = opts.ablate === "C7" && opts.snapshot ? opts.snapshot : at;
|
|
5576
|
+
const candidates2 = [];
|
|
5577
|
+
const visited = /* @__PURE__ */ new Set();
|
|
5578
|
+
const queue = [...world.pins].sort();
|
|
5579
|
+
while (queue.length > 0) {
|
|
5580
|
+
const id = queue.shift();
|
|
5581
|
+
if (visited.has(id))
|
|
5582
|
+
continue;
|
|
5583
|
+
visited.add(id);
|
|
5584
|
+
const reg = world.registrars[id];
|
|
5585
|
+
if (!reg) {
|
|
5586
|
+
if (opts.ablate !== "C8")
|
|
5587
|
+
unreachable.push(id);
|
|
5588
|
+
continue;
|
|
5589
|
+
}
|
|
5590
|
+
proof.heads[id] = reg.head ?? null;
|
|
5591
|
+
if (opts.ablate !== "C8" && typeof world.max_head_age_seconds === "number") {
|
|
5592
|
+
const age = reg.head_at ? Date.parse(at) - Date.parse(reg.head_at) : NaN;
|
|
5593
|
+
if (!Number.isFinite(age) || age > world.max_head_age_seconds * 1e3)
|
|
5594
|
+
staleHeads.push(id);
|
|
5595
|
+
}
|
|
5596
|
+
const cert = evaluateScope(reg.certified_scope, ctx);
|
|
5597
|
+
for (const f of cert.openFacts)
|
|
5598
|
+
openFacts.add(f);
|
|
5599
|
+
for (const e of [...reg.recognitions ?? []].sort((a, b) => a.to < b.to ? -1 : 1)) {
|
|
5600
|
+
const s = evaluateScope(e.scope, ctx);
|
|
5601
|
+
if (s.value === "TRUE")
|
|
5602
|
+
queue.push(e.to);
|
|
5603
|
+
for (const f of s.openFacts)
|
|
5604
|
+
openFacts.add(f);
|
|
5605
|
+
}
|
|
5606
|
+
const closedLists = [];
|
|
5607
|
+
if (opts.ablate !== "C8") {
|
|
5608
|
+
let covered = false;
|
|
5609
|
+
for (const c of reg.closures) {
|
|
5610
|
+
if (closureReplaced(c, reg.closures, at))
|
|
5611
|
+
continue;
|
|
5612
|
+
const s = evaluateScope(c.scope, ctx);
|
|
5613
|
+
for (const f of s.openFacts)
|
|
5614
|
+
openFacts.add(f);
|
|
5615
|
+
if (s.value !== "TRUE")
|
|
5616
|
+
continue;
|
|
5617
|
+
const fresh = closureFresh(c, at);
|
|
5618
|
+
proof.closures.push({ registrar: id, scope: c.scope, at: c.at, fresh });
|
|
5619
|
+
if (fresh) {
|
|
5620
|
+
covered = true;
|
|
5621
|
+
closedLists.push(c.authorities);
|
|
5622
|
+
}
|
|
5623
|
+
}
|
|
5624
|
+
if (!covered)
|
|
5625
|
+
staleClosures.push(id);
|
|
5626
|
+
}
|
|
5627
|
+
const supersededNow = new Set((reg.supersessions ?? []).filter((s) => s.from <= memberAt).map((s) => s.superseded));
|
|
5628
|
+
const revoked = new Set(reg.revoked ?? []);
|
|
5629
|
+
const liveAuthorities = /* @__PURE__ */ new Set();
|
|
5630
|
+
const trueAuthorities = /* @__PURE__ */ new Set();
|
|
5631
|
+
for (const claim of reg.claims) {
|
|
5632
|
+
if (opts.ablate !== "C7" || opts.snapshot) {
|
|
5633
|
+
if (!inForce(claim, memberAt)) {
|
|
5634
|
+
proof.dropped.push({ authority: claim.authority, registrar: id, reason: "not_in_force" });
|
|
5635
|
+
continue;
|
|
5636
|
+
}
|
|
5637
|
+
if (supersededNow.has(claim.authority)) {
|
|
5638
|
+
proof.dropped.push({ authority: claim.authority, registrar: id, reason: "superseded" });
|
|
5639
|
+
continue;
|
|
5640
|
+
}
|
|
5641
|
+
if (revoked.has(claim.authority)) {
|
|
5642
|
+
proof.dropped.push({ authority: claim.authority, registrar: id, reason: "revoked" });
|
|
5643
|
+
continue;
|
|
5644
|
+
}
|
|
5645
|
+
}
|
|
5646
|
+
liveAuthorities.add(claim.authority);
|
|
5647
|
+
const s = evaluateScope(claim.scope, ctx);
|
|
5648
|
+
for (const f of s.openFacts)
|
|
5649
|
+
openFacts.add(f);
|
|
5650
|
+
if (s.value === "TRUE")
|
|
5651
|
+
trueAuthorities.add(claim.authority);
|
|
5652
|
+
if (s.value === "FALSE")
|
|
5653
|
+
continue;
|
|
5654
|
+
const within = opts.ablate === "C6" ? { value: "TRUE", openFacts: [] } : cert;
|
|
5655
|
+
if (s.value === "UNDECIDED" || within.value === "UNDECIDED")
|
|
5656
|
+
continue;
|
|
5657
|
+
if (within.value === "FALSE")
|
|
5658
|
+
continue;
|
|
5659
|
+
candidates2.push({ authority: claim.authority, version: claim.version ?? null, registrar: id, scope: claim.scope, exclusive: claim.exclusive === true });
|
|
5660
|
+
}
|
|
5661
|
+
if (opts.ablate !== "C8" && closedLists.length > 0) {
|
|
5662
|
+
for (const a of new Set(closedLists.flat())) {
|
|
5663
|
+
if (!liveAuthorities.has(a))
|
|
5664
|
+
disagreements.push({ registrar: id, authority: a, reason: "closed_but_not_claimed" });
|
|
5665
|
+
}
|
|
5666
|
+
for (const a of trueAuthorities) {
|
|
5667
|
+
if (!closedLists.some((l) => l.includes(a)))
|
|
5668
|
+
disagreements.push({ registrar: id, authority: a, reason: "claimed_but_not_closed" });
|
|
5669
|
+
}
|
|
5670
|
+
}
|
|
5671
|
+
}
|
|
5672
|
+
proof.dropped.sort((a, b) => a.authority + a.registrar < b.authority + b.registrar ? -1 : 1);
|
|
5673
|
+
proof.closures.sort((a, b) => a.registrar + a.scope + a.at < b.registrar + b.scope + b.at ? -1 : 1);
|
|
5674
|
+
if (openFacts.size > 0 || unreachable.length > 0 || staleClosures.length > 0 || disagreements.length > 0 || staleHeads.length > 0) {
|
|
5675
|
+
return {
|
|
5676
|
+
status: "INCOMPLETE",
|
|
5677
|
+
missing: {
|
|
5678
|
+
context_facts: [...openFacts].sort(),
|
|
5679
|
+
unreachable_registrars: unreachable.sort(),
|
|
5680
|
+
stale_closures: staleClosures.sort(),
|
|
5681
|
+
stale_heads: staleHeads.sort(),
|
|
5682
|
+
closure_disagreements: disagreements.sort((a, b) => a.registrar + "\0" + a.authority < b.registrar + "\0" + b.authority ? -1 : 1)
|
|
5683
|
+
},
|
|
5684
|
+
proof
|
|
5685
|
+
};
|
|
5686
|
+
}
|
|
5687
|
+
const exclusives = candidates2.filter((c) => c.exclusive);
|
|
5688
|
+
const conflictPairs = exclusives.filter((c) => exclusives.some((o) => o.registrar !== c.registrar));
|
|
5689
|
+
if (conflictPairs.length > 0) {
|
|
5690
|
+
proof.conflicts.push({
|
|
5691
|
+
context_covered_by: conflictPairs.map((c) => ({ registrar: c.registrar, authority: c.authority, scope: c.scope })).sort((a, b) => a.registrar + a.authority < b.registrar + b.authority ? -1 : 1)
|
|
5692
|
+
});
|
|
5693
|
+
return { status: "CONFLICT", conflicts: proof.conflicts, proof };
|
|
5694
|
+
}
|
|
5695
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5696
|
+
const applicable = [];
|
|
5697
|
+
for (const c of [...candidates2].sort((a, b) => a.authority + "\0" + a.registrar < b.authority + "\0" + b.registrar ? -1 : 1)) {
|
|
5698
|
+
const key = c.authority + "\0" + c.registrar;
|
|
5699
|
+
if (seen.has(key))
|
|
5700
|
+
continue;
|
|
5701
|
+
seen.add(key);
|
|
5702
|
+
applicable.push({ authority: c.authority, version: c.version, registrar: c.registrar, scope: c.scope });
|
|
5703
|
+
}
|
|
5704
|
+
return { status: "RESOLVED", applicable, proof };
|
|
5705
|
+
}
|
|
5706
|
+
|
|
5707
|
+
// node_modules/@nomosprotocol/verify/dist/registrar.js
|
|
5708
|
+
var LOG_GENESIS = "0".repeat(64);
|
|
5709
|
+
var registrarHeadPayload = (h, log = "nomos-exchange-log") => jcs({ log, size: h.size, hash: h.hash, at: h.at });
|
|
5710
|
+
function verifyLogChain(entries) {
|
|
5711
|
+
let prev = LOG_GENESIS;
|
|
5712
|
+
const hashAt = /* @__PURE__ */ new Map([[0, LOG_GENESIS]]);
|
|
5713
|
+
for (const [i, e] of entries.entries()) {
|
|
5714
|
+
if (e.seq !== i + 1)
|
|
5715
|
+
return { ok: false, detail: `entry ${i + 1}: its seq is ${e.seq}` };
|
|
5716
|
+
if (e.prev_hash !== prev)
|
|
5717
|
+
return { ok: false, detail: `entry ${e.seq}: prev_hash does not match entry ${e.seq - 1}` };
|
|
5718
|
+
const { hash, ...body } = e;
|
|
5719
|
+
if (sha256Hex(jcs(body)) !== hash)
|
|
5720
|
+
return { ok: false, detail: `entry ${e.seq}: its hash does not match its contents` };
|
|
5721
|
+
prev = hash;
|
|
5722
|
+
hashAt.set(e.seq, hash);
|
|
5723
|
+
}
|
|
5724
|
+
return { ok: true, hashAt };
|
|
5725
|
+
}
|
|
5726
|
+
function verifyRegistrarLog(o) {
|
|
5727
|
+
const fail2 = (reason, detail) => ({ ok: false, reason, detail });
|
|
5728
|
+
const chain = verifyLogChain(o.entries);
|
|
5729
|
+
if (!chain.ok)
|
|
5730
|
+
return fail2("chain_broken", chain.detail);
|
|
5731
|
+
const h = o.head;
|
|
5732
|
+
if (!h || typeof h.size !== "number" || h.size > o.entries.length || chain.hashAt.get(h.size) !== h.hash) {
|
|
5733
|
+
return fail2("head_mismatch", `the head (size ${h?.size}) does not name an entry of this chain`);
|
|
5734
|
+
}
|
|
5735
|
+
if (!h.signature || !h.kid)
|
|
5736
|
+
return fail2("head_unsigned", "the head is not signed");
|
|
5737
|
+
const pinnedKid = kidOf(o.publicKeyPem);
|
|
5738
|
+
if (!pinnedKid || h.kid !== pinnedKid)
|
|
5739
|
+
return fail2("wrong_key", `the head is signed by ${h.kid}, not the pinned key ${pinnedKid ?? "(unreadable)"}`);
|
|
5740
|
+
if (!verifySuite("Ed25519", o.publicKeyPem, registrarHeadPayload(h, o.log), { signature: h.signature }).ok)
|
|
5741
|
+
return fail2("bad_signature", "the head signature does not verify under the pinned key");
|
|
5742
|
+
const age = o.now.getTime() - Date.parse(h.at);
|
|
5743
|
+
if (!Number.isFinite(age))
|
|
5744
|
+
return fail2("head_stale", "the head carries no time");
|
|
5745
|
+
if (age < -6e4)
|
|
5746
|
+
return fail2("head_in_future", `the head is dated ${h.at}, after now`);
|
|
5747
|
+
if (age > o.maxHeadAgeSeconds * 1e3)
|
|
5748
|
+
return fail2("head_stale", `the head is ${Math.round(age / 1e3)} s old; the bound is ${o.maxHeadAgeSeconds} s`);
|
|
5749
|
+
if (o.previous && chain.hashAt.get(o.previous.size) !== o.previous.hash) {
|
|
5750
|
+
return fail2("history_rewritten", `the head kept earlier (${o.previous.size}:${o.previous.hash.slice(0, 12)}\u2026) is not part of this log`);
|
|
5751
|
+
}
|
|
5752
|
+
return { ok: true, size: o.entries.length, head: { size: h.size, hash: h.hash, at: h.at, kid: h.kid } };
|
|
5753
|
+
}
|
|
5754
|
+
function foldRegistrarLog(entries, o) {
|
|
5755
|
+
const open = /* @__PURE__ */ new Map();
|
|
5756
|
+
const closedClaims = [];
|
|
5757
|
+
const closures = [];
|
|
5758
|
+
const recognitions = [];
|
|
5759
|
+
const supersessions = [];
|
|
5760
|
+
const revoked = /* @__PURE__ */ new Set();
|
|
5761
|
+
let head = null;
|
|
5762
|
+
for (const e of entries) {
|
|
5763
|
+
head = e.hash;
|
|
5764
|
+
if (e.kind === "applies") {
|
|
5765
|
+
const prior = open.get(e.name);
|
|
5766
|
+
if (prior)
|
|
5767
|
+
closedClaims.push({ ...prior, until: e.at });
|
|
5768
|
+
open.set(e.name, {
|
|
5769
|
+
authority: e.name,
|
|
5770
|
+
version: e.version ?? null,
|
|
5771
|
+
scope: typeof e.entry?.scope === "string" ? e.entry.scope : "always",
|
|
5772
|
+
exclusive: e.entry?.exclusive === true,
|
|
5773
|
+
from: e.at,
|
|
5774
|
+
until: typeof e.entry?.until === "string" ? e.entry.until : null,
|
|
5775
|
+
...typeof e.entry?.basis === "string" ? { basis: e.entry.basis } : {}
|
|
5776
|
+
});
|
|
5777
|
+
} else if (e.kind === "withdrawn") {
|
|
5778
|
+
const prior = open.get(e.name);
|
|
5779
|
+
if (prior) {
|
|
5780
|
+
closedClaims.push({ ...prior, until: e.at });
|
|
5781
|
+
open.delete(e.name);
|
|
5782
|
+
}
|
|
5783
|
+
} else if (e.kind === "revoked") {
|
|
5784
|
+
revoked.add(e.name);
|
|
5785
|
+
} else if (e.kind === "closed") {
|
|
5786
|
+
const scope = typeof e.entry?.scope === "string" ? e.entry.scope : "always";
|
|
5787
|
+
const authorities = Array.isArray(e.entry?.authorities) ? e.entry.authorities.filter((a) => typeof a === "string") : [];
|
|
5788
|
+
closures.push({ scope, authorities, at: e.at, label: e.name, ...typeof e.entry?.max_age_days === "number" ? { max_age_days: e.entry.max_age_days } : {} });
|
|
5789
|
+
} else if (e.kind === "recognizes") {
|
|
5790
|
+
recognitions.push({ to: e.name, scope: typeof e.entry?.scope === "string" ? e.entry.scope : "always" });
|
|
5791
|
+
} else if (e.kind === "superseded") {
|
|
5792
|
+
if (typeof e.entry?.by === "string")
|
|
5793
|
+
supersessions.push({ superseded: e.name, by: e.entry.by, from: e.at });
|
|
5794
|
+
}
|
|
5795
|
+
}
|
|
5796
|
+
return {
|
|
5797
|
+
id: o.id,
|
|
5798
|
+
certified_scope: o.certifiedScope ?? "always",
|
|
5799
|
+
claims: [...closedClaims, ...open.values()],
|
|
5800
|
+
closures,
|
|
5801
|
+
recognitions,
|
|
5802
|
+
supersessions,
|
|
5803
|
+
revoked: [...revoked].sort(),
|
|
5804
|
+
head
|
|
5805
|
+
};
|
|
5806
|
+
}
|
|
5807
|
+
|
|
5473
5808
|
// src/verify-chain.ts
|
|
5474
5809
|
var CHAIN_PROTOCOL_VERSION2 = "1";
|
|
5475
5810
|
var DEFAULT_BASE = "https://www.nomosprotocol.com";
|
|
@@ -5646,6 +5981,68 @@ ${tool}`);
|
|
|
5646
5981
|
return lines.join("\n");
|
|
5647
5982
|
}
|
|
5648
5983
|
|
|
5984
|
+
// src/act/registrars.ts
|
|
5985
|
+
var RegistrarUnavailable = class extends Error {
|
|
5986
|
+
constructor(message, retryAfterSeconds, registrar) {
|
|
5987
|
+
super(message);
|
|
5988
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
5989
|
+
this.registrar = registrar;
|
|
5990
|
+
this.name = "RegistrarUnavailable";
|
|
5991
|
+
}
|
|
5992
|
+
};
|
|
5993
|
+
var PAGE = 1e3;
|
|
5994
|
+
function registrarSource(o) {
|
|
5995
|
+
const f = o.fetch ?? fetch, now = o.now ?? (() => /* @__PURE__ */ new Date());
|
|
5996
|
+
const base = o.url.replace(/\/$/, "");
|
|
5997
|
+
const maxHeadAge = o.maxHeadAgeSeconds ?? 600, refresh = (o.refreshSeconds ?? 60) * 1e3;
|
|
5998
|
+
let view = null, kept = o.initialHead ?? null;
|
|
5999
|
+
let fetchedAt = 0, inFlight = null, lastError = "";
|
|
6000
|
+
async function getJson2(path) {
|
|
6001
|
+
const res = await f(`${base}${path}`, { headers: { accept: "application/json" } });
|
|
6002
|
+
if (!res.ok) throw new Error(`${base}${path} answered ${res.status}`);
|
|
6003
|
+
return res.json();
|
|
6004
|
+
}
|
|
6005
|
+
async function load() {
|
|
6006
|
+
fetchedAt = now().getTime();
|
|
6007
|
+
try {
|
|
6008
|
+
const head = await getJson2("/.well-known/nomos-exchange-log/head");
|
|
6009
|
+
const entries = [];
|
|
6010
|
+
for (let after = 0; ; ) {
|
|
6011
|
+
const page2 = await getJson2(`/.well-known/nomos-exchange-log?after=${after}&limit=${PAGE}`);
|
|
6012
|
+
const got = Array.isArray(page2?.entries) ? page2.entries : [];
|
|
6013
|
+
entries.push(...got);
|
|
6014
|
+
if (got.length < PAGE || !page2.next) break;
|
|
6015
|
+
after = got[got.length - 1].seq;
|
|
6016
|
+
}
|
|
6017
|
+
const vouched = entries.slice(0, Math.min(entries.length, Number(head?.size) || 0));
|
|
6018
|
+
const check = verifyRegistrarLog({ entries: vouched, head, publicKeyPem: o.publicKeyPem, now: now(), maxHeadAgeSeconds: maxHeadAge, previous: kept });
|
|
6019
|
+
if (!check.ok) {
|
|
6020
|
+
lastError = `${check.reason}: ${check.detail}`;
|
|
6021
|
+
if (check.reason === "history_rewritten" || check.reason === "wrong_key" || check.reason === "bad_signature" || check.reason === "chain_broken") view = null;
|
|
6022
|
+
return;
|
|
6023
|
+
}
|
|
6024
|
+
view = { record: foldRegistrarLog(vouched, { id: o.id, certifiedScope: o.certifiedScope }), head: check.head };
|
|
6025
|
+
kept = { size: check.head.size, hash: check.head.hash };
|
|
6026
|
+
lastError = "";
|
|
6027
|
+
} catch (e) {
|
|
6028
|
+
lastError = String(e?.message ?? e);
|
|
6029
|
+
}
|
|
6030
|
+
}
|
|
6031
|
+
const source = (async () => {
|
|
6032
|
+
const t = now().getTime();
|
|
6033
|
+
if (!inFlight && t - fetchedAt >= refresh) inFlight = load().finally(() => {
|
|
6034
|
+
inFlight = null;
|
|
6035
|
+
});
|
|
6036
|
+
if (inFlight) await inFlight;
|
|
6037
|
+
if (!view || t - Date.parse(view.head.at) > maxHeadAge * 1e3) {
|
|
6038
|
+
throw new RegistrarUnavailable(`Registrar ${o.id} (${base}) has no current, verified log${lastError ? `: ${lastError}` : ""}. Not committing until the law that applies can be read.`, Math.max(1, Math.ceil(refresh / 1e3)), o.id);
|
|
6039
|
+
}
|
|
6040
|
+
return view;
|
|
6041
|
+
});
|
|
6042
|
+
source.id = o.id;
|
|
6043
|
+
return source;
|
|
6044
|
+
}
|
|
6045
|
+
|
|
5649
6046
|
// src/act/bytes.ts
|
|
5650
6047
|
var utf82 = (s) => new TextEncoder().encode(s);
|
|
5651
6048
|
var fromUtf82 = (b) => new TextDecoder().decode(b);
|
|
@@ -5926,7 +6323,7 @@ var STATUS = { AUTHORIZED: 201, ESCALATED: 202, INCOMPLETE: 422, DENIED: 403, RE
|
|
|
5926
6323
|
var statusFor = (decision) => STATUS[decision] ?? 400;
|
|
5927
6324
|
var ACT_MEDIA_TYPE = "application/nomos-act+json";
|
|
5928
6325
|
var HINTS = {
|
|
5929
|
-
INCOMPLETE: (v) => `Missing facts that could change the outcome: ${(v.open_facts ?? []).join(", ")}. Bring them as testimony from a witness certified for each claim, or as the channel the authority declares.`,
|
|
6326
|
+
INCOMPLETE: (v) => v.reason_code === "laws_not_presented" ? `Other law also governs this act here: ${(v.laws ?? []).join(", ")}. This system commits only when every governing law is carried; this Act carries one.` : v.reason_code === "resolution_incomplete" ? `This system cannot yet establish which law governs this act${v.missing?.context_facts?.length ? `: its own knowledge of the act lacks ${v.missing.context_facts.join(", ")}` : v.missing?.stale_closures?.length ? ": a registrar it honours does not cover this case" : ""}. Nothing the carrier sends can supply this; nothing is committed while the governing law is unknown.` : v.reason_code === "resolution_conflict" ? "Two registrars each claim exclusive precedence over this act. A person must settle which law governs before it can be committed." : `Missing facts that could change the outcome: ${(v.open_facts ?? []).join(", ")}. Bring them as testimony from a witness certified for each claim, or as the channel the authority declares.`,
|
|
5930
6327
|
ESCALATED: (v) => `Needs ${v.consents_required} approval(s) from role ${v.role}. Request consent over act_digest ${v.act_digest} and resubmit this same Act before ${v.retry_until}.`,
|
|
5931
6328
|
DENIED: (v) => `Rule ${v.rule ?? "(default)"} refuses this action. No approval can change a denial.`,
|
|
5932
6329
|
WRONG_RELYING_PARTY: () => "The Act is addressed to another system. Build it with this relying_party_id.",
|
|
@@ -6039,6 +6436,24 @@ function accept(o) {
|
|
|
6039
6436
|
maxWindowSeconds
|
|
6040
6437
|
});
|
|
6041
6438
|
}
|
|
6439
|
+
async function resolveFor(act2, authority, facts, at, reuse) {
|
|
6440
|
+
if (!o.resolution) return null;
|
|
6441
|
+
const views = reuse ?? await Promise.all(o.resolution.registrars.map(async (src) => [src.id, await src()]));
|
|
6442
|
+
const context = { ...await o.resolution.context(act2, facts) };
|
|
6443
|
+
const r = resolveApplicableSet(
|
|
6444
|
+
{ pins: views.map(([id]) => id), registrars: Object.fromEntries(views.map(([id, v]) => [id, v.record])) },
|
|
6445
|
+
{ context, at: at.toISOString() }
|
|
6446
|
+
);
|
|
6447
|
+
const heads = Object.fromEntries(views.map(([id, v]) => [id, v.head.hash]));
|
|
6448
|
+
const applicable = r.status === "RESOLVED" ? [...new Set(r.applicable.map((m) => m.authority))].sort() : [];
|
|
6449
|
+
const info = { status: r.status, context, applicable, heads };
|
|
6450
|
+
if (r.status === "INCOMPLETE") return { ok: false, info, views, verdict: { decision: "INCOMPLETE", reason_code: "resolution_incomplete", missing: r.missing } };
|
|
6451
|
+
if (r.status === "CONFLICT") return { ok: false, info, views, verdict: { decision: "INCOMPLETE", reason_code: "resolution_conflict", conflicts: r.conflicts } };
|
|
6452
|
+
const carried = new Set([authority.registrarName, authority.artifactId].filter((x) => !!x));
|
|
6453
|
+
const notCarried = applicable.filter((a) => !carried.has(a));
|
|
6454
|
+
if (notCarried.length) return { ok: false, info: { ...info, laws_not_presented: notCarried }, views, verdict: { decision: "INCOMPLETE", reason_code: "laws_not_presented", laws: notCarried } };
|
|
6455
|
+
return { ok: true, info, views };
|
|
6456
|
+
}
|
|
6042
6457
|
async function handle(req) {
|
|
6043
6458
|
const ctype = String(req.headers["content-type"] ?? "").split(";")[0].trim().toLowerCase();
|
|
6044
6459
|
if ((req.method ?? "POST").toUpperCase() !== "POST") return { status: 405, headers: { allow: "POST", "content-type": "application/json" }, body: { error: "POST an Act here." } };
|
|
@@ -6085,8 +6500,31 @@ function accept(o) {
|
|
|
6085
6500
|
if (verdict.decision === "REPLAYED") {
|
|
6086
6501
|
return answer(verdict, { act_id: act2.act_id, receipt: await store.receiptFor(act2.nonce) });
|
|
6087
6502
|
}
|
|
6503
|
+
let resolved = null;
|
|
6504
|
+
if (verdict.decision === "AUTHORIZED" && o.resolution) {
|
|
6505
|
+
try {
|
|
6506
|
+
resolved = await resolveFor(act2, authority, facts, verifiedAt);
|
|
6507
|
+
} catch (e) {
|
|
6508
|
+
if (!(e instanceof RegistrarUnavailable)) throw e;
|
|
6509
|
+
return {
|
|
6510
|
+
status: 503,
|
|
6511
|
+
headers: { "content-type": "application/json", "retry-after": String(e.retryAfterSeconds) },
|
|
6512
|
+
body: { error: "The law that governs this act cannot be read right now, so nothing is committed. Resubmit this same Act later.", detail: e.message, registrar: e.registrar, retry_after: e.retryAfterSeconds }
|
|
6513
|
+
};
|
|
6514
|
+
}
|
|
6515
|
+
if (resolved && !resolved.ok) {
|
|
6516
|
+
const held = { ...resolved.verdict, act_id: act2.act_id, act_digest: verdict.act_digest, resolution: resolved.info };
|
|
6517
|
+
await o.onVerdict?.(held, { ...receiptOf(held, facts), resolution: resolved.info });
|
|
6518
|
+
if (o.mode === "shadow") {
|
|
6519
|
+
const a = answer(held);
|
|
6520
|
+
return { ...a, status: 200, body: { ...a.body, shadow: true } };
|
|
6521
|
+
}
|
|
6522
|
+
return answer(held);
|
|
6523
|
+
}
|
|
6524
|
+
}
|
|
6525
|
+
const withResolution = (r) => resolved?.ok ? { ...r, resolution: resolved.info } : r;
|
|
6088
6526
|
if (verdict.decision !== "AUTHORIZED" || o.mode === "shadow") {
|
|
6089
|
-
await o.onVerdict?.(verdict, receiptOf(verdict, facts));
|
|
6527
|
+
await o.onVerdict?.(verdict, withResolution(receiptOf(verdict, facts)));
|
|
6090
6528
|
if (verdict.decision === "ESCALATED") {
|
|
6091
6529
|
const esc3 = (act2.authority.artifact.governance?.escalations ?? []).find((e) => e?.id === verdict.escalation_id);
|
|
6092
6530
|
return answer(verdict, { role: esc3?.role_required ?? null, retry_until: act2.expires_at });
|
|
@@ -6104,17 +6542,23 @@ function accept(o) {
|
|
|
6104
6542
|
finalFacts = fresh;
|
|
6105
6543
|
final = verifyWith(act2, authority, fresh, verifiedAt, false, rev);
|
|
6106
6544
|
if (final.decision !== "AUTHORIZED") throw new Rollback(answer(final));
|
|
6545
|
+
if (o.resolution) {
|
|
6546
|
+
const again = await resolveFor(act2, authority, fresh, verifiedAt, resolved?.views);
|
|
6547
|
+
if (again && !again.ok) throw new Rollback(answer({ ...again.verdict, act_id: act2.act_id, resolution: again.info }));
|
|
6548
|
+
resolved = again;
|
|
6549
|
+
}
|
|
6107
6550
|
}
|
|
6108
6551
|
}
|
|
6109
6552
|
const action = structuredClone({ type: act2.action.type, ...act2.action.subject !== void 0 ? { subject: act2.action.subject } : {}, params: act2.action.params ?? {} });
|
|
6110
6553
|
const result = await o.commit(action, { tx: t.tx, actId: act2.act_id });
|
|
6111
|
-
const receipt = receiptOf(final, finalFacts, now());
|
|
6554
|
+
const receipt = withResolution(receiptOf(final, finalFacts, now()));
|
|
6112
6555
|
await t.putReceipt(act2.nonce, receipt, act2);
|
|
6113
6556
|
await o.onVerdict?.(final, receipt);
|
|
6114
6557
|
return answer(final, { receipt, ...result !== void 0 ? { result } : {} });
|
|
6115
6558
|
});
|
|
6116
6559
|
} catch (e) {
|
|
6117
6560
|
if (e instanceof Rollback) return e.answer;
|
|
6561
|
+
if (e instanceof RegistrarUnavailable) return { status: 503, headers: { "content-type": "application/json", "retry-after": String(e.retryAfterSeconds) }, body: { error: "The law that governs this act cannot be read right now, so nothing is committed. Resubmit this same Act later.", detail: e.message, registrar: e.registrar, retry_after: e.retryAfterSeconds } };
|
|
6118
6562
|
if (e instanceof LostRace) return answer({ decision: "REPLAYED" }, { act_id: act2.act_id, receipt: await store.receiptFor(act2.nonce) });
|
|
6119
6563
|
return { status: 500, headers: { "content-type": "application/json" }, body: { error: "The commit failed and was rolled back; nothing was applied.", detail: String(e?.message ?? e) } };
|
|
6120
6564
|
}
|
|
@@ -6879,6 +7323,7 @@ var scriptHash = (js) => `'sha256-${btoa(String.fromCharCode(...sha256(utf82(js)
|
|
|
6879
7323
|
var CSP = () => `default-src 'none'; script-src ${scriptHash(APPROVE_JS)} ${scriptHash(ENROL_JS)}; style-src 'unsafe-inline'; connect-src 'self'; form-action 'none'; frame-ancestors 'none'; base-uri 'none'`;
|
|
6880
7324
|
|
|
6881
7325
|
// src/act/carrier.ts
|
|
7326
|
+
var RESOLUTION_HOLDS = /* @__PURE__ */ new Set(["laws_not_presented", "resolution_incomplete", "resolution_conflict"]);
|
|
6882
7327
|
var STATUS_OF = { AUTHORIZED: "committed", ESCALATED: "escalated", INCOMPLETE: "incomplete", DENIED: "denied", REPLAYED: "replayed" };
|
|
6883
7328
|
var NomosActError = class extends Error {
|
|
6884
7329
|
constructor(message) {
|
|
@@ -6898,9 +7343,9 @@ async function act(o) {
|
|
|
6898
7343
|
const entry = issuer2.authorities.find((a) => a.artifact_id === accepted.artifact_id);
|
|
6899
7344
|
if (!entry) throw new NomosActError(`The issuer at ${accepted.issuer} does not publish ${accepted.artifact_id}.`);
|
|
6900
7345
|
const artifact = await getJson(f, entry.artifact_url, "the authority");
|
|
6901
|
-
let
|
|
7346
|
+
let inForce2;
|
|
6902
7347
|
if (accepted.currency_policy === "record_or_statement" && !accepted.in_force_seal_hash && entry.in_force_url) {
|
|
6903
|
-
|
|
7348
|
+
inForce2 = await getJson(f, entry.in_force_url, "the in-force statement").catch(() => void 0);
|
|
6904
7349
|
}
|
|
6905
7350
|
const inputs = artifact?.data_contract?.inputs ?? {};
|
|
6906
7351
|
const witnessed = Object.entries(inputs).filter(([, i]) => i?.source === "testimony").map(([n]) => n);
|
|
@@ -6940,7 +7385,7 @@ async function act(o) {
|
|
|
6940
7385
|
testimony.push(t);
|
|
6941
7386
|
if (Array.isArray(body2.key_certs)) available.push(...body2.key_certs);
|
|
6942
7387
|
}
|
|
6943
|
-
const theAct = buildAct({ relyingParty: rp.relying_party_id, action: o.action, artifact, keyCerts: [], testimony, presenterFacts: o.presenterFacts, inForce, windowSeconds });
|
|
7388
|
+
const theAct = buildAct({ relyingParty: rp.relying_party_id, action: o.action, artifact, keyCerts: [], testimony, presenterFacts: o.presenterFacts, inForce: inForce2, windowSeconds });
|
|
6944
7389
|
present(theAct, available);
|
|
6945
7390
|
let { status, body } = await submit(f, rp.act_endpoint, theAct);
|
|
6946
7391
|
let approvalUrl;
|
|
@@ -6968,6 +7413,10 @@ async function act(o) {
|
|
|
6968
7413
|
}
|
|
6969
7414
|
}
|
|
6970
7415
|
const kind = STATUS_OF[body.decision] ?? "refused";
|
|
7416
|
+
if (kind === "incomplete" && RESOLUTION_HOLDS.has(body.reason_code)) {
|
|
7417
|
+
const laws = Array.isArray(body.laws) ? body.laws : [];
|
|
7418
|
+
return done("incomplete", body, theAct, { missing: [], summary: body.reason_code === "laws_not_presented" ? `Not committed: other law also governs this act at ${rp.relying_party_id} (${laws.join(", ")}), and this Act carries only ${theAct.authority?.artifact?.meta?.artifact_id ?? "one authority"}.` : `Not committed: ${body.hint ?? `${rp.relying_party_id} cannot yet settle which law governs this act (${body.reason_code}).`}` });
|
|
7419
|
+
}
|
|
6971
7420
|
if (kind === "incomplete") {
|
|
6972
7421
|
const missing = (body.open_facts ?? []).map((fact) => {
|
|
6973
7422
|
const why = unavailable.find((u) => u.fact === fact || fact.startsWith(u.fact + "."));
|
|
@@ -6999,6 +7448,7 @@ async function getJson(f, url, what) {
|
|
|
6999
7448
|
async function submit(f, endpoint, theAct) {
|
|
7000
7449
|
const res = await f(endpoint, { method: "POST", headers: { "content-type": ACT_MEDIA_TYPE }, body: JSON.stringify(theAct) });
|
|
7001
7450
|
const body = await res.json().catch(() => ({ decision: "MALFORMED", reason_code: "unreadable_response" }));
|
|
7451
|
+
if (res.status === 503) throw new NomosActError(`The relying party is not committing right now (503): ${body?.error ?? ""}${body?.retry_after ? ` Resubmit this same Act after ${body.retry_after} s.` : ""}`);
|
|
7002
7452
|
if (res.status >= 500) throw new NomosActError(`The relying party failed to commit (${res.status}): ${body?.error ?? ""}`);
|
|
7003
7453
|
return { status: res.status, body };
|
|
7004
7454
|
}
|
|
@@ -7202,6 +7652,7 @@ ${buttons}</body>`;
|
|
|
7202
7652
|
NomosRateLimitError,
|
|
7203
7653
|
NomosValidationError,
|
|
7204
7654
|
NomosWebhookSignatureError,
|
|
7655
|
+
RegistrarUnavailable,
|
|
7205
7656
|
RegistryError,
|
|
7206
7657
|
RevocationUnavailable,
|
|
7207
7658
|
WELL_KNOWN,
|
|
@@ -7232,6 +7683,7 @@ ${buttons}</body>`;
|
|
|
7232
7683
|
postgresStore,
|
|
7233
7684
|
presentedCertificates,
|
|
7234
7685
|
readAttestation,
|
|
7686
|
+
registrarSource,
|
|
7235
7687
|
reliedKids,
|
|
7236
7688
|
revocationListCertificates,
|
|
7237
7689
|
revocationSource,
|