@nomosprotocol/sdk 1.2.1 → 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/dist/index.cjs +250 -53
- 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 +245 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -43,9 +43,35 @@ interface DetectContradictionsParams {
|
|
|
43
43
|
}
|
|
44
44
|
type Verdict = 'approved' | 'rejected' | 'escalated';
|
|
45
45
|
type CanVerdict = 'AUTHORIZED' | 'DENIED' | 'ESCALATED';
|
|
46
|
+
/** Structured form of "who stands behind this artifact" — role, statement, and when, not just
|
|
47
|
+
* a name buried in `authority.standing`'s free text. Present only when a live (unrevoked,
|
|
48
|
+
* seal-bound) attestation exists on the exact sealed version that answered. Exchange rail only —
|
|
49
|
+
* the private-artifact and chain-of-trust rails have no equivalent concept today. */
|
|
50
|
+
interface AttestationInfo {
|
|
51
|
+
attester_name: string;
|
|
52
|
+
attester_org_id: string;
|
|
53
|
+
role: string;
|
|
54
|
+
statement: string;
|
|
55
|
+
attested_at: string;
|
|
56
|
+
}
|
|
46
57
|
interface CanParams {
|
|
47
|
-
/** Exchange artifact's standard name — slug (optionally ".nomos"-suffixed) or raw id,
|
|
48
|
-
|
|
58
|
+
/** A public Exchange artifact's standard name — slug (optionally ".nomos"-suffixed) or raw id,
|
|
59
|
+
* e.g. "eu-ai-act.nomos". Keyless. Mutually exclusive with `artifact_id`. */
|
|
60
|
+
authority?: string;
|
|
61
|
+
/** Your own artifact's id (from Studio or the Exchange). Requires an API key — only valid via
|
|
62
|
+
* `client.can()` on an authenticated `Nomos` instance, not the free `can()` export. Mutually
|
|
63
|
+
* exclusive with `authority`. */
|
|
64
|
+
artifact_id?: string;
|
|
65
|
+
/** Chain-of-trust rail (PROTOTYPE, not a numbered spec): a self-contained sealed artifact you
|
|
66
|
+
* received directly — from an agent, another system, anywhere — that NOMOS has never seen or
|
|
67
|
+
* registered. Requires `key_certs` and `root_public_key_pem` alongside it. Keyless, works on
|
|
68
|
+
* both `nomos.can()` and `client.can()`. */
|
|
69
|
+
artifact?: unknown;
|
|
70
|
+
/** The key certificates presented alongside `artifact` — order never affects the result. */
|
|
71
|
+
key_certs?: KeyCertificate[];
|
|
72
|
+
/** The root public key (PEM) YOU have independently decided to trust. There is deliberately no
|
|
73
|
+
* default — see the chain-of-trust design note for why. Required alongside `artifact`. */
|
|
74
|
+
root_public_key_pem?: string;
|
|
49
75
|
/** Optional human-readable label for what's being asked (recorded in the transcript) */
|
|
50
76
|
action?: string;
|
|
51
77
|
/** The facts to evaluate. Either pass this explicitly, or spread the facts flat alongside
|
|
@@ -63,24 +89,98 @@ interface CanOptions {
|
|
|
63
89
|
interface CanResult {
|
|
64
90
|
/** True only for an AUTHORIZED verdict. DENIED and ESCALATED are both `false`. */
|
|
65
91
|
allowed: boolean;
|
|
66
|
-
/** The authority's own verdict, verbatim
|
|
92
|
+
/** The authority's own verdict, verbatim, in ONE consistent vocabulary regardless of which
|
|
93
|
+
* rail answered it — the public Exchange or your own authenticated artifact. */
|
|
67
94
|
verdict: CanVerdict;
|
|
68
95
|
/** Human-readable explanation of the verdict. */
|
|
69
96
|
reason: string;
|
|
70
97
|
/** The rule id that decided it, if any. */
|
|
71
98
|
rule: string | null;
|
|
72
|
-
/** Permanent, addressable transcript id — open it any time.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
99
|
+
/** Permanent, addressable transcript id — open it any time. Present only when the Exchange rail
|
|
100
|
+
* answered (it mints a permanent public transcript for every query). Absent, not faked, when
|
|
101
|
+
* your own authenticated artifact answered instead — see `audit` for that rail's provenance. */
|
|
102
|
+
query_id?: string;
|
|
103
|
+
/** Relative URL of the transcript. Same availability as `query_id`. */
|
|
104
|
+
url?: string;
|
|
76
105
|
/** Which authority answered, and its standing. */
|
|
77
106
|
authority: {
|
|
78
107
|
id: string;
|
|
79
108
|
title: string;
|
|
80
109
|
standing: string;
|
|
110
|
+
attestation?: AttestationInfo;
|
|
81
111
|
};
|
|
112
|
+
/** The authority's own declared version — its sealed meta.version, not administrative
|
|
113
|
+
* metadata that can drift from what's actually embedded in the artifact. Present whenever the
|
|
114
|
+
* answering artifact declares one; omitted (not a guess) when it doesn't. */
|
|
115
|
+
version?: string;
|
|
82
116
|
/** On ESCALATED: the facts the authority still needs to reach a verdict. */
|
|
83
117
|
missing_inputs: string[];
|
|
118
|
+
/** Notify/log/audit/flag-style duties that fired alongside the verdict — e.g. "must inform the
|
|
119
|
+
* affected person" — distinct from the verdict itself: an obligation can accompany an
|
|
120
|
+
* AUTHORIZED result, it doesn't only apply to denials. Present on both rails; omitted (not an
|
|
121
|
+
* empty array) when none fired, since "no obligations" and "we didn't check" should stay
|
|
122
|
+
* distinguishable. */
|
|
123
|
+
obligations?: Array<{
|
|
124
|
+
kind: string;
|
|
125
|
+
rule_id: string | null;
|
|
126
|
+
rule_name: string | null;
|
|
127
|
+
reason?: string;
|
|
128
|
+
}>;
|
|
129
|
+
/** RECOMMENDED maximum seconds to hold this verdict before re-querying or re-checking the
|
|
130
|
+
* issuer's revocation list (NOMOS-SPEC-006 §6.2). Advisory; absent when the artifact isn't
|
|
131
|
+
* structurally revocable on this deployment — treat absence as "unknown," not "safe forever." */
|
|
132
|
+
max_age?: number;
|
|
133
|
+
/** Present only when your own authenticated artifact answered — that rail's own provenance
|
|
134
|
+
* (a hash you can store for compliance), not a permanent public transcript like `query_id`. */
|
|
135
|
+
audit?: {
|
|
136
|
+
hash: string;
|
|
137
|
+
timestamp: string;
|
|
138
|
+
};
|
|
139
|
+
/** NOMOS-SPEC-006 — true only when the issuer has revoked this exact sealed version; forces
|
|
140
|
+
* `verdict` to DENIED regardless of what the artifact's own rules would otherwise have said.
|
|
141
|
+
* Omitted (not `false`) when revocation doesn't structurally apply on this deployment — "no
|
|
142
|
+
* revocation" and "couldn't check" must never look identical. */
|
|
143
|
+
revoked?: boolean;
|
|
144
|
+
/** Present only alongside `revoked: true` — the issuer's stated reason. */
|
|
145
|
+
revocation_reason?: string;
|
|
146
|
+
}
|
|
147
|
+
type ChainVerdictDecision = 'ALLOWED' | 'ISSUER_NOT_RECOGNIZED' | 'KEY_REVOKED' | 'SEAL_INVALID' | 'MALFORMED';
|
|
148
|
+
interface KeyCertificate {
|
|
149
|
+
parent_kid: string;
|
|
150
|
+
child_kid: string;
|
|
151
|
+
child_public_key_pem: string;
|
|
152
|
+
scope?: string;
|
|
153
|
+
issued_at: string;
|
|
154
|
+
expires_at: string;
|
|
155
|
+
algorithm: 'Ed25519';
|
|
156
|
+
signature: string;
|
|
157
|
+
}
|
|
158
|
+
interface VerifyChainParams {
|
|
159
|
+
/** The sealed .nomos artifact being presented. */
|
|
160
|
+
artifact: unknown;
|
|
161
|
+
/** The set of key certificates presented alongside it — order never affects the result. */
|
|
162
|
+
key_certs: KeyCertificate[];
|
|
163
|
+
/** The root public key (PEM) the CALLER has independently decided to trust. There is
|
|
164
|
+
* deliberately no default — see the chain-of-trust design note for why. */
|
|
165
|
+
root_public_key_pem: string;
|
|
166
|
+
}
|
|
167
|
+
interface VerifyChainOptions {
|
|
168
|
+
/** Override the API host (defaults to the public NOMOS platform). */
|
|
169
|
+
baseUrl?: string;
|
|
170
|
+
signal?: AbortSignal;
|
|
171
|
+
}
|
|
172
|
+
interface VerifyChainResult {
|
|
173
|
+
decision: ChainVerdictDecision;
|
|
174
|
+
/** Present only when decision === 'ALLOWED'. */
|
|
175
|
+
leaf_kid?: string;
|
|
176
|
+
/** Present only when decision === 'ALLOWED' — the resolved kid path from root to leaf. */
|
|
177
|
+
path?: string[];
|
|
178
|
+
/** Present only when decision === 'ISSUER_NOT_RECOGNIZED'. */
|
|
179
|
+
reason?: string;
|
|
180
|
+
/** Present only when decision === 'KEY_REVOKED'. */
|
|
181
|
+
revoked_kid?: string;
|
|
182
|
+
/** Human-readable detail for any non-ALLOWED decision. */
|
|
183
|
+
detail?: string;
|
|
84
184
|
}
|
|
85
185
|
interface VerifyDecisionResult {
|
|
86
186
|
/** Unique request ID — include in support tickets */
|
|
@@ -239,7 +339,7 @@ interface NomosRawResponse {
|
|
|
239
339
|
type WithLastResponse<T> = T & {
|
|
240
340
|
lastResponse: NomosRawResponse;
|
|
241
341
|
};
|
|
242
|
-
type NomosWebhookEventType = 'artifact.sealed' | 'artifact.published' | 'decision.verified' | 'decision.escalated' | 'exchange.purchased' | 'exchange.reviewed' | 'drift.detected';
|
|
342
|
+
type NomosWebhookEventType = 'artifact.sealed' | 'artifact.published' | 'artifact.revoked' | 'decision.verified' | 'decision.escalated' | 'exchange.purchased' | 'exchange.reviewed' | 'drift.detected';
|
|
243
343
|
interface NomosWebhookEvent {
|
|
244
344
|
id: string;
|
|
245
345
|
type: NomosWebhookEventType;
|
|
@@ -409,7 +509,7 @@ declare class Webhooks {
|
|
|
409
509
|
verifySignature(payload: string | Uint8Array, signature: string, secret: string, toleranceSeconds?: number): Promise<boolean>;
|
|
410
510
|
}
|
|
411
511
|
|
|
412
|
-
type NomosErrorCode = 'authentication_error' | 'authorization_error' | 'rate_limit_error' | 'validation_error' | 'not_found' | 'api_error' | 'network_error' | 'webhook_signature_error';
|
|
512
|
+
type NomosErrorCode = 'authentication_error' | 'authorization_error' | 'rate_limit_error' | 'validation_error' | 'not_found' | 'api_error' | 'network_error' | 'webhook_signature_error' | 'payment_required' | 'issuer_not_trusted';
|
|
413
513
|
declare class NomosError extends Error {
|
|
414
514
|
readonly code: NomosErrorCode;
|
|
415
515
|
readonly status?: number;
|
|
@@ -442,6 +542,27 @@ declare class NomosNetworkError extends NomosError {
|
|
|
442
542
|
declare class NomosWebhookSignatureError extends NomosError {
|
|
443
543
|
constructor(message: string);
|
|
444
544
|
}
|
|
545
|
+
/** can() asked about a paid authority the caller hasn't purchased or licensed. Distinct from a
|
|
546
|
+
* generic 403 on purpose: this isn't "you're not allowed," it's "here's exactly what unlocks
|
|
547
|
+
* it" — price and a URL to complete the purchase. NOMOS never auto-charges on your behalf;
|
|
548
|
+
* this is the seam where a caller decides to buy, not where a payment silently happens. */
|
|
549
|
+
declare class NomosPaymentRequiredError extends NomosError {
|
|
550
|
+
readonly priceUsd: number;
|
|
551
|
+
readonly purchaseUrl: string;
|
|
552
|
+
constructor(message: string, priceUsd: number, purchaseUrl: string, requestId?: string);
|
|
553
|
+
}
|
|
554
|
+
/** can()'s chain-of-trust rail couldn't establish that the presented artifact is trustworthy —
|
|
555
|
+
* an unrecognized issuer, a revoked key, a tampered seal, or a malformed presentation. This is
|
|
556
|
+
* deliberately NOT a DENIED verdict: "the rules say no" and "we never got far enough to ask the
|
|
557
|
+
* rules anything" are different claims, and collapsing them would tell the caller the wrong
|
|
558
|
+
* thing to do next (re-presenting a better chain can fix the first case; it can never fix a
|
|
559
|
+
* genuinely tampered artifact). `reason` is the underlying chain decision
|
|
560
|
+
* (ISSUER_NOT_RECOGNIZED / KEY_REVOKED / SEAL_INVALID / MALFORMED) for callers that need to
|
|
561
|
+
* distinguish them. */
|
|
562
|
+
declare class NomosIssuerNotTrustedError extends NomosError {
|
|
563
|
+
readonly reason: string;
|
|
564
|
+
constructor(message: string, reason: string, requestId?: string);
|
|
565
|
+
}
|
|
445
566
|
|
|
446
567
|
type errors_NomosAPIError = NomosAPIError;
|
|
447
568
|
declare const errors_NomosAPIError: typeof NomosAPIError;
|
|
@@ -452,10 +573,14 @@ declare const errors_NomosAuthorizationError: typeof NomosAuthorizationError;
|
|
|
452
573
|
type errors_NomosError = NomosError;
|
|
453
574
|
declare const errors_NomosError: typeof NomosError;
|
|
454
575
|
type errors_NomosErrorCode = NomosErrorCode;
|
|
576
|
+
type errors_NomosIssuerNotTrustedError = NomosIssuerNotTrustedError;
|
|
577
|
+
declare const errors_NomosIssuerNotTrustedError: typeof NomosIssuerNotTrustedError;
|
|
455
578
|
type errors_NomosNetworkError = NomosNetworkError;
|
|
456
579
|
declare const errors_NomosNetworkError: typeof NomosNetworkError;
|
|
457
580
|
type errors_NomosNotFoundError = NomosNotFoundError;
|
|
458
581
|
declare const errors_NomosNotFoundError: typeof NomosNotFoundError;
|
|
582
|
+
type errors_NomosPaymentRequiredError = NomosPaymentRequiredError;
|
|
583
|
+
declare const errors_NomosPaymentRequiredError: typeof NomosPaymentRequiredError;
|
|
459
584
|
type errors_NomosRateLimitError = NomosRateLimitError;
|
|
460
585
|
declare const errors_NomosRateLimitError: typeof NomosRateLimitError;
|
|
461
586
|
type errors_NomosValidationError = NomosValidationError;
|
|
@@ -463,7 +588,7 @@ declare const errors_NomosValidationError: typeof NomosValidationError;
|
|
|
463
588
|
type errors_NomosWebhookSignatureError = NomosWebhookSignatureError;
|
|
464
589
|
declare const errors_NomosWebhookSignatureError: typeof NomosWebhookSignatureError;
|
|
465
590
|
declare namespace errors {
|
|
466
|
-
export { errors_NomosAPIError as NomosAPIError, errors_NomosAuthenticationError as NomosAuthenticationError, errors_NomosAuthorizationError as NomosAuthorizationError, errors_NomosError as NomosError, type errors_NomosErrorCode as NomosErrorCode, errors_NomosNetworkError as NomosNetworkError, errors_NomosNotFoundError as NomosNotFoundError, errors_NomosRateLimitError as NomosRateLimitError, errors_NomosValidationError as NomosValidationError, errors_NomosWebhookSignatureError as NomosWebhookSignatureError };
|
|
591
|
+
export { errors_NomosAPIError as NomosAPIError, errors_NomosAuthenticationError as NomosAuthenticationError, errors_NomosAuthorizationError as NomosAuthorizationError, errors_NomosError as NomosError, type errors_NomosErrorCode as NomosErrorCode, errors_NomosIssuerNotTrustedError as NomosIssuerNotTrustedError, errors_NomosNetworkError as NomosNetworkError, errors_NomosNotFoundError as NomosNotFoundError, errors_NomosPaymentRequiredError as NomosPaymentRequiredError, errors_NomosRateLimitError as NomosRateLimitError, errors_NomosValidationError as NomosValidationError, errors_NomosWebhookSignatureError as NomosWebhookSignatureError };
|
|
467
592
|
}
|
|
468
593
|
|
|
469
594
|
declare class Nomos {
|
|
@@ -474,16 +599,50 @@ declare class Nomos {
|
|
|
474
599
|
/** Whether this instance is using a live or test API key. */
|
|
475
600
|
readonly mode: 'live' | 'test';
|
|
476
601
|
static readonly errors: typeof errors;
|
|
602
|
+
private readonly http;
|
|
477
603
|
constructor(apiKey: string, config?: NomosConfig);
|
|
604
|
+
/**
|
|
605
|
+
* "Can I do this?" — the one verb, now covering your own artifacts too. Pass `authority` for a
|
|
606
|
+
* public Exchange artifact, or `artifact_id` for your own (Studio or the Exchange) — same
|
|
607
|
+
* return shape either way, so calling code never needs to know which rail answered.
|
|
608
|
+
*
|
|
609
|
+
* @example
|
|
610
|
+
* const client = new Nomos('nms_live_...');
|
|
611
|
+
* const verdict = await client.can({ artifact_id: 'loan_approval_v1', credit_score: 720 });
|
|
612
|
+
*/
|
|
613
|
+
can(params: CanParams, opts?: CanOptions): Promise<CanResult>;
|
|
478
614
|
}
|
|
479
615
|
|
|
480
616
|
declare function can(params: CanParams, opts?: CanOptions): Promise<CanResult>;
|
|
481
617
|
/**
|
|
482
618
|
* Ready-to-use, keyless entry point matching the canonical `nomos.can(...)` form.
|
|
483
|
-
* For
|
|
619
|
+
* For paid artifacts or your own artifacts, use `client.can(...)` on an authenticated `Nomos`
|
|
620
|
+
* instance instead — same function name, same verdict shape, the only difference is which rail
|
|
621
|
+
* answers and what it can unlock.
|
|
484
622
|
*/
|
|
485
623
|
declare const nomos: {
|
|
486
624
|
can: typeof can;
|
|
487
625
|
};
|
|
488
626
|
|
|
489
|
-
|
|
627
|
+
/**
|
|
628
|
+
* Chain-of-trust verification (PROTOTYPE — not a numbered spec). Checks whether a presented
|
|
629
|
+
* artifact's signing key resolves, through the presented key certificates, back to a root you
|
|
630
|
+
* have independently decided to trust — entirely server-side against nomos-chain.ts's pure
|
|
631
|
+
* verifier, with no account or API key required (keyless, matching `nomos.can()`'s precedent).
|
|
632
|
+
*
|
|
633
|
+
* There is no default root anywhere in this call — `root_public_key_pem` is required. That's
|
|
634
|
+
* deliberate: it keeps the trust decision with the caller, not with this SDK or the platform.
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* import { verifyChain } from '@nomosprotocol/sdk';
|
|
638
|
+
*
|
|
639
|
+
* const result = await verifyChain({
|
|
640
|
+
* artifact: sealedArtifact,
|
|
641
|
+
* key_certs: [rootToIntermediate, intermediateToLeaf],
|
|
642
|
+
* root_public_key_pem: myPinnedRootPem,
|
|
643
|
+
* });
|
|
644
|
+
* if (result.decision === 'ALLOWED') { ... }
|
|
645
|
+
*/
|
|
646
|
+
declare function verifyChain(params: VerifyChainParams, opts?: VerifyChainOptions): Promise<VerifyChainResult>;
|
|
647
|
+
|
|
648
|
+
export { type Artifact, type ArtifactList, type ArtifactSchema, type ArtifactSchemaField, type AttestationInfo, type CanOptions, type CanParams, type CanResult, type CanVerdict, type ChainVerdictDecision, type Contradiction, type DetectContradictionsParams, type DetectContradictionsResult, type GenerateGovernanceParams, type GenerateGovernanceResult, type KeyCertificate, type ListArtifactsParams, Nomos, NomosAPIError, NomosAuthenticationError, NomosAuthorizationError, type NomosConfig, NomosError, type NomosErrorCode, NomosIssuerNotTrustedError, NomosNetworkError, NomosNotFoundError, NomosPaymentRequiredError, NomosRateLimitError, type NomosRawResponse, NomosValidationError, type NomosWebhookEvent, type NomosWebhookEventType, NomosWebhookSignatureError, type RequestOptions, type Verdict, type VerifyChainOptions, type VerifyChainParams, type VerifyChainResult, type VerifyDecisionParams, type VerifyDecisionResult, type WithLastResponse, can, nomos, verifyChain };
|
package/dist/index.d.ts
CHANGED
|
@@ -43,9 +43,35 @@ interface DetectContradictionsParams {
|
|
|
43
43
|
}
|
|
44
44
|
type Verdict = 'approved' | 'rejected' | 'escalated';
|
|
45
45
|
type CanVerdict = 'AUTHORIZED' | 'DENIED' | 'ESCALATED';
|
|
46
|
+
/** Structured form of "who stands behind this artifact" — role, statement, and when, not just
|
|
47
|
+
* a name buried in `authority.standing`'s free text. Present only when a live (unrevoked,
|
|
48
|
+
* seal-bound) attestation exists on the exact sealed version that answered. Exchange rail only —
|
|
49
|
+
* the private-artifact and chain-of-trust rails have no equivalent concept today. */
|
|
50
|
+
interface AttestationInfo {
|
|
51
|
+
attester_name: string;
|
|
52
|
+
attester_org_id: string;
|
|
53
|
+
role: string;
|
|
54
|
+
statement: string;
|
|
55
|
+
attested_at: string;
|
|
56
|
+
}
|
|
46
57
|
interface CanParams {
|
|
47
|
-
/** Exchange artifact's standard name — slug (optionally ".nomos"-suffixed) or raw id,
|
|
48
|
-
|
|
58
|
+
/** A public Exchange artifact's standard name — slug (optionally ".nomos"-suffixed) or raw id,
|
|
59
|
+
* e.g. "eu-ai-act.nomos". Keyless. Mutually exclusive with `artifact_id`. */
|
|
60
|
+
authority?: string;
|
|
61
|
+
/** Your own artifact's id (from Studio or the Exchange). Requires an API key — only valid via
|
|
62
|
+
* `client.can()` on an authenticated `Nomos` instance, not the free `can()` export. Mutually
|
|
63
|
+
* exclusive with `authority`. */
|
|
64
|
+
artifact_id?: string;
|
|
65
|
+
/** Chain-of-trust rail (PROTOTYPE, not a numbered spec): a self-contained sealed artifact you
|
|
66
|
+
* received directly — from an agent, another system, anywhere — that NOMOS has never seen or
|
|
67
|
+
* registered. Requires `key_certs` and `root_public_key_pem` alongside it. Keyless, works on
|
|
68
|
+
* both `nomos.can()` and `client.can()`. */
|
|
69
|
+
artifact?: unknown;
|
|
70
|
+
/** The key certificates presented alongside `artifact` — order never affects the result. */
|
|
71
|
+
key_certs?: KeyCertificate[];
|
|
72
|
+
/** The root public key (PEM) YOU have independently decided to trust. There is deliberately no
|
|
73
|
+
* default — see the chain-of-trust design note for why. Required alongside `artifact`. */
|
|
74
|
+
root_public_key_pem?: string;
|
|
49
75
|
/** Optional human-readable label for what's being asked (recorded in the transcript) */
|
|
50
76
|
action?: string;
|
|
51
77
|
/** The facts to evaluate. Either pass this explicitly, or spread the facts flat alongside
|
|
@@ -63,24 +89,98 @@ interface CanOptions {
|
|
|
63
89
|
interface CanResult {
|
|
64
90
|
/** True only for an AUTHORIZED verdict. DENIED and ESCALATED are both `false`. */
|
|
65
91
|
allowed: boolean;
|
|
66
|
-
/** The authority's own verdict, verbatim
|
|
92
|
+
/** The authority's own verdict, verbatim, in ONE consistent vocabulary regardless of which
|
|
93
|
+
* rail answered it — the public Exchange or your own authenticated artifact. */
|
|
67
94
|
verdict: CanVerdict;
|
|
68
95
|
/** Human-readable explanation of the verdict. */
|
|
69
96
|
reason: string;
|
|
70
97
|
/** The rule id that decided it, if any. */
|
|
71
98
|
rule: string | null;
|
|
72
|
-
/** Permanent, addressable transcript id — open it any time.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
99
|
+
/** Permanent, addressable transcript id — open it any time. Present only when the Exchange rail
|
|
100
|
+
* answered (it mints a permanent public transcript for every query). Absent, not faked, when
|
|
101
|
+
* your own authenticated artifact answered instead — see `audit` for that rail's provenance. */
|
|
102
|
+
query_id?: string;
|
|
103
|
+
/** Relative URL of the transcript. Same availability as `query_id`. */
|
|
104
|
+
url?: string;
|
|
76
105
|
/** Which authority answered, and its standing. */
|
|
77
106
|
authority: {
|
|
78
107
|
id: string;
|
|
79
108
|
title: string;
|
|
80
109
|
standing: string;
|
|
110
|
+
attestation?: AttestationInfo;
|
|
81
111
|
};
|
|
112
|
+
/** The authority's own declared version — its sealed meta.version, not administrative
|
|
113
|
+
* metadata that can drift from what's actually embedded in the artifact. Present whenever the
|
|
114
|
+
* answering artifact declares one; omitted (not a guess) when it doesn't. */
|
|
115
|
+
version?: string;
|
|
82
116
|
/** On ESCALATED: the facts the authority still needs to reach a verdict. */
|
|
83
117
|
missing_inputs: string[];
|
|
118
|
+
/** Notify/log/audit/flag-style duties that fired alongside the verdict — e.g. "must inform the
|
|
119
|
+
* affected person" — distinct from the verdict itself: an obligation can accompany an
|
|
120
|
+
* AUTHORIZED result, it doesn't only apply to denials. Present on both rails; omitted (not an
|
|
121
|
+
* empty array) when none fired, since "no obligations" and "we didn't check" should stay
|
|
122
|
+
* distinguishable. */
|
|
123
|
+
obligations?: Array<{
|
|
124
|
+
kind: string;
|
|
125
|
+
rule_id: string | null;
|
|
126
|
+
rule_name: string | null;
|
|
127
|
+
reason?: string;
|
|
128
|
+
}>;
|
|
129
|
+
/** RECOMMENDED maximum seconds to hold this verdict before re-querying or re-checking the
|
|
130
|
+
* issuer's revocation list (NOMOS-SPEC-006 §6.2). Advisory; absent when the artifact isn't
|
|
131
|
+
* structurally revocable on this deployment — treat absence as "unknown," not "safe forever." */
|
|
132
|
+
max_age?: number;
|
|
133
|
+
/** Present only when your own authenticated artifact answered — that rail's own provenance
|
|
134
|
+
* (a hash you can store for compliance), not a permanent public transcript like `query_id`. */
|
|
135
|
+
audit?: {
|
|
136
|
+
hash: string;
|
|
137
|
+
timestamp: string;
|
|
138
|
+
};
|
|
139
|
+
/** NOMOS-SPEC-006 — true only when the issuer has revoked this exact sealed version; forces
|
|
140
|
+
* `verdict` to DENIED regardless of what the artifact's own rules would otherwise have said.
|
|
141
|
+
* Omitted (not `false`) when revocation doesn't structurally apply on this deployment — "no
|
|
142
|
+
* revocation" and "couldn't check" must never look identical. */
|
|
143
|
+
revoked?: boolean;
|
|
144
|
+
/** Present only alongside `revoked: true` — the issuer's stated reason. */
|
|
145
|
+
revocation_reason?: string;
|
|
146
|
+
}
|
|
147
|
+
type ChainVerdictDecision = 'ALLOWED' | 'ISSUER_NOT_RECOGNIZED' | 'KEY_REVOKED' | 'SEAL_INVALID' | 'MALFORMED';
|
|
148
|
+
interface KeyCertificate {
|
|
149
|
+
parent_kid: string;
|
|
150
|
+
child_kid: string;
|
|
151
|
+
child_public_key_pem: string;
|
|
152
|
+
scope?: string;
|
|
153
|
+
issued_at: string;
|
|
154
|
+
expires_at: string;
|
|
155
|
+
algorithm: 'Ed25519';
|
|
156
|
+
signature: string;
|
|
157
|
+
}
|
|
158
|
+
interface VerifyChainParams {
|
|
159
|
+
/** The sealed .nomos artifact being presented. */
|
|
160
|
+
artifact: unknown;
|
|
161
|
+
/** The set of key certificates presented alongside it — order never affects the result. */
|
|
162
|
+
key_certs: KeyCertificate[];
|
|
163
|
+
/** The root public key (PEM) the CALLER has independently decided to trust. There is
|
|
164
|
+
* deliberately no default — see the chain-of-trust design note for why. */
|
|
165
|
+
root_public_key_pem: string;
|
|
166
|
+
}
|
|
167
|
+
interface VerifyChainOptions {
|
|
168
|
+
/** Override the API host (defaults to the public NOMOS platform). */
|
|
169
|
+
baseUrl?: string;
|
|
170
|
+
signal?: AbortSignal;
|
|
171
|
+
}
|
|
172
|
+
interface VerifyChainResult {
|
|
173
|
+
decision: ChainVerdictDecision;
|
|
174
|
+
/** Present only when decision === 'ALLOWED'. */
|
|
175
|
+
leaf_kid?: string;
|
|
176
|
+
/** Present only when decision === 'ALLOWED' — the resolved kid path from root to leaf. */
|
|
177
|
+
path?: string[];
|
|
178
|
+
/** Present only when decision === 'ISSUER_NOT_RECOGNIZED'. */
|
|
179
|
+
reason?: string;
|
|
180
|
+
/** Present only when decision === 'KEY_REVOKED'. */
|
|
181
|
+
revoked_kid?: string;
|
|
182
|
+
/** Human-readable detail for any non-ALLOWED decision. */
|
|
183
|
+
detail?: string;
|
|
84
184
|
}
|
|
85
185
|
interface VerifyDecisionResult {
|
|
86
186
|
/** Unique request ID — include in support tickets */
|
|
@@ -239,7 +339,7 @@ interface NomosRawResponse {
|
|
|
239
339
|
type WithLastResponse<T> = T & {
|
|
240
340
|
lastResponse: NomosRawResponse;
|
|
241
341
|
};
|
|
242
|
-
type NomosWebhookEventType = 'artifact.sealed' | 'artifact.published' | 'decision.verified' | 'decision.escalated' | 'exchange.purchased' | 'exchange.reviewed' | 'drift.detected';
|
|
342
|
+
type NomosWebhookEventType = 'artifact.sealed' | 'artifact.published' | 'artifact.revoked' | 'decision.verified' | 'decision.escalated' | 'exchange.purchased' | 'exchange.reviewed' | 'drift.detected';
|
|
243
343
|
interface NomosWebhookEvent {
|
|
244
344
|
id: string;
|
|
245
345
|
type: NomosWebhookEventType;
|
|
@@ -409,7 +509,7 @@ declare class Webhooks {
|
|
|
409
509
|
verifySignature(payload: string | Uint8Array, signature: string, secret: string, toleranceSeconds?: number): Promise<boolean>;
|
|
410
510
|
}
|
|
411
511
|
|
|
412
|
-
type NomosErrorCode = 'authentication_error' | 'authorization_error' | 'rate_limit_error' | 'validation_error' | 'not_found' | 'api_error' | 'network_error' | 'webhook_signature_error';
|
|
512
|
+
type NomosErrorCode = 'authentication_error' | 'authorization_error' | 'rate_limit_error' | 'validation_error' | 'not_found' | 'api_error' | 'network_error' | 'webhook_signature_error' | 'payment_required' | 'issuer_not_trusted';
|
|
413
513
|
declare class NomosError extends Error {
|
|
414
514
|
readonly code: NomosErrorCode;
|
|
415
515
|
readonly status?: number;
|
|
@@ -442,6 +542,27 @@ declare class NomosNetworkError extends NomosError {
|
|
|
442
542
|
declare class NomosWebhookSignatureError extends NomosError {
|
|
443
543
|
constructor(message: string);
|
|
444
544
|
}
|
|
545
|
+
/** can() asked about a paid authority the caller hasn't purchased or licensed. Distinct from a
|
|
546
|
+
* generic 403 on purpose: this isn't "you're not allowed," it's "here's exactly what unlocks
|
|
547
|
+
* it" — price and a URL to complete the purchase. NOMOS never auto-charges on your behalf;
|
|
548
|
+
* this is the seam where a caller decides to buy, not where a payment silently happens. */
|
|
549
|
+
declare class NomosPaymentRequiredError extends NomosError {
|
|
550
|
+
readonly priceUsd: number;
|
|
551
|
+
readonly purchaseUrl: string;
|
|
552
|
+
constructor(message: string, priceUsd: number, purchaseUrl: string, requestId?: string);
|
|
553
|
+
}
|
|
554
|
+
/** can()'s chain-of-trust rail couldn't establish that the presented artifact is trustworthy —
|
|
555
|
+
* an unrecognized issuer, a revoked key, a tampered seal, or a malformed presentation. This is
|
|
556
|
+
* deliberately NOT a DENIED verdict: "the rules say no" and "we never got far enough to ask the
|
|
557
|
+
* rules anything" are different claims, and collapsing them would tell the caller the wrong
|
|
558
|
+
* thing to do next (re-presenting a better chain can fix the first case; it can never fix a
|
|
559
|
+
* genuinely tampered artifact). `reason` is the underlying chain decision
|
|
560
|
+
* (ISSUER_NOT_RECOGNIZED / KEY_REVOKED / SEAL_INVALID / MALFORMED) for callers that need to
|
|
561
|
+
* distinguish them. */
|
|
562
|
+
declare class NomosIssuerNotTrustedError extends NomosError {
|
|
563
|
+
readonly reason: string;
|
|
564
|
+
constructor(message: string, reason: string, requestId?: string);
|
|
565
|
+
}
|
|
445
566
|
|
|
446
567
|
type errors_NomosAPIError = NomosAPIError;
|
|
447
568
|
declare const errors_NomosAPIError: typeof NomosAPIError;
|
|
@@ -452,10 +573,14 @@ declare const errors_NomosAuthorizationError: typeof NomosAuthorizationError;
|
|
|
452
573
|
type errors_NomosError = NomosError;
|
|
453
574
|
declare const errors_NomosError: typeof NomosError;
|
|
454
575
|
type errors_NomosErrorCode = NomosErrorCode;
|
|
576
|
+
type errors_NomosIssuerNotTrustedError = NomosIssuerNotTrustedError;
|
|
577
|
+
declare const errors_NomosIssuerNotTrustedError: typeof NomosIssuerNotTrustedError;
|
|
455
578
|
type errors_NomosNetworkError = NomosNetworkError;
|
|
456
579
|
declare const errors_NomosNetworkError: typeof NomosNetworkError;
|
|
457
580
|
type errors_NomosNotFoundError = NomosNotFoundError;
|
|
458
581
|
declare const errors_NomosNotFoundError: typeof NomosNotFoundError;
|
|
582
|
+
type errors_NomosPaymentRequiredError = NomosPaymentRequiredError;
|
|
583
|
+
declare const errors_NomosPaymentRequiredError: typeof NomosPaymentRequiredError;
|
|
459
584
|
type errors_NomosRateLimitError = NomosRateLimitError;
|
|
460
585
|
declare const errors_NomosRateLimitError: typeof NomosRateLimitError;
|
|
461
586
|
type errors_NomosValidationError = NomosValidationError;
|
|
@@ -463,7 +588,7 @@ declare const errors_NomosValidationError: typeof NomosValidationError;
|
|
|
463
588
|
type errors_NomosWebhookSignatureError = NomosWebhookSignatureError;
|
|
464
589
|
declare const errors_NomosWebhookSignatureError: typeof NomosWebhookSignatureError;
|
|
465
590
|
declare namespace errors {
|
|
466
|
-
export { errors_NomosAPIError as NomosAPIError, errors_NomosAuthenticationError as NomosAuthenticationError, errors_NomosAuthorizationError as NomosAuthorizationError, errors_NomosError as NomosError, type errors_NomosErrorCode as NomosErrorCode, errors_NomosNetworkError as NomosNetworkError, errors_NomosNotFoundError as NomosNotFoundError, errors_NomosRateLimitError as NomosRateLimitError, errors_NomosValidationError as NomosValidationError, errors_NomosWebhookSignatureError as NomosWebhookSignatureError };
|
|
591
|
+
export { errors_NomosAPIError as NomosAPIError, errors_NomosAuthenticationError as NomosAuthenticationError, errors_NomosAuthorizationError as NomosAuthorizationError, errors_NomosError as NomosError, type errors_NomosErrorCode as NomosErrorCode, errors_NomosIssuerNotTrustedError as NomosIssuerNotTrustedError, errors_NomosNetworkError as NomosNetworkError, errors_NomosNotFoundError as NomosNotFoundError, errors_NomosPaymentRequiredError as NomosPaymentRequiredError, errors_NomosRateLimitError as NomosRateLimitError, errors_NomosValidationError as NomosValidationError, errors_NomosWebhookSignatureError as NomosWebhookSignatureError };
|
|
467
592
|
}
|
|
468
593
|
|
|
469
594
|
declare class Nomos {
|
|
@@ -474,16 +599,50 @@ declare class Nomos {
|
|
|
474
599
|
/** Whether this instance is using a live or test API key. */
|
|
475
600
|
readonly mode: 'live' | 'test';
|
|
476
601
|
static readonly errors: typeof errors;
|
|
602
|
+
private readonly http;
|
|
477
603
|
constructor(apiKey: string, config?: NomosConfig);
|
|
604
|
+
/**
|
|
605
|
+
* "Can I do this?" — the one verb, now covering your own artifacts too. Pass `authority` for a
|
|
606
|
+
* public Exchange artifact, or `artifact_id` for your own (Studio or the Exchange) — same
|
|
607
|
+
* return shape either way, so calling code never needs to know which rail answered.
|
|
608
|
+
*
|
|
609
|
+
* @example
|
|
610
|
+
* const client = new Nomos('nms_live_...');
|
|
611
|
+
* const verdict = await client.can({ artifact_id: 'loan_approval_v1', credit_score: 720 });
|
|
612
|
+
*/
|
|
613
|
+
can(params: CanParams, opts?: CanOptions): Promise<CanResult>;
|
|
478
614
|
}
|
|
479
615
|
|
|
480
616
|
declare function can(params: CanParams, opts?: CanOptions): Promise<CanResult>;
|
|
481
617
|
/**
|
|
482
618
|
* Ready-to-use, keyless entry point matching the canonical `nomos.can(...)` form.
|
|
483
|
-
* For
|
|
619
|
+
* For paid artifacts or your own artifacts, use `client.can(...)` on an authenticated `Nomos`
|
|
620
|
+
* instance instead — same function name, same verdict shape, the only difference is which rail
|
|
621
|
+
* answers and what it can unlock.
|
|
484
622
|
*/
|
|
485
623
|
declare const nomos: {
|
|
486
624
|
can: typeof can;
|
|
487
625
|
};
|
|
488
626
|
|
|
489
|
-
|
|
627
|
+
/**
|
|
628
|
+
* Chain-of-trust verification (PROTOTYPE — not a numbered spec). Checks whether a presented
|
|
629
|
+
* artifact's signing key resolves, through the presented key certificates, back to a root you
|
|
630
|
+
* have independently decided to trust — entirely server-side against nomos-chain.ts's pure
|
|
631
|
+
* verifier, with no account or API key required (keyless, matching `nomos.can()`'s precedent).
|
|
632
|
+
*
|
|
633
|
+
* There is no default root anywhere in this call — `root_public_key_pem` is required. That's
|
|
634
|
+
* deliberate: it keeps the trust decision with the caller, not with this SDK or the platform.
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* import { verifyChain } from '@nomosprotocol/sdk';
|
|
638
|
+
*
|
|
639
|
+
* const result = await verifyChain({
|
|
640
|
+
* artifact: sealedArtifact,
|
|
641
|
+
* key_certs: [rootToIntermediate, intermediateToLeaf],
|
|
642
|
+
* root_public_key_pem: myPinnedRootPem,
|
|
643
|
+
* });
|
|
644
|
+
* if (result.decision === 'ALLOWED') { ... }
|
|
645
|
+
*/
|
|
646
|
+
declare function verifyChain(params: VerifyChainParams, opts?: VerifyChainOptions): Promise<VerifyChainResult>;
|
|
647
|
+
|
|
648
|
+
export { type Artifact, type ArtifactList, type ArtifactSchema, type ArtifactSchemaField, type AttestationInfo, type CanOptions, type CanParams, type CanResult, type CanVerdict, type ChainVerdictDecision, type Contradiction, type DetectContradictionsParams, type DetectContradictionsResult, type GenerateGovernanceParams, type GenerateGovernanceResult, type KeyCertificate, type ListArtifactsParams, Nomos, NomosAPIError, NomosAuthenticationError, NomosAuthorizationError, type NomosConfig, NomosError, type NomosErrorCode, NomosIssuerNotTrustedError, NomosNetworkError, NomosNotFoundError, NomosPaymentRequiredError, NomosRateLimitError, type NomosRawResponse, NomosValidationError, type NomosWebhookEvent, type NomosWebhookEventType, NomosWebhookSignatureError, type RequestOptions, type Verdict, type VerifyChainOptions, type VerifyChainParams, type VerifyChainResult, type VerifyDecisionParams, type VerifyDecisionResult, type WithLastResponse, can, nomos, verifyChain };
|