@nomosprotocol/sdk 1.3.4 → 2.0.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.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { CurrencyPolicy, ActVerdict } from '@nomosprotocol/verify';
2
+ export { bindingDigest, verifyAct, verifyArtifact, verifySeal } from '@nomosprotocol/verify';
3
+
1
4
  interface VerifyDecisionParams {
2
5
  /** Artifact ID from NOMOS Studio or the Exchange */
3
6
  artifact_id: string;
@@ -68,7 +71,7 @@ interface CanParams {
68
71
  * both `nomos.can()` and `client.can()`. */
69
72
  artifact?: unknown;
70
73
  /** The key certificates presented alongside `artifact` — order never affects the result. */
71
- key_certs?: KeyCertificate[];
74
+ key_certs?: KeyCertificate$1[];
72
75
  /** The root public key (PEM) YOU have independently decided to trust. There is deliberately no
73
76
  * default — see the chain-of-trust design note for why. Required alongside `artifact`. */
74
77
  root_public_key_pem?: string;
@@ -128,7 +131,10 @@ interface CanResult {
128
131
  }>;
129
132
  /** RECOMMENDED maximum seconds to hold this verdict before re-querying or re-checking the
130
133
  * 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." */
134
+ * structurally revocable on this deployment — treat absence as "unknown," not "safe forever."
135
+ * Disclosed gap: only ever set on the public authority rail today — client.can() and the
136
+ * presented-artifact rail don't emit it yet, so apply the same "don't hold a stale verdict
137
+ * across a meaningful delay" discipline manually on those two until that's closed. */
132
138
  max_age?: number;
133
139
  /** Present only when your own authenticated artifact answered — that rail's own provenance
134
140
  * (a hash you can store for compliance), not a permanent public transcript like `query_id`. */
@@ -151,8 +157,67 @@ interface CanResult {
151
157
  * (not a guess) on the Exchange/private-artifact rails, where this concept doesn't apply. */
152
158
  revocation_checked?: 'live' | 'staple' | 'unchecked';
153
159
  }
160
+ interface ConservedStateInfo {
161
+ artifact_id: string;
162
+ scope: string;
163
+ limit_amount: number;
164
+ consumed: number;
165
+ reserved: number;
166
+ available: number;
167
+ /** The raw ledger fact to pass into `can()` as `consumed_before` — already consumed+reserved
168
+ * (outstanding reservations count as spoken-for), not consumed alone. */
169
+ consumed_before: number;
170
+ version: number;
171
+ state_digest: string;
172
+ }
173
+ /** Reserve against a ledger using a real `can()` decision. */
174
+ interface ReserveByQueryParams {
175
+ artifact_id: string;
176
+ scope: string;
177
+ amount: number;
178
+ /** The `query_id` from a real `can()`/`nomos.can()` call that returned AUTHORIZED.
179
+ * `reserve()` looks that decision up itself and derives its own binding from it — this is a
180
+ * lookup key, not a claim you're asserting, and a made-up or already-used one is rejected. */
181
+ query_id: string;
182
+ action: string;
183
+ /** Optimistic-concurrency check: reject unless the ledger's state still matches what you last
184
+ * read via `conservedState.get()`. Omit only when you have no prior read to compare against. */
185
+ expected_state_digest?: string;
186
+ ttl_seconds?: number;
187
+ }
188
+ /** Reserve against a ledger using a NOMOS-SPEC-008 Act: the ledger verifies the Act itself (its
189
+ * own pinned root and audience id, its own `consumed_before`, single-use nonce) and holds exactly
190
+ * `act.action.params.amount` for `act.action.type === 'conserved_state.reserve'`, or nothing. */
191
+ interface ReserveByActParams {
192
+ artifact_id: string;
193
+ scope: string;
194
+ act: Record<string, unknown>;
195
+ ttl_seconds?: number;
196
+ }
197
+ type ReserveParams = ReserveByQueryParams | ReserveByActParams;
198
+ /** The cryptographically-bound reservation object — R-12 §5. */
199
+ interface Reservation {
200
+ reservation_id: string;
201
+ authority_seal: string;
202
+ decision_digest: string;
203
+ agent: string;
204
+ action: string;
205
+ scope: string;
206
+ amount: number;
207
+ state_digest: string;
208
+ expires_at: string;
209
+ status: 'held' | 'settled' | 'released' | 'expired';
210
+ }
211
+ interface ConservedStateReceipt {
212
+ reservation_id: string;
213
+ outcome: 'settled' | 'released';
214
+ amount: number;
215
+ ledger_key: string;
216
+ resolved_at: string;
217
+ reference?: string;
218
+ }
154
219
  type ChainVerdictDecision = 'ALLOWED' | 'ISSUER_NOT_RECOGNIZED' | 'KEY_REVOKED' | 'CERTIFICATE_REVOKED' | 'OUT_OF_SCOPE' | 'SEAL_INVALID' | 'MALFORMED';
155
- interface KeyCertificate {
220
+ interface KeyCertificate$1 {
156
221
  parent_kid: string;
157
222
  child_kid: string;
158
223
  child_public_key_pem: string;
@@ -166,13 +231,15 @@ interface VerifyChainParams {
166
231
  /** The sealed .nomos artifact being presented. */
167
232
  artifact: unknown;
168
233
  /** The set of key certificates presented alongside it — order never affects the result. */
169
- key_certs: KeyCertificate[];
234
+ key_certs: KeyCertificate$1[];
170
235
  /** The root public key (PEM) the CALLER has independently decided to trust. There is
171
236
  * deliberately no default — see the chain-of-trust design note for why. */
172
237
  root_public_key_pem: string;
173
238
  }
174
239
  interface VerifyChainOptions {
175
- /** Override the API host (defaults to the public NOMOS platform). */
240
+ /** Ask the hosted platform instead of verifying locally. Off by default. */
241
+ remote?: boolean;
242
+ /** With `remote`: override the API host (defaults to the public NOMOS platform). */
176
243
  baseUrl?: string;
177
244
  signal?: AbortSignal;
178
245
  }
@@ -525,32 +592,107 @@ declare class Webhooks {
525
592
  verifySignature(payload: string | Uint8Array, signature: string, secret: string, toleranceSeconds?: number): Promise<boolean>;
526
593
  }
527
594
 
595
+ /**
596
+ * The state layer for a conserved (depleting) budget — R-12, a design in progress
597
+ * (docs/design-notes/conserved-state-authority.md in the platform repo; public mirror:
598
+ * computableauthority.com/research/conserved-state-authority). PROTOTYPE, not a numbered spec.
599
+ *
600
+ * `can()` stays exactly what it always was: pure, stateless, given facts and returning a
601
+ * verdict. Nothing here changes that. This resource is what a caller consults BEFORE calling
602
+ * `can()` (to build the `consumed_before` fact) and commits to AFTER `can()` returns AUTHORIZED
603
+ * and the caller has actually decided to act — never at `can()` time itself (repeatedly calling
604
+ * `can()` while deciding must never itself burn the budget).
605
+ *
606
+ * @example
607
+ * const state = await client.conservedState.get('supplier-budget-2026', 'supplier:acme');
608
+ * const verdict = await client.can({ artifact_id: 'supplier-budget-2026', consumed_before: state.consumed_before });
609
+ * if (verdict.allowed) {
610
+ * const reservation = await client.conservedState.reserve({
611
+ * artifact_id: 'supplier-budget-2026', scope: 'supplier:acme',
612
+ * amount: 5000, query_id: verdict.query_id!, action: 'payments.transfer',
613
+ * });
614
+ * try {
615
+ * // ... perform the real action ...
616
+ * await client.conservedState.settle(reservation.reservation_id);
617
+ * } catch {
618
+ * await client.conservedState.release(reservation.reservation_id);
619
+ * }
620
+ * }
621
+ */
622
+ declare class ConservedState {
623
+ private readonly http;
624
+ constructor(http: HttpClient);
625
+ /**
626
+ * Read a ledger's current balance — no auth required, same posture as `can()`'s own keyless
627
+ * rail (reading how much budget remains is no more sensitive than reading a verdict).
628
+ */
629
+ get(artifactId: string, scope: string, opts?: RequestOptions): Promise<WithLastResponse<ConservedStateInfo>>;
630
+ /**
631
+ * Commit capacity against a REAL, AUTHORIZED `can()` decision. Authenticated — unlike `can()`,
632
+ * spending against a shared budget requires an API key or session; `agent` on the returned
633
+ * reservation traces to that authenticated identity, never a value you pass in.
634
+ *
635
+ * Throws (via the SDK's standard NomosError hierarchy; `err.details?.code` carries the
636
+ * server's own code): `DECISION_NOT_FOUND` (the query_id names no real query), `DECISION_NOT
637
+ * _AUTHORIZED` (that decision didn't verdict AUTHORIZED for this artifact), `DECISION_ALREADY
638
+ * _USED` (already bound to a reservation — one decision authorizes one, ever), `STATE_CONFLICT`
639
+ * (a stale `expected_state_digest`), `INSUFFICIENT_CAPACITY` (`err.details.requested`/
640
+ * `.available` carry the numbers), or `NO_LEDGER` (nobody has declared this budget yet).
641
+ *
642
+ * Passing `{ artifact_id, scope, act }` instead authorizes the hold with a NOMOS-SPEC-008 Act.
643
+ * Extra codes: `ACT_NOT_ACCEPTED` (the ledger has no Act binding) and `ACT_REJECTED`, with the
644
+ * verifier's full answer in `err.details.result` — for `INCOMPLETE` it names the open rules and
645
+ * the facts whose testimony would decide them.
646
+ */
647
+ reserve(params: ReserveParams, opts?: RequestOptions): Promise<WithLastResponse<Reservation>>;
648
+ /**
649
+ * The reserved action succeeded — moves the hold into real, settled spend. Idempotent when
650
+ * you pass the same `reference` again for a retry (e.g. after a network timeout): you get the
651
+ * ORIGINAL receipt back, never a double-charge.
652
+ */
653
+ settle(reservationId: string, reference?: string, opts?: RequestOptions): Promise<WithLastResponse<ConservedStateReceipt>>;
654
+ /**
655
+ * The reserved action failed, or you decided not to act — gives the hold's capacity back
656
+ * without ever touching what's actually been spent.
657
+ */
658
+ release(reservationId: string, reference?: string, opts?: RequestOptions): Promise<WithLastResponse<ConservedStateReceipt>>;
659
+ }
660
+
528
661
  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';
529
662
  declare class NomosError extends Error {
530
663
  readonly code: NomosErrorCode;
531
664
  readonly status?: number;
532
665
  readonly requestId?: string;
533
- constructor(message: string, code: NomosErrorCode, status?: number, requestId?: string);
666
+ /** The full parsed JSON response body, when the server sent one — every field it put there
667
+ * (its own `code`, and anything endpoint-specific like `requested`/`available` on a
668
+ * conserved-state capacity rejection, or `price_usd`/`purchase_url` before those got a
669
+ * dedicated error class). `NomosError`'s own `code` above is the SDK's fixed HTTP-status
670
+ * taxonomy; `details?.code` is the SERVER's own, finer-grained application code — the two
671
+ * are deliberately not conflated into one field. */
672
+ readonly details?: unknown;
673
+ constructor(message: string, code: NomosErrorCode, status?: number, requestId?: string, details?: unknown);
534
674
  }
535
675
  declare class NomosAuthenticationError extends NomosError {
536
- constructor(message?: string, requestId?: string);
676
+ constructor(message?: string, requestId?: string, details?: unknown);
537
677
  }
538
678
  declare class NomosAuthorizationError extends NomosError {
539
- constructor(message?: string, requestId?: string);
679
+ constructor(message?: string, requestId?: string, details?: unknown);
540
680
  }
541
681
  declare class NomosRateLimitError extends NomosError {
542
682
  readonly retryAfter?: number;
543
- constructor(message?: string, retryAfter?: number, requestId?: string);
683
+ constructor(message?: string, retryAfter?: number, requestId?: string, details?: unknown);
544
684
  }
685
+ /** `details` is the parsed response body — kept as its own constructor param (rather than just
686
+ * relying on the base class field) since it long predates NomosError.details and every caller
687
+ * already passes it positionally in this slot; unchanged for backward compatibility. */
545
688
  declare class NomosValidationError extends NomosError {
546
- readonly details?: unknown;
547
689
  constructor(message: string, details?: unknown, requestId?: string);
548
690
  }
549
691
  declare class NomosNotFoundError extends NomosError {
550
- constructor(message: string, requestId?: string);
692
+ constructor(message: string, requestId?: string, details?: unknown);
551
693
  }
552
694
  declare class NomosAPIError extends NomosError {
553
- constructor(message: string, status: number, requestId?: string);
695
+ constructor(message: string, status: number, requestId?: string, details?: unknown);
554
696
  }
555
697
  declare class NomosNetworkError extends NomosError {
556
698
  constructor(message: string);
@@ -620,6 +762,9 @@ declare class Nomos {
620
762
  readonly artifacts: Artifacts;
621
763
  readonly governance: Governance;
622
764
  readonly webhooks: Webhooks;
765
+ /** The R-12 conserved-state (depleting-budget) state layer — PROTOTYPE, not a numbered spec.
766
+ * See resources/conserved-state.ts for the full reserve/settle/release lifecycle. */
767
+ readonly conservedState: ConservedState;
623
768
  /** Whether this instance is using a live or test API key. */
624
769
  readonly mode: 'live' | 'test';
625
770
  static readonly errors: typeof errors;
@@ -649,24 +794,412 @@ declare const nomos: {
649
794
  };
650
795
 
651
796
  /**
652
- * Chain-of-trust verification (PROTOTYPE — not a numbered spec). Checks whether a presented
653
- * artifact's signing key resolves, through the presented key certificates, back to a root you
654
- * have independently decided to trust — entirely server-side against nomos-chain.ts's pure
655
- * verifier, with no account or API key required (keyless, matching `nomos.can()`'s precedent).
797
+ * NOMOS-SPEC-007 rev. 1.9 chain verification: does this artifact's signing key resolve, through the
798
+ * presented key certificates, to a root you have decided to trust, and was it delegated this artifact?
656
799
  *
657
- * There is no default root anywhere in this call — `root_public_key_pem` is required. That's
658
- * deliberate: it keeps the trust decision with the caller, not with this SDK or the platform.
800
+ * Computed locally by @nomosprotocol/verify: no network call, no account, and no dependence on any
801
+ * NOMOS service being up or honest. There is no default root: `root_public_key_pem` is required, so
802
+ * the trust decision stays with you. Pass `{ remote: true }` only to ask the hosted platform instead.
659
803
  *
660
804
  * @example
661
- * import { verifyChain } from '@nomosprotocol/sdk';
662
- *
663
- * const result = await verifyChain({
664
- * artifact: sealedArtifact,
665
- * key_certs: [rootToIntermediate, intermediateToLeaf],
666
- * root_public_key_pem: myPinnedRootPem,
667
- * });
805
+ * const result = await verifyChain({ artifact, key_certs, root_public_key_pem: myPinnedRootPem });
668
806
  * if (result.decision === 'ALLOWED') { ... }
669
807
  */
670
808
  declare function verifyChain(params: VerifyChainParams, opts?: VerifyChainOptions): Promise<VerifyChainResult>;
671
809
 
672
- 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 };
810
+ type SignatureSuite = 'Ed25519' | 'ES256';
811
+ interface Signer {
812
+ /** NOMOS-SPEC-001 §8.4 key id of the public key. */
813
+ kid: string;
814
+ /** The public key, canonical SPKI PEM (NOMOS-SPEC-010 §3.1). */
815
+ publicKeyPem: string;
816
+ /** The suite this key signs under. */
817
+ algorithm: SignatureSuite;
818
+ /** Signs the exact payload bytes. Returns the signature in the suite's encoding, base64. */
819
+ sign(payload: Uint8Array): Promise<string>;
820
+ }
821
+ declare function kidOf(publicKeyPem: string): string;
822
+ /** A signer over a private key held in this process: PKCS#8 PEM. For development and tests;
823
+ * in production pass a Signer backed by your KMS or HSM. */
824
+ declare function localSigner(privateKeyPem: string): Signer;
825
+ /** A fresh in-memory key. For development and tests only. */
826
+ declare function generateSigner(algorithm?: SignatureSuite): Signer & {
827
+ privateKeyPem: string;
828
+ };
829
+ /** A deterministic Ed25519 key from a seed string: the same test key on every machine. Never for
830
+ * anything real — the seed is the key. */
831
+ declare function seededSigner(seed: string): Signer;
832
+
833
+ interface Action {
834
+ type: string;
835
+ subject?: string;
836
+ params?: Record<string, unknown>;
837
+ }
838
+ interface KeyCertificate {
839
+ parent_kid: string;
840
+ child_kid: string;
841
+ child_public_key_pem: string;
842
+ scope?: string | null;
843
+ issued_at: string;
844
+ expires_at: string;
845
+ algorithm: 'Ed25519' | 'ES256';
846
+ signature: string;
847
+ }
848
+ /** NOMOS-SPEC-007 §3: `parent` certifies `child` within `scope` until `expiresAt`. */
849
+ declare function certify(parent: Signer, child: {
850
+ kid: string;
851
+ publicKeyPem: string;
852
+ }, opts: {
853
+ scope?: string;
854
+ issuedAt?: Date;
855
+ expiresAt: Date;
856
+ }): Promise<KeyCertificate>;
857
+ /** NOMOS-SPEC-001 §8: seal an artifact body with the issuer's key. */
858
+ declare function seal(body: Record<string, unknown>, issuer: Signer, signedBy: Record<string, unknown> | string): Promise<any>;
859
+ /** NOMOS-SPEC-008 §3: a witness's signed statement of one fact about one subject. */
860
+ declare function signTestimony(witness: Signer, t: {
861
+ claim: string;
862
+ value: unknown;
863
+ about?: string | null;
864
+ asOf?: Date;
865
+ validUntil: Date;
866
+ }): Promise<any>;
867
+ /** NOMOS-SPEC-008 §4: an approver's consent to exactly this Act, in this role. */
868
+ declare function signConsent(approver: Signer, act: any, role: string, decision?: 'approve' | 'refuse'): Promise<any>;
869
+ /** NOMOS-SPEC-008 §5.4: the issuer's statement that this exact version is in force, for a day at most. */
870
+ declare function signInForce(issuer: Signer, artifact: any, opts: {
871
+ asOf?: Date;
872
+ validUntil: Date;
873
+ }): Promise<any>;
874
+ interface BuildActOptions {
875
+ relyingParty: string;
876
+ action: Action;
877
+ artifact: any;
878
+ keyCerts: KeyCertificate[];
879
+ testimony?: any[];
880
+ presenterFacts?: Record<string, unknown>;
881
+ inForce?: any;
882
+ /** Validity window in seconds (SPEC-008 §5.1). Longer windows leave a person time to approve. */
883
+ windowSeconds?: number;
884
+ now?: Date;
885
+ }
886
+ /** NOMOS-SPEC-008 §2: assemble an Act. It needs no key: what makes it valid is what it carries. */
887
+ declare function buildAct(o: BuildActOptions): any;
888
+
889
+ /**
890
+ * NOMOS-SPEC-009 §3 discovery documents. A document tells a carrier where to go and what to bring;
891
+ * it never decides anything (§2), so nothing here is trusted beyond what the verifier rechecks.
892
+ */
893
+
894
+ interface RelyingPartyDocument {
895
+ nomos_document: 'relying-party';
896
+ version: '1';
897
+ relying_party_id: string;
898
+ act_endpoint: string;
899
+ roots: Array<{
900
+ kid: string;
901
+ public_key_pem: string;
902
+ }>;
903
+ authorities: Array<{
904
+ artifact_id: string;
905
+ issuer?: string;
906
+ actions: string[];
907
+ currency_policy: 'record' | 'record_or_statement';
908
+ in_force_seal_hash?: string;
909
+ }>;
910
+ local_facts?: string[];
911
+ max_window_seconds: number;
912
+ max_act_bytes?: number;
913
+ consent_suites?: string[];
914
+ valid_until?: string;
915
+ }
916
+ interface IssuerDocument {
917
+ nomos_document: 'issuer';
918
+ version: '1';
919
+ issuer_id: string;
920
+ authorities: Array<{
921
+ artifact_id: string;
922
+ version: string;
923
+ seal_hash: string;
924
+ artifact_url: string;
925
+ in_force_url?: string;
926
+ }>;
927
+ key_certs: KeyCertificate[];
928
+ witnesses?: string[];
929
+ approvals?: Array<{
930
+ role: string;
931
+ endpoint: string;
932
+ }>;
933
+ revocations_url?: string;
934
+ valid_until?: string;
935
+ }
936
+ interface WitnessDocument {
937
+ nomos_document: 'witness';
938
+ version: '1';
939
+ witness_id: string;
940
+ kid: string;
941
+ claims: string[];
942
+ statement_endpoint: string;
943
+ access?: string;
944
+ valid_until?: string;
945
+ }
946
+ declare const PATH: {
947
+ readonly 'relying-party': "/.well-known/nomos-relying-party";
948
+ readonly issuer: "/.well-known/nomos-issuer";
949
+ readonly witness: "/.well-known/nomos-witness";
950
+ };
951
+ type Kind = keyof typeof PATH;
952
+ type DocOf<K extends Kind> = K extends 'relying-party' ? RelyingPartyDocument : K extends 'issuer' ? IssuerDocument : WitnessDocument;
953
+ declare class NomosDiscoveryError extends Error {
954
+ readonly url: string;
955
+ constructor(message: string, url: string);
956
+ }
957
+ /** The origin of a URL or bare origin: `https://shop.example/anything` → `https://shop.example`. */
958
+ declare function originOf(to: string): string;
959
+ /** Fetches and checks one discovery document (§2 rule 4, §3). */
960
+ declare function fetchDocument<K extends Kind>(kind: K, origin: string, fetchImpl?: typeof fetch): Promise<DocOf<K>>;
961
+ declare const WELL_KNOWN: {
962
+ readonly 'relying-party': "/.well-known/nomos-relying-party";
963
+ readonly issuer: "/.well-known/nomos-issuer";
964
+ readonly witness: "/.well-known/nomos-witness";
965
+ };
966
+
967
+ /**
968
+ * accept() — the relying party: the system that makes the change.
969
+ *
970
+ * const rp = accept({ relyingPartyId, root, authorities, commit });
971
+ * app.use(rp.express()); // Express, Connect, node:http
972
+ * export default { fetch: rp.fetch }; // Hono, Next.js, Cloudflare, Deno, Bun
973
+ *
974
+ * For every Act it receives it runs NOMOS-SPEC-008 §6 with @nomosprotocol/verify, locally, and on
975
+ * AUTHORIZED applies §8 exactly, in one transaction: record the nonce, re-read its own facts
976
+ * (re-verifying if they moved), hand `commit` a copy of exactly the verified action, and store the
977
+ * receipt. It answers with the NOMOS-SPEC-009 §6.2 status codes and serves its own discovery
978
+ * document (§3.1), generated from this same configuration so the two can never disagree (§2).
979
+ */
980
+
981
+ interface AcceptedAuthority {
982
+ /** The sealed artifact's meta.artifact_id. */
983
+ artifactId: string;
984
+ /** Origin of the issuer document (NOMOS-SPEC-009 §3.2), advertised so carriers can find it. */
985
+ issuer?: string;
986
+ /** The action types this system commits under this authority. Anything else is refused. */
987
+ actions: string[];
988
+ /** SPEC-008 §5.5. `record` (RECOMMENDED) needs `inForceSealHash`. */
989
+ currencyPolicy: CurrencyPolicy;
990
+ /** Your record of the version in force: the seal hash of the version you accept. */
991
+ inForceSealHash?: string;
992
+ }
993
+ interface Receipt {
994
+ act_id: string;
995
+ act_digest: string;
996
+ decision: string;
997
+ rule: string | null;
998
+ by_consent?: boolean;
999
+ verified_at: string;
1000
+ committed_at?: string;
1001
+ relying_party_facts: Record<string, unknown>;
1002
+ in_force_source?: string;
1003
+ currency_policy: CurrencyPolicy;
1004
+ consent_origins?: string[];
1005
+ }
1006
+ /** One atomic operation (SPEC-008 §8). `tx` is passed to `commit` and `localFacts` so your own
1007
+ * writes and reads share it. */
1008
+ interface AcceptTransaction<Tx = unknown> {
1009
+ /** Records the nonce. false if it was already recorded (a concurrent duplicate). */
1010
+ claimNonce(nonce: string): Promise<boolean>;
1011
+ putReceipt(nonce: string, receipt: Receipt): Promise<void>;
1012
+ tx: Tx;
1013
+ }
1014
+ interface AcceptStore<Tx = unknown> {
1015
+ hasNonce(nonce: string): Promise<boolean>;
1016
+ receiptFor(nonce: string): Promise<Receipt | null>;
1017
+ transaction<T>(fn: (t: AcceptTransaction<Tx>) => Promise<T>): Promise<T>;
1018
+ }
1019
+ interface AcceptOptions<Tx = unknown> {
1020
+ /** Your identifier. Acts addressed to anything else are refused (SPEC-008 §5.3). */
1021
+ relyingPartyId: string;
1022
+ /** The root you pin (PEM). There is no default root. */
1023
+ root: string;
1024
+ authorities: AcceptedAuthority[];
1025
+ /** Applies the change. Receives a deep copy of exactly the verified action, and nothing else
1026
+ * from the request (SPEC-009 §6.4). Its return value is sent back as `result`. */
1027
+ commit: (action: {
1028
+ type: string;
1029
+ subject?: string;
1030
+ params: Record<string, unknown>;
1031
+ }, ctx: {
1032
+ tx: Tx;
1033
+ actId: string;
1034
+ }) => Promise<unknown> | unknown;
1035
+ /** Facts you supply from your own state (inputs with source `relying_party`). Called once to
1036
+ * verify, and again inside the transaction to check nothing moved (SPEC-008 §8 step 3). */
1037
+ localFacts?: (act: any, tx?: Tx) => Promise<Record<string, unknown>> | Record<string, unknown>;
1038
+ /** Where nonces and receipts live. Defaults to memory, for development only. */
1039
+ store?: AcceptStore<Tx>;
1040
+ /** The absolute URL carriers POST Acts to, as advertised in your discovery document. */
1041
+ actEndpoint: string;
1042
+ /** SPEC-008 §5.1 / SPEC-009 §6.3. Long enough for a person to approve. Default 900. */
1043
+ maxWindowSeconds?: number;
1044
+ maxActBytes?: number;
1045
+ /** Current revocation state (SPEC-006, SPEC-007 §5). Read on every verification. */
1046
+ revocations?: () => Promise<{
1047
+ kids?: Set<string>;
1048
+ certs?: Set<string>;
1049
+ artifacts?: Set<string>;
1050
+ }> | {
1051
+ kids?: Set<string>;
1052
+ certs?: Set<string>;
1053
+ artifacts?: Set<string>;
1054
+ };
1055
+ /** `shadow`: verify and record every verdict, never commit. For pilots. */
1056
+ mode?: 'enforce' | 'shadow';
1057
+ /** Every verdict, committed or not (SPEC-008 §9: a receipt for every verification). */
1058
+ onVerdict?: (verdict: ActVerdict, receipt: Receipt) => void | Promise<void>;
1059
+ /** How long this document is valid for, in seconds. Default one day. */
1060
+ documentTtlSeconds?: number;
1061
+ now?: () => Date;
1062
+ }
1063
+ interface Answer {
1064
+ status: number;
1065
+ headers: Record<string, string>;
1066
+ body: Record<string, unknown>;
1067
+ }
1068
+ declare const statusFor: (decision: string) => number;
1069
+ declare const ACT_MEDIA_TYPE = "application/nomos-act+json";
1070
+ /** Nonces and receipts in memory, one transaction at a time. Lost on restart, single process:
1071
+ * for development and tests only. Use a database-backed store in production. */
1072
+ declare function memoryStore(): AcceptStore<null>;
1073
+ declare function accept<Tx = unknown>(o: AcceptOptions<Tx>): {
1074
+ handle: (req: {
1075
+ method?: string;
1076
+ headers: Record<string, string | string[] | undefined>;
1077
+ body: string | Uint8Array;
1078
+ }) => Promise<Answer>;
1079
+ document: () => RelyingPartyDocument;
1080
+ fetch: (request: Request) => Promise<Response>;
1081
+ express: () => (req: any, res: any, next?: () => void) => Promise<void>;
1082
+ node: () => (req: any, res: any, next?: () => void) => Promise<void>;
1083
+ };
1084
+
1085
+ type ActStatus = 'committed' | 'escalated' | 'incomplete' | 'denied' | 'refused' | 'replayed';
1086
+ interface ActResult {
1087
+ status: ActStatus;
1088
+ /** The relying party's verdict, exactly as it returned it (SPEC-009 §6.2). */
1089
+ verdict: Record<string, any>;
1090
+ /** When committed: the receipt, and what the relying party's commit returned. */
1091
+ receipt?: Record<string, any>;
1092
+ result?: unknown;
1093
+ /** When incomplete: the facts that could still change the outcome, and why each is missing. */
1094
+ missing?: Array<{
1095
+ fact: string;
1096
+ source: string | null;
1097
+ why: string;
1098
+ }>;
1099
+ /** When escalated and not approved in time: where a person can approve. */
1100
+ approvalUrl?: string;
1101
+ /** The Act as submitted, for your records. */
1102
+ act: any;
1103
+ /** What happened, in one sentence. */
1104
+ summary: string;
1105
+ }
1106
+ interface ActOptions {
1107
+ /** The relying party: its origin or any URL on it. */
1108
+ to: string;
1109
+ action: Action;
1110
+ /** Which authority to act under, when the relying party accepts several for this action type. */
1111
+ authority?: string;
1112
+ /** Facts the carrier supplies itself (inputs whose declared source is `presenter`). */
1113
+ presenterFacts?: Record<string, unknown>;
1114
+ /** Credentials for witnesses that need them: origin → headers (SPEC-009 §3.3 `access`). */
1115
+ witnessHeaders?: Record<string, Record<string, string>>;
1116
+ /** Wait up to this long for a person to approve, in ms. Default: until the Act expires. */
1117
+ approvalTimeoutMs?: number;
1118
+ /** Called once per pending approval with the page a person can approve on. */
1119
+ onApproval?: (approval: {
1120
+ role: string;
1121
+ url?: string;
1122
+ actDigest: string;
1123
+ }) => void;
1124
+ /** Use a specific fetch (tests, proxies). */
1125
+ fetch?: typeof fetch;
1126
+ /** Poll interval for pending approvals, ms. Default 1000. */
1127
+ pollMs?: number;
1128
+ }
1129
+ declare class NomosActError extends Error {
1130
+ constructor(message: string);
1131
+ }
1132
+ declare function act(o: ActOptions): Promise<ActResult>;
1133
+
1134
+ interface IssuerOptions {
1135
+ /** Your public origin, e.g. https://policy.acme.example */
1136
+ origin: string;
1137
+ issuerId: string;
1138
+ /** The key that sealed the authorities; it also signs in-force statements (SPEC-008 §5.4). */
1139
+ signer: Signer;
1140
+ /** Sealed artifacts, each the version currently in force. */
1141
+ authorities: any[];
1142
+ /** The certificate pool carriers present: your sealing key, witnesses, approvers (SPEC-007). */
1143
+ keyCerts: KeyCertificate[];
1144
+ witnesses?: string[];
1145
+ approvals?: Array<{
1146
+ role: string;
1147
+ endpoint: string;
1148
+ }>;
1149
+ revocationsUrl?: string;
1150
+ }
1151
+ declare function issuer(o: IssuerOptions): {
1152
+ fetch: (request: Request) => Promise<Response>;
1153
+ express: () => (req: any, res: any, next?: () => void) => Promise<any>;
1154
+ node: () => (req: any, res: any, next?: () => void) => Promise<any>;
1155
+ document: () => IssuerDocument;
1156
+ };
1157
+ interface WitnessOptions {
1158
+ origin: string;
1159
+ witnessId: string;
1160
+ /** A key certified for exactly these claims (SPEC-007 rev. 1.8 §3.4.1). */
1161
+ signer: Signer;
1162
+ /** Each claim this witness states, and how to read its current value for a subject. Return
1163
+ * undefined when the subject is unknown. */
1164
+ claims: Record<string, (about: string | null) => unknown | Promise<unknown>>;
1165
+ /** How long a statement stays true, at most, in seconds. Default 900. */
1166
+ maxValiditySeconds?: number;
1167
+ /** Your access control (SPEC-009 §3.3): return false to refuse a requester. */
1168
+ authorize?: (request: {
1169
+ claim: string;
1170
+ about: string | null;
1171
+ }) => boolean | Promise<boolean>;
1172
+ access?: string;
1173
+ }
1174
+ declare function witness(o: WitnessOptions): {
1175
+ fetch: (request: Request) => Promise<Response>;
1176
+ express: () => (req: any, res: any, next?: () => void) => Promise<any>;
1177
+ node: () => (req: any, res: any, next?: () => void) => Promise<any>;
1178
+ document: () => WitnessDocument;
1179
+ };
1180
+ interface ApproverOptions {
1181
+ origin: string;
1182
+ /** The person's key, certified with `consent:<role> approver:<their id>` (SPEC-007 rev. 1.9 §3.7). */
1183
+ signer: Signer;
1184
+ roles: string[];
1185
+ /** 'page' (default): a person approves on a page this handler serves. 'auto': approve every
1186
+ * request at once — development only. Or a function that decides. */
1187
+ decide?: 'page' | 'auto' | ((request: {
1188
+ role: string;
1189
+ act: any;
1190
+ }) => boolean | Promise<boolean>);
1191
+ }
1192
+ interface Pending {
1193
+ role: string;
1194
+ act: any;
1195
+ status: 'pending' | 'approved' | 'refused' | 'expired';
1196
+ consent?: any;
1197
+ }
1198
+ declare function approver(o: ApproverOptions): {
1199
+ fetch: (request: Request) => Promise<Response>;
1200
+ express: () => (req: any, res: any, next?: () => void) => Promise<any>;
1201
+ node: () => (req: any, res: any, next?: () => void) => Promise<any>;
1202
+ pending: Map<string, Pending>;
1203
+ };
1204
+
1205
+ export { ACT_MEDIA_TYPE, type AcceptOptions, type AcceptStore, type AcceptTransaction, type AcceptedAuthority, type KeyCertificate as ActKeyCertificate, type ActOptions, type ActResult, type ActStatus, type Action, type Answer, type ApproverOptions, type Artifact, type ArtifactList, type ArtifactSchema, type ArtifactSchemaField, type AttestationInfo, type BuildActOptions, type CanOptions, type CanParams, type CanResult, type CanVerdict, type ChainVerdictDecision, type ConservedStateInfo, type ConservedStateReceipt, type Contradiction, type DetectContradictionsParams, type DetectContradictionsResult, type GenerateGovernanceParams, type GenerateGovernanceResult, type IssuerDocument, type IssuerOptions, type KeyCertificate$1 as KeyCertificate, type ListArtifactsParams, Nomos, NomosAPIError, NomosActError, NomosAuthenticationError, NomosAuthorizationError, type NomosConfig, NomosDiscoveryError, NomosError, type NomosErrorCode, NomosIssuerNotTrustedError, NomosNetworkError, NomosNotFoundError, NomosPaymentRequiredError, NomosRateLimitError, type NomosRawResponse, NomosValidationError, type NomosWebhookEvent, type NomosWebhookEventType, NomosWebhookSignatureError, type Receipt, type RelyingPartyDocument, type RequestOptions, type Reservation, type ReserveByActParams, type ReserveByQueryParams, type ReserveParams, type SignatureSuite, type Signer, type Verdict, type VerifyChainOptions, type VerifyChainParams, type VerifyChainResult, type VerifyDecisionParams, type VerifyDecisionResult, WELL_KNOWN, type WithLastResponse, type WitnessDocument, type WitnessOptions, accept, act, approver, buildAct, can, certify, fetchDocument, generateSigner, issuer, kidOf, localSigner, memoryStore, nomos, originOf, seal, seededSigner, signConsent, signInForce, signTestimony, statusFor, verifyChain, witness };