@nomosprotocol/sdk 1.2.0 → 1.3.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 +22 -2
- package/dist/index.cjs +261 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +171 -12
- package/dist/index.d.ts +171 -12
- package/dist/index.js +257 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Every public authority on the [NOMOS Exchange](https://www.nomosprotocol.com/exc
|
|
|
14
14
|
import { nomos } from "@nomosprotocol/sdk";
|
|
15
15
|
|
|
16
16
|
const verdict = await nomos.can({
|
|
17
|
-
authority: "eu-ai-act
|
|
17
|
+
authority: "eu-ai-act.nomos",
|
|
18
18
|
ai_categorises_biometric_data_for_sensitive_attributes: true,
|
|
19
19
|
});
|
|
20
20
|
|
|
@@ -29,7 +29,7 @@ Facts can be spread flat alongside `authority` (as above), or passed explicitly:
|
|
|
29
29
|
|
|
30
30
|
```ts
|
|
31
31
|
const verdict = await nomos.can({
|
|
32
|
-
authority: "eu-ai-act
|
|
32
|
+
authority: "eu-ai-act.nomos",
|
|
33
33
|
inputs: { ai_categorises_biometric_data_for_sensitive_attributes: true },
|
|
34
34
|
action: "screen a new feature before launch", // optional, recorded in the transcript
|
|
35
35
|
});
|
|
@@ -54,6 +54,26 @@ const verdict = await nomos.can({
|
|
|
54
54
|
|
|
55
55
|
Every call mints a permanent, cryptographically sealed transcript — open `query_id` any time at `nomosprotocol.com/queries/<query_id>` to replay exactly what was asked and answered, bound to the exact authority version that responded.
|
|
56
56
|
|
|
57
|
+
### Error handling
|
|
58
|
+
|
|
59
|
+
A failed call (unknown authority, network issue, upstream error) rejects with a typed `NomosError` subclass — never a bare `Error` — so you can branch on `instanceof` or the stable `.code` string:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { nomos, NomosNotFoundError, NomosNetworkError } from "@nomosprotocol/sdk";
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const verdict = await nomos.can({ authority: "eu-ai-act.nomos", ...facts });
|
|
66
|
+
} catch (err) {
|
|
67
|
+
if (err instanceof NomosNotFoundError) {
|
|
68
|
+
// authority slug/id doesn't exist — err.code === 'not_found'
|
|
69
|
+
} else if (err instanceof NomosNetworkError) {
|
|
70
|
+
// request timed out or the network failed
|
|
71
|
+
} else {
|
|
72
|
+
throw err;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
57
77
|
### Options
|
|
58
78
|
|
|
59
79
|
```ts
|
package/dist/index.cjs
CHANGED
|
@@ -25,13 +25,16 @@ __export(index_exports, {
|
|
|
25
25
|
NomosAuthenticationError: () => NomosAuthenticationError,
|
|
26
26
|
NomosAuthorizationError: () => NomosAuthorizationError,
|
|
27
27
|
NomosError: () => NomosError,
|
|
28
|
+
NomosIssuerNotTrustedError: () => NomosIssuerNotTrustedError,
|
|
28
29
|
NomosNetworkError: () => NomosNetworkError,
|
|
29
30
|
NomosNotFoundError: () => NomosNotFoundError,
|
|
31
|
+
NomosPaymentRequiredError: () => NomosPaymentRequiredError,
|
|
30
32
|
NomosRateLimitError: () => NomosRateLimitError,
|
|
31
33
|
NomosValidationError: () => NomosValidationError,
|
|
32
34
|
NomosWebhookSignatureError: () => NomosWebhookSignatureError,
|
|
33
35
|
can: () => can,
|
|
34
|
-
nomos: () => nomos
|
|
36
|
+
nomos: () => nomos,
|
|
37
|
+
verifyChain: () => verifyChain
|
|
35
38
|
});
|
|
36
39
|
module.exports = __toCommonJS(index_exports);
|
|
37
40
|
|
|
@@ -42,8 +45,10 @@ __export(errors_exports, {
|
|
|
42
45
|
NomosAuthenticationError: () => NomosAuthenticationError,
|
|
43
46
|
NomosAuthorizationError: () => NomosAuthorizationError,
|
|
44
47
|
NomosError: () => NomosError,
|
|
48
|
+
NomosIssuerNotTrustedError: () => NomosIssuerNotTrustedError,
|
|
45
49
|
NomosNetworkError: () => NomosNetworkError,
|
|
46
50
|
NomosNotFoundError: () => NomosNotFoundError,
|
|
51
|
+
NomosPaymentRequiredError: () => NomosPaymentRequiredError,
|
|
47
52
|
NomosRateLimitError: () => NomosRateLimitError,
|
|
48
53
|
NomosValidationError: () => NomosValidationError,
|
|
49
54
|
NomosWebhookSignatureError: () => NomosWebhookSignatureError
|
|
@@ -107,6 +112,21 @@ var NomosWebhookSignatureError = class extends NomosError {
|
|
|
107
112
|
this.name = "NomosWebhookSignatureError";
|
|
108
113
|
}
|
|
109
114
|
};
|
|
115
|
+
var NomosPaymentRequiredError = class extends NomosError {
|
|
116
|
+
constructor(message, priceUsd, purchaseUrl, requestId) {
|
|
117
|
+
super(message, "payment_required", 402, requestId);
|
|
118
|
+
this.name = "NomosPaymentRequiredError";
|
|
119
|
+
this.priceUsd = priceUsd;
|
|
120
|
+
this.purchaseUrl = purchaseUrl;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var NomosIssuerNotTrustedError = class extends NomosError {
|
|
124
|
+
constructor(message, reason, requestId) {
|
|
125
|
+
super(message, "issuer_not_trusted", 403, requestId);
|
|
126
|
+
this.name = "NomosIssuerNotTrustedError";
|
|
127
|
+
this.reason = reason;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
110
130
|
|
|
111
131
|
// src/util.ts
|
|
112
132
|
async function sleep(ms) {
|
|
@@ -526,6 +546,192 @@ var Webhooks = class {
|
|
|
526
546
|
}
|
|
527
547
|
};
|
|
528
548
|
|
|
549
|
+
// src/can.ts
|
|
550
|
+
var CHAIN_PROTOCOL_VERSION = "1";
|
|
551
|
+
var DEFAULT_EXCHANGE_BASE = "https://www.nomosprotocol.com";
|
|
552
|
+
function splitFacts(params) {
|
|
553
|
+
const { authority, artifact_id, action, inputs, ...flat } = params;
|
|
554
|
+
void authority;
|
|
555
|
+
void artifact_id;
|
|
556
|
+
const facts = inputs && typeof inputs === "object" ? inputs : flat;
|
|
557
|
+
return { facts, action };
|
|
558
|
+
}
|
|
559
|
+
function mapHttpError(status, data, requestId) {
|
|
560
|
+
const message = data?.error ?? data?.message ?? `NOMOS query failed (HTTP ${status})`;
|
|
561
|
+
if (data?.code === "PURCHASE_REQUIRED") {
|
|
562
|
+
throw new NomosPaymentRequiredError(message, data.price_usd ?? 0, data.purchase_url ?? "", requestId);
|
|
563
|
+
}
|
|
564
|
+
switch (status) {
|
|
565
|
+
case 401:
|
|
566
|
+
throw new NomosAuthenticationError(message, requestId);
|
|
567
|
+
case 403:
|
|
568
|
+
throw new NomosAuthorizationError(message, requestId);
|
|
569
|
+
case 404:
|
|
570
|
+
throw new NomosNotFoundError(message, requestId);
|
|
571
|
+
case 422:
|
|
572
|
+
case 400:
|
|
573
|
+
throw new NomosValidationError(message, data?.details, requestId);
|
|
574
|
+
case 429:
|
|
575
|
+
throw new NomosRateLimitError(message, void 0, requestId);
|
|
576
|
+
default:
|
|
577
|
+
throw new NomosAPIError(message, status, requestId);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
function normalizeAuthorityQueryResult(data, authority) {
|
|
581
|
+
return {
|
|
582
|
+
allowed: data.verdict === "AUTHORIZED",
|
|
583
|
+
verdict: data.verdict,
|
|
584
|
+
reason: data.verdict_description,
|
|
585
|
+
rule: data.matched_rule_id ?? null,
|
|
586
|
+
query_id: data.query_id,
|
|
587
|
+
url: data.url,
|
|
588
|
+
authority: {
|
|
589
|
+
id: data.artifact?.id ?? authority,
|
|
590
|
+
title: data.artifact?.title ?? "",
|
|
591
|
+
standing: data.artifact?.standing ?? "",
|
|
592
|
+
...data.artifact?.attestation ? { attestation: data.artifact.attestation } : {}
|
|
593
|
+
},
|
|
594
|
+
...data.artifact?.version ? { version: data.artifact.version } : {},
|
|
595
|
+
missing_inputs: data.missing_inputs ?? [],
|
|
596
|
+
...typeof data.max_age === "number" ? { max_age: data.max_age } : {},
|
|
597
|
+
// authority-query.ts already returns { kind, rule_id, rule_name } — the public-safe shape
|
|
598
|
+
// CanResult uses directly.
|
|
599
|
+
...Array.isArray(data.obligations) && data.obligations.length > 0 ? { obligations: data.obligations } : {},
|
|
600
|
+
// NOMOS-SPEC-006 — present only when the issuer has actually revoked this exact sealed
|
|
601
|
+
// version; omitted (not false) when revocation doesn't structurally apply here, so "checked
|
|
602
|
+
// and clean" and "couldn't check" never look the same to a caller.
|
|
603
|
+
...data.revoked === true ? { revoked: true, revocation_reason: data.revocation_reason } : {}
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
async function canViaExchange(authority, facts, action, opts) {
|
|
607
|
+
const base = (opts?.baseUrl ?? DEFAULT_EXCHANGE_BASE).replace(/\/$/, "");
|
|
608
|
+
const url = `${base}/api/v1/can`;
|
|
609
|
+
let res;
|
|
610
|
+
try {
|
|
611
|
+
res = await fetch(url, {
|
|
612
|
+
method: "POST",
|
|
613
|
+
headers: { "Content-Type": "application/json" },
|
|
614
|
+
body: JSON.stringify({ artifact: authority, action, ...facts }),
|
|
615
|
+
signal: opts?.signal
|
|
616
|
+
});
|
|
617
|
+
} catch (err) {
|
|
618
|
+
if (err?.name === "AbortError") throw new NomosNetworkError("Request aborted");
|
|
619
|
+
throw new NomosNetworkError(err?.message ?? "Network error");
|
|
620
|
+
}
|
|
621
|
+
const requestId = res.headers.get("x-request-id") ?? "";
|
|
622
|
+
const data = await res.json().catch(() => null);
|
|
623
|
+
if (!res.ok) mapHttpError(res.status, data, requestId);
|
|
624
|
+
return normalizeAuthorityQueryResult(data, authority);
|
|
625
|
+
}
|
|
626
|
+
async function canViaExchangeAuthenticated(http, authority, facts, action) {
|
|
627
|
+
const { data } = await http.post("/api/v1/can", { artifact: authority, action, ...facts });
|
|
628
|
+
return normalizeAuthorityQueryResult(data, authority);
|
|
629
|
+
}
|
|
630
|
+
async function canViaArtifact(http, artifactId, facts, action) {
|
|
631
|
+
const isPublic = artifactId.startsWith("pub_");
|
|
632
|
+
const path = isPublic ? "/api/v1/verify" : "/api/v1/verify-decision";
|
|
633
|
+
const body = isPublic ? { artifact_id: artifactId, decision: action ?? "evaluate", inputs: facts } : { artifact_id: artifactId, decision: action ?? "evaluate", inputs: facts, caller: { correlation_id: globalThis.crypto.randomUUID() } };
|
|
634
|
+
const { data: raw } = await http.post(path, body);
|
|
635
|
+
const verdict = raw.verdict === "approved" ? "AUTHORIZED" : raw.verdict === "rejected" ? "DENIED" : raw.outcome === "auto_approved" ? "AUTHORIZED" : raw.outcome === "auto_rejected" ? "DENIED" : "ESCALATED";
|
|
636
|
+
return {
|
|
637
|
+
allowed: raw.allowed ?? verdict === "AUTHORIZED",
|
|
638
|
+
verdict,
|
|
639
|
+
reason: raw.verdict_description ?? "",
|
|
640
|
+
rule: raw.rule?.id ?? null,
|
|
641
|
+
authority: {
|
|
642
|
+
id: raw.artifact_id ?? artifactId,
|
|
643
|
+
title: raw.artifact_name ?? "",
|
|
644
|
+
standing: raw.confidence?.tier ?? ""
|
|
645
|
+
},
|
|
646
|
+
...raw.artifact_version ? { version: raw.artifact_version } : {},
|
|
647
|
+
missing_inputs: raw.incomplete_inputs?.fields ?? [],
|
|
648
|
+
...raw.audit ? { audit: { hash: raw.audit.hash ?? raw.audit_hash ?? "", timestamp: raw.audit.timestamp ?? raw.ts ?? (/* @__PURE__ */ new Date()).toISOString() } } : {},
|
|
649
|
+
// This rail's obligations are RuleEffect objects (authority-types.ts) — a richer, INTERNAL
|
|
650
|
+
// shape ({ effect_type, value, provenance: { rule_id, rule_name } }), NOT the same shape the
|
|
651
|
+
// Exchange rail already returns ({ kind, rule_id, rule_name }). Mapped explicitly here rather
|
|
652
|
+
// than passed through raw — the two rails' server-side representations genuinely differ, and
|
|
653
|
+
// assuming they matched would have been the actual bug.
|
|
654
|
+
...Array.isArray(raw.obligations) && raw.obligations.length > 0 ? { obligations: raw.obligations.map((o) => ({
|
|
655
|
+
kind: o.kind ?? o.value ?? "obligation",
|
|
656
|
+
rule_id: o.rule_id ?? o.provenance?.rule_id ?? null,
|
|
657
|
+
rule_name: o.rule_name ?? o.provenance?.rule_name ?? null,
|
|
658
|
+
...o.reason ? { reason: o.reason } : {}
|
|
659
|
+
})) } : {}
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
async function canViaChain(artifact, keyCerts, rootPublicKeyPem, facts, action, opts) {
|
|
663
|
+
const base = (opts?.baseUrl ?? DEFAULT_EXCHANGE_BASE).replace(/\/$/, "");
|
|
664
|
+
const url = `${base}/api/v1/chain-of-trust/verify`;
|
|
665
|
+
let res;
|
|
666
|
+
try {
|
|
667
|
+
res = await fetch(url, {
|
|
668
|
+
method: "POST",
|
|
669
|
+
headers: { "Content-Type": "application/json" },
|
|
670
|
+
body: JSON.stringify({ version: CHAIN_PROTOCOL_VERSION, artifact, key_certs: keyCerts, root_public_key_pem: rootPublicKeyPem, facts, action }),
|
|
671
|
+
signal: opts?.signal
|
|
672
|
+
});
|
|
673
|
+
} catch (err) {
|
|
674
|
+
if (err?.name === "AbortError") throw new NomosNetworkError("Request aborted");
|
|
675
|
+
throw new NomosNetworkError(err?.message ?? "Network error");
|
|
676
|
+
}
|
|
677
|
+
const requestId = res.headers.get("x-request-id") ?? "";
|
|
678
|
+
const data = await res.json().catch(() => null);
|
|
679
|
+
if (data?.decision === "AUTHORIZED" || data?.decision === "DENIED" || data?.decision === "ESCALATED") {
|
|
680
|
+
return {
|
|
681
|
+
allowed: data.decision === "AUTHORIZED",
|
|
682
|
+
verdict: data.decision,
|
|
683
|
+
reason: data.reason ?? "",
|
|
684
|
+
rule: data.rule ?? null,
|
|
685
|
+
authority: { id: "presented-artifact", title: "", standing: "" },
|
|
686
|
+
// Read directly off the artifact the caller already has — no server round-trip needed for
|
|
687
|
+
// data the caller is already holding.
|
|
688
|
+
...artifact?.meta?.version ? { version: artifact.meta.version } : {},
|
|
689
|
+
missing_inputs: data.missing_inputs ?? [],
|
|
690
|
+
...Array.isArray(data.obligations) && data.obligations.length > 0 ? { obligations: data.obligations } : {}
|
|
691
|
+
// Deliberately no query_id/url/audit — this evaluation is stateless by design (the whole
|
|
692
|
+
// point is answering without NOMOS needing to have seen this artifact before); there is no
|
|
693
|
+
// permanent transcript to point to, and faking one would misrepresent what just happened.
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
const message = data?.detail ?? `Chain verification failed (HTTP ${res.status})`;
|
|
697
|
+
if (data?.decision === "ISSUER_NOT_RECOGNIZED" || data?.decision === "KEY_REVOKED" || data?.decision === "SEAL_INVALID" || data?.decision === "ALLOWED") {
|
|
698
|
+
throw new NomosIssuerNotTrustedError(message, data.decision, requestId);
|
|
699
|
+
}
|
|
700
|
+
if (data?.decision === "MALFORMED") throw new NomosValidationError(message, data, requestId);
|
|
701
|
+
mapHttpError(res.status, data, requestId);
|
|
702
|
+
}
|
|
703
|
+
async function can(params, opts) {
|
|
704
|
+
if (params.artifact !== void 0) {
|
|
705
|
+
if (!params.key_certs || !params.root_public_key_pem) {
|
|
706
|
+
throw new Error("can(): `artifact` requires `key_certs` and `root_public_key_pem` alongside it.");
|
|
707
|
+
}
|
|
708
|
+
const { facts: facts2, action: action2 } = splitFacts(params);
|
|
709
|
+
return canViaChain(params.artifact, params.key_certs, params.root_public_key_pem, facts2, action2, opts);
|
|
710
|
+
}
|
|
711
|
+
if (params.artifact_id) {
|
|
712
|
+
throw new Error("can(): `artifact_id` requires an API key \u2014 use `client.can(...)` on an authenticated Nomos instance, not the free `can()` export.");
|
|
713
|
+
}
|
|
714
|
+
if (!params.authority || typeof params.authority !== "string") {
|
|
715
|
+
throw new Error("can(): `authority` (an Exchange artifact id or slug), `artifact_id` (via client.can()), or `artifact` (chain-of-trust) is required.");
|
|
716
|
+
}
|
|
717
|
+
const { facts, action } = splitFacts(params);
|
|
718
|
+
return canViaExchange(params.authority, facts, action, opts);
|
|
719
|
+
}
|
|
720
|
+
async function canAuthenticated(http, params, opts) {
|
|
721
|
+
void opts;
|
|
722
|
+
const { facts, action } = splitFacts(params);
|
|
723
|
+
if (params.artifact !== void 0) {
|
|
724
|
+
if (!params.key_certs || !params.root_public_key_pem) {
|
|
725
|
+
throw new Error("can(): `artifact` requires `key_certs` and `root_public_key_pem` alongside it.");
|
|
726
|
+
}
|
|
727
|
+
return canViaChain(params.artifact, params.key_certs, params.root_public_key_pem, facts, action, opts);
|
|
728
|
+
}
|
|
729
|
+
if (params.artifact_id) return canViaArtifact(http, params.artifact_id, facts, action);
|
|
730
|
+
if (params.authority) return canViaExchangeAuthenticated(http, params.authority, facts, action);
|
|
731
|
+
throw new Error("can(): `authority` (a public Exchange artifact), `artifact_id` (your own artifact), or `artifact` (chain-of-trust) is required.");
|
|
732
|
+
}
|
|
733
|
+
var nomos = { can };
|
|
734
|
+
|
|
529
735
|
// src/nomos.ts
|
|
530
736
|
var DEFAULT_BASE_URL = "https://nomos.ai";
|
|
531
737
|
var DEFAULT_MAX_RETRIES = 3;
|
|
@@ -541,55 +747,69 @@ var Nomos = class {
|
|
|
541
747
|
);
|
|
542
748
|
}
|
|
543
749
|
this.mode = apiKey.startsWith("nms_test_") ? "test" : "live";
|
|
544
|
-
|
|
750
|
+
this.http = new HttpClient({
|
|
545
751
|
apiKey,
|
|
546
752
|
baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""),
|
|
547
753
|
maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,
|
|
548
754
|
timeout: config.timeout ?? DEFAULT_TIMEOUT
|
|
549
755
|
});
|
|
550
|
-
this.decisions = new Decisions(http);
|
|
551
|
-
this.artifacts = new Artifacts(http);
|
|
552
|
-
this.governance = new Governance(http);
|
|
756
|
+
this.decisions = new Decisions(this.http);
|
|
757
|
+
this.artifacts = new Artifacts(this.http);
|
|
758
|
+
this.governance = new Governance(this.http);
|
|
553
759
|
this.webhooks = new Webhooks();
|
|
554
760
|
}
|
|
761
|
+
/**
|
|
762
|
+
* "Can I do this?" — the one verb, now covering your own artifacts too. Pass `authority` for a
|
|
763
|
+
* public Exchange artifact, or `artifact_id` for your own (Studio or the Exchange) — same
|
|
764
|
+
* return shape either way, so calling code never needs to know which rail answered.
|
|
765
|
+
*
|
|
766
|
+
* @example
|
|
767
|
+
* const client = new Nomos('nms_live_...');
|
|
768
|
+
* const verdict = await client.can({ artifact_id: 'loan_approval_v1', credit_score: 720 });
|
|
769
|
+
*/
|
|
770
|
+
async can(params, opts) {
|
|
771
|
+
return canAuthenticated(this.http, params, opts);
|
|
772
|
+
}
|
|
555
773
|
};
|
|
556
774
|
|
|
557
|
-
// src/
|
|
558
|
-
var
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
if (!
|
|
562
|
-
throw new Error("
|
|
775
|
+
// src/verify-chain.ts
|
|
776
|
+
var CHAIN_PROTOCOL_VERSION2 = "1";
|
|
777
|
+
var DEFAULT_BASE = "https://www.nomosprotocol.com";
|
|
778
|
+
async function verifyChain(params, opts) {
|
|
779
|
+
if (!params.root_public_key_pem) {
|
|
780
|
+
throw new Error("verifyChain(): `root_public_key_pem` is required \u2014 there is no default root.");
|
|
563
781
|
}
|
|
564
|
-
const
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
782
|
+
const base = (opts?.baseUrl ?? DEFAULT_BASE).replace(/\/$/, "");
|
|
783
|
+
const url = `${base}/api/v1/chain-of-trust/verify`;
|
|
784
|
+
let res;
|
|
785
|
+
try {
|
|
786
|
+
res = await fetch(url, {
|
|
787
|
+
method: "POST",
|
|
788
|
+
headers: { "Content-Type": "application/json" },
|
|
789
|
+
body: JSON.stringify({
|
|
790
|
+
version: CHAIN_PROTOCOL_VERSION2,
|
|
791
|
+
artifact: params.artifact,
|
|
792
|
+
key_certs: params.key_certs,
|
|
793
|
+
root_public_key_pem: params.root_public_key_pem
|
|
794
|
+
}),
|
|
795
|
+
signal: opts?.signal
|
|
796
|
+
});
|
|
797
|
+
} catch (err) {
|
|
798
|
+
if (err?.name === "AbortError") throw new NomosNetworkError("Request aborted");
|
|
799
|
+
throw new NomosNetworkError(err?.message ?? "Network error");
|
|
800
|
+
}
|
|
801
|
+
const requestId = res.headers.get("x-request-id") ?? "";
|
|
573
802
|
const data = await res.json().catch(() => null);
|
|
574
|
-
if (
|
|
575
|
-
|
|
803
|
+
if (data && typeof data.decision === "string") {
|
|
804
|
+
return data;
|
|
576
805
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
url: data.url,
|
|
584
|
-
authority: {
|
|
585
|
-
id: data.artifact?.id ?? authority,
|
|
586
|
-
title: data.artifact?.title ?? "",
|
|
587
|
-
standing: data.artifact?.standing ?? ""
|
|
588
|
-
},
|
|
589
|
-
missing_inputs: data.missing_inputs ?? []
|
|
590
|
-
};
|
|
806
|
+
const message = data?.error ?? `Chain verification request failed (HTTP ${res.status})`;
|
|
807
|
+
if (res.status === 429) {
|
|
808
|
+
throw new NomosRateLimitError(message, res.headers.get("retry-after") ? parseInt(res.headers.get("retry-after"), 10) : void 0, requestId);
|
|
809
|
+
}
|
|
810
|
+
if (res.status === 400) throw new NomosValidationError(message, data?.details, requestId);
|
|
811
|
+
throw new NomosAPIError(message, res.status, requestId);
|
|
591
812
|
}
|
|
592
|
-
var nomos = { can };
|
|
593
813
|
// Annotate the CommonJS export names for ESM import in node:
|
|
594
814
|
0 && (module.exports = {
|
|
595
815
|
Nomos,
|
|
@@ -597,12 +817,15 @@ var nomos = { can };
|
|
|
597
817
|
NomosAuthenticationError,
|
|
598
818
|
NomosAuthorizationError,
|
|
599
819
|
NomosError,
|
|
820
|
+
NomosIssuerNotTrustedError,
|
|
600
821
|
NomosNetworkError,
|
|
601
822
|
NomosNotFoundError,
|
|
823
|
+
NomosPaymentRequiredError,
|
|
602
824
|
NomosRateLimitError,
|
|
603
825
|
NomosValidationError,
|
|
604
826
|
NomosWebhookSignatureError,
|
|
605
827
|
can,
|
|
606
|
-
nomos
|
|
828
|
+
nomos,
|
|
829
|
+
verifyChain
|
|
607
830
|
});
|
|
608
831
|
//# sourceMappingURL=index.cjs.map
|