@nomosprotocol/sdk 1.4.0 → 2.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.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { CurrencyPolicy, ActVerdict, KeyCertificate as KeyCertificate$2, RevocationStatement, RevocationList, ScopeTerms } 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;
@@ -214,7 +217,7 @@ interface ConservedStateReceipt {
214
217
  reference?: string;
215
218
  }
216
219
  type ChainVerdictDecision = 'ALLOWED' | 'ISSUER_NOT_RECOGNIZED' | 'KEY_REVOKED' | 'CERTIFICATE_REVOKED' | 'OUT_OF_SCOPE' | 'SEAL_INVALID' | 'MALFORMED';
217
- interface KeyCertificate {
220
+ interface KeyCertificate$1 {
218
221
  parent_kid: string;
219
222
  child_kid: string;
220
223
  child_public_key_pem: string;
@@ -228,13 +231,15 @@ interface VerifyChainParams {
228
231
  /** The sealed .nomos artifact being presented. */
229
232
  artifact: unknown;
230
233
  /** The set of key certificates presented alongside it — order never affects the result. */
231
- key_certs: KeyCertificate[];
234
+ key_certs: KeyCertificate$1[];
232
235
  /** The root public key (PEM) the CALLER has independently decided to trust. There is
233
236
  * deliberately no default — see the chain-of-trust design note for why. */
234
237
  root_public_key_pem: string;
235
238
  }
236
239
  interface VerifyChainOptions {
237
- /** 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). */
238
243
  baseUrl?: string;
239
244
  signal?: AbortSignal;
240
245
  }
@@ -789,24 +794,752 @@ declare const nomos: {
789
794
  };
790
795
 
791
796
  /**
792
- * Chain-of-trust verification (PROTOTYPE — not a numbered spec). Checks whether a presented
793
- * artifact's signing key resolves, through the presented key certificates, back to a root you
794
- * have independently decided to trust — entirely server-side against nomos-chain.ts's pure
795
- * 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?
796
799
  *
797
- * There is no default root anywhere in this call — `root_public_key_pem` is required. That's
798
- * 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.
799
803
  *
800
804
  * @example
801
- * import { verifyChain } from '@nomosprotocol/sdk';
802
- *
803
- * const result = await verifyChain({
804
- * artifact: sealedArtifact,
805
- * key_certs: [rootToIntermediate, intermediateToLeaf],
806
- * root_public_key_pem: myPinnedRootPem,
807
- * });
805
+ * const result = await verifyChain({ artifact, key_certs, root_public_key_pem: myPinnedRootPem });
808
806
  * if (result.decision === 'ALLOWED') { ... }
809
807
  */
810
808
  declare function verifyChain(params: VerifyChainParams, opts?: VerifyChainOptions): Promise<VerifyChainResult>;
811
809
 
812
- export { type Artifact, type ArtifactList, type ArtifactSchema, type ArtifactSchemaField, type AttestationInfo, 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 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 Reservation, type ReserveByActParams, type ReserveByQueryParams, type ReserveParams, 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
+ /** The key id of a canonical Ed25519 or P-256 public key (NOMOS-SPEC-010 §3.1–§3.2). Throws for
822
+ * any other key: a non-canonical key has no key id, because no verifier would accept it. */
823
+ declare function kidOf(publicKeyPem: string): string;
824
+ /** A signer over a private key held in this process: PKCS#8 PEM (or SEC1 for P-256). For
825
+ * development and tests; in production pass a Signer backed by your KMS or HSM. */
826
+ declare function localSigner(privateKeyPem: string): Signer;
827
+ /** A fresh in-memory key. For development and tests only. */
828
+ declare function generateSigner(algorithm?: SignatureSuite): Signer & {
829
+ privateKeyPem: string;
830
+ };
831
+ /** A deterministic Ed25519 key from a seed string: the same test key on every machine. Never for
832
+ * anything real — the seed is the key. */
833
+ declare function seededSigner(seed: string): Signer;
834
+
835
+ interface Action {
836
+ type: string;
837
+ subject?: string;
838
+ params?: Record<string, unknown>;
839
+ }
840
+ interface KeyCertificate {
841
+ parent_kid: string;
842
+ child_kid: string;
843
+ child_public_key_pem: string;
844
+ scope?: string | null;
845
+ issued_at: string;
846
+ expires_at: string;
847
+ algorithm: 'Ed25519' | 'ES256';
848
+ signature: string;
849
+ }
850
+ /** NOMOS-SPEC-007 §3: `parent` certifies `child` within `scope` until `expiresAt`. */
851
+ declare function certify(parent: Signer, child: {
852
+ kid: string;
853
+ publicKeyPem: string;
854
+ }, opts: {
855
+ scope?: string;
856
+ issuedAt?: Date;
857
+ expiresAt: Date;
858
+ }): Promise<KeyCertificate>;
859
+ /** NOMOS-SPEC-001 §8: seal an artifact body with the issuer's key. */
860
+ declare function seal(body: Record<string, unknown>, issuer: Signer, signedBy: Record<string, unknown> | string): Promise<any>;
861
+ /** NOMOS-SPEC-008 §3: a witness's signed statement of one fact about one subject. */
862
+ declare function signTestimony(witness: Signer, t: {
863
+ claim: string;
864
+ value: unknown;
865
+ about?: string | null;
866
+ asOf?: Date;
867
+ validUntil: Date;
868
+ }): Promise<any>;
869
+ /** NOMOS-SPEC-008 §4: an approver's consent to exactly this Act, in this role. */
870
+ declare function signConsent(approver: Signer, act: any, role: string, decision?: 'approve' | 'refuse'): Promise<any>;
871
+ /** NOMOS-SPEC-008 §5.4: the issuer's statement that this exact version is in force, for a day at most. */
872
+ declare function signInForce(issuer: Signer, artifact: any, opts: {
873
+ asOf?: Date;
874
+ validUntil: Date;
875
+ }): Promise<any>;
876
+ interface BuildActOptions {
877
+ relyingParty: string;
878
+ action: Action;
879
+ artifact: any;
880
+ keyCerts: KeyCertificate[];
881
+ testimony?: any[];
882
+ presenterFacts?: Record<string, unknown>;
883
+ inForce?: any;
884
+ /** Validity window in seconds (SPEC-008 §5.1). Longer windows leave a person time to approve. */
885
+ windowSeconds?: number;
886
+ now?: Date;
887
+ }
888
+ /** NOMOS-SPEC-008 §2: assemble an Act. It needs no key: what makes it valid is what it carries. */
889
+ declare function buildAct(o: BuildActOptions): any;
890
+
891
+ /**
892
+ * NOMOS-SPEC-009 §3 discovery documents. A document tells a carrier where to go and what to bring;
893
+ * it never decides anything (§2), so nothing here is trusted beyond what the verifier rechecks.
894
+ */
895
+
896
+ interface RelyingPartyDocument {
897
+ nomos_document: 'relying-party';
898
+ version: '1';
899
+ relying_party_id: string;
900
+ act_endpoint: string;
901
+ roots: Array<{
902
+ kid: string;
903
+ public_key_pem: string;
904
+ }>;
905
+ authorities: Array<{
906
+ artifact_id: string;
907
+ issuer?: string;
908
+ actions: string[];
909
+ currency_policy: 'record' | 'record_or_statement';
910
+ in_force_seal_hash?: string;
911
+ }>;
912
+ local_facts?: string[];
913
+ max_window_seconds: number;
914
+ max_act_bytes?: number;
915
+ consent_suites?: string[];
916
+ valid_until?: string;
917
+ }
918
+ interface IssuerDocument {
919
+ nomos_document: 'issuer';
920
+ version: '1';
921
+ issuer_id: string;
922
+ authorities: Array<{
923
+ artifact_id: string;
924
+ version: string;
925
+ seal_hash: string;
926
+ artifact_url: string;
927
+ in_force_url?: string;
928
+ }>;
929
+ key_certs: KeyCertificate[];
930
+ witnesses?: string[];
931
+ approvals?: Array<{
932
+ role: string;
933
+ endpoint: string;
934
+ }>;
935
+ revocations_url?: string;
936
+ valid_until?: string;
937
+ }
938
+ interface WitnessDocument {
939
+ nomos_document: 'witness';
940
+ version: '1';
941
+ witness_id: string;
942
+ kid: string;
943
+ claims: string[];
944
+ statement_endpoint: string;
945
+ access?: string;
946
+ valid_until?: string;
947
+ }
948
+ declare const PATH: {
949
+ readonly 'relying-party': "/.well-known/nomos-relying-party";
950
+ readonly issuer: "/.well-known/nomos-issuer";
951
+ readonly witness: "/.well-known/nomos-witness";
952
+ };
953
+ type Kind = keyof typeof PATH;
954
+ type DocOf<K extends Kind> = K extends 'relying-party' ? RelyingPartyDocument : K extends 'issuer' ? IssuerDocument : WitnessDocument;
955
+ declare class NomosDiscoveryError extends Error {
956
+ readonly url: string;
957
+ constructor(message: string, url: string);
958
+ }
959
+ /** The origin of a URL or bare origin: `https://shop.example/anything` → `https://shop.example`. */
960
+ declare function originOf(to: string): string;
961
+ /** Fetches and checks one discovery document (§2 rule 4, §3). */
962
+ declare function fetchDocument<K extends Kind>(kind: K, origin: string, fetchImpl?: typeof fetch): Promise<DocOf<K>>;
963
+ declare const WELL_KNOWN: {
964
+ readonly 'relying-party': "/.well-known/nomos-relying-party";
965
+ readonly issuer: "/.well-known/nomos-issuer";
966
+ readonly witness: "/.well-known/nomos-witness";
967
+ };
968
+
969
+ /**
970
+ * accept() — the relying party: the system that makes the change.
971
+ *
972
+ * const rp = accept({ relyingPartyId, root, authorities, commit });
973
+ * app.use(rp.express()); // Express, Connect, node:http
974
+ * export default { fetch: rp.fetch }; // Hono, Next.js, Cloudflare, Deno, Bun
975
+ *
976
+ * For every Act it receives it runs NOMOS-SPEC-008 §6 with @nomosprotocol/verify, locally, and on
977
+ * AUTHORIZED applies §8 exactly, in one transaction: record the nonce, re-read its own facts
978
+ * (re-verifying if they moved), hand `commit` a copy of exactly the verified action, and store the
979
+ * receipt. It answers with the NOMOS-SPEC-009 §6.2 status codes and serves its own discovery
980
+ * document (§3.1), generated from this same configuration so the two can never disagree (§2).
981
+ */
982
+
983
+ interface AcceptedAuthority {
984
+ /** The sealed artifact's meta.artifact_id. */
985
+ artifactId: string;
986
+ /** Origin of the issuer document (NOMOS-SPEC-009 §3.2), advertised so carriers can find it. */
987
+ issuer?: string;
988
+ /** The action types this system commits under this authority. Anything else is refused. */
989
+ actions: string[];
990
+ /** SPEC-008 §5.5. `record` (RECOMMENDED) needs `inForceSealHash`. */
991
+ currencyPolicy: CurrencyPolicy;
992
+ /** Your record of the version in force: the seal hash of the version you accept. */
993
+ inForceSealHash?: string;
994
+ }
995
+ interface Receipt {
996
+ act_id: string;
997
+ act_digest: string;
998
+ decision: string;
999
+ rule: string | null;
1000
+ by_consent?: boolean;
1001
+ verified_at: string;
1002
+ committed_at?: string;
1003
+ relying_party_facts: Record<string, unknown>;
1004
+ in_force_source?: string;
1005
+ currency_policy: CurrencyPolicy;
1006
+ consent_origins?: string[];
1007
+ }
1008
+ /** One atomic operation (SPEC-008 §8). `tx` is passed to `commit` and `localFacts` so your own
1009
+ * writes and reads share it. */
1010
+ interface AcceptTransaction<Tx = unknown> {
1011
+ /** Records the nonce. false if it was already recorded (a concurrent duplicate). */
1012
+ claimNonce(nonce: string): Promise<boolean>;
1013
+ /** Stores the receipt, and the exact Act it verified (SPEC-008 §9: the receipt plus a retained
1014
+ * copy of the Act let a third party re-run the verification). */
1015
+ putReceipt(nonce: string, receipt: Receipt, act?: unknown): Promise<void>;
1016
+ tx: Tx;
1017
+ }
1018
+ interface AcceptStore<Tx = unknown> {
1019
+ hasNonce(nonce: string): Promise<boolean>;
1020
+ receiptFor(nonce: string): Promise<Receipt | null>;
1021
+ transaction<T>(fn: (t: AcceptTransaction<Tx>) => Promise<T>): Promise<T>;
1022
+ }
1023
+ interface AcceptOptions<Tx = unknown> {
1024
+ /** Your identifier. Acts addressed to anything else are refused (SPEC-008 §5.3). */
1025
+ relyingPartyId: string;
1026
+ /** The root you pin (PEM). There is no default root. */
1027
+ root: string;
1028
+ authorities: AcceptedAuthority[];
1029
+ /** Applies the change. Receives a deep copy of exactly the verified action, and nothing else
1030
+ * from the request (SPEC-009 §6.4). Its return value is sent back as `result`. */
1031
+ commit: (action: {
1032
+ type: string;
1033
+ subject?: string;
1034
+ params: Record<string, unknown>;
1035
+ }, ctx: {
1036
+ tx: Tx;
1037
+ actId: string;
1038
+ }) => Promise<unknown> | unknown;
1039
+ /** Facts you supply from your own state (inputs with source `relying_party`). Called once to
1040
+ * verify, and again inside the transaction to check nothing moved (SPEC-008 §8 step 3). */
1041
+ localFacts?: (act: any, tx?: Tx) => Promise<Record<string, unknown>> | Record<string, unknown>;
1042
+ /** Where nonces and receipts live. Defaults to memory, for development only. */
1043
+ store?: AcceptStore<Tx>;
1044
+ /** The absolute URL carriers POST Acts to, as advertised in your discovery document. */
1045
+ actEndpoint: string;
1046
+ /** SPEC-008 §5.1 / SPEC-009 §6.3. Long enough for a person to approve. Default 900. */
1047
+ maxWindowSeconds?: number;
1048
+ maxActBytes?: number;
1049
+ /** Current revocation state (SPEC-006, SPEC-007 §5), read once per Act. Use revocationSource()
1050
+ * for an issuer's published list. If it throws, the Act is refused with 503 and nothing is
1051
+ * committed: revocations that cannot be checked are never treated as "nothing revoked"
1052
+ * (SPEC-007 rev. 1.10 §5.6). */
1053
+ revocations?: () => Promise<{
1054
+ kids?: Set<string>;
1055
+ certs?: Set<string>;
1056
+ artifacts?: Set<string>;
1057
+ }> | {
1058
+ kids?: Set<string>;
1059
+ certs?: Set<string>;
1060
+ artifacts?: Set<string>;
1061
+ };
1062
+ /** `shadow`: verify and record every verdict, never commit. For pilots. */
1063
+ mode?: 'enforce' | 'shadow';
1064
+ /** Every verdict, committed or not (SPEC-008 §9: a receipt for every verification). */
1065
+ onVerdict?: (verdict: ActVerdict, receipt: Receipt) => void | Promise<void>;
1066
+ /** How long this document is valid for, in seconds. Default one day. */
1067
+ documentTtlSeconds?: number;
1068
+ now?: () => Date;
1069
+ }
1070
+ interface Answer {
1071
+ status: number;
1072
+ headers: Record<string, string>;
1073
+ body: Record<string, unknown>;
1074
+ }
1075
+ declare const statusFor: (decision: string) => number;
1076
+ declare const ACT_MEDIA_TYPE = "application/nomos-act+json";
1077
+ /** Nonces and receipts in memory, one transaction at a time. Lost on restart, single process:
1078
+ * for development and tests only. In production use postgresStore() or your own AcceptStore. */
1079
+ declare function memoryStore(): AcceptStore<null>;
1080
+ declare function accept<Tx = unknown>(o: AcceptOptions<Tx>): {
1081
+ handle: (req: {
1082
+ method?: string;
1083
+ headers: Record<string, string | string[] | undefined>;
1084
+ body: string | Uint8Array;
1085
+ }) => Promise<Answer>;
1086
+ document: () => RelyingPartyDocument;
1087
+ fetch: (request: Request) => Promise<Response>;
1088
+ express: () => (req: any, res: any, next?: () => void) => Promise<void>;
1089
+ node: () => (req: any, res: any, next?: () => void) => Promise<void>;
1090
+ };
1091
+
1092
+ /**
1093
+ * postgresStore() — the production store for accept(): nonces, receipts and the Acts themselves,
1094
+ * in your own Postgres, in the same transaction as your own change.
1095
+ *
1096
+ * import pg from 'pg';
1097
+ * const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
1098
+ * const store = postgresStore(pool);
1099
+ * await store.migrate(); // once; or apply store.schema yourself
1100
+ * accept({ ..., store, commit: async (action, { tx }) => tx.query('INSERT INTO orders …', […]) });
1101
+ *
1102
+ * What it guarantees (NOMOS-SPEC-008 §8, NOMOS-SPEC-009 §6.3–§6.4):
1103
+ * - One transaction. `commit` receives `tx`, the very client the nonce is recorded on, so your
1104
+ * change, the nonce and the receipt commit together or not at all.
1105
+ * - One commit per Act, under any concurrency. The nonce is the table's primary key; a second
1106
+ * submission of the same Act waits for the first transaction and then finds the nonce taken,
1107
+ * so it is answered REPLAYED with the first receipt. If the first rolled back, the second
1108
+ * commits instead: a nonce is recorded only when the change is.
1109
+ * - An audit trail. Each row keeps the receipt and the exact Act it verified, so a third party
1110
+ * can re-run SPEC-008 §6 later (SPEC-008 §9). Rows are never deleted by this store: how long
1111
+ * to retain them is your policy. They must outlive the Acts' validity windows at least, or a
1112
+ * replayed Act could commit twice.
1113
+ *
1114
+ * It depends on no driver: pass a `pg` Pool (node-postgres) or anything with the same two
1115
+ * methods, for example a pool adapter over postgres.js, Neon's serverless driver or PGlite.
1116
+ */
1117
+
1118
+ /** The part of a node-postgres client this store uses. */
1119
+ interface PgClient {
1120
+ query(text: string, values?: unknown[]): Promise<{
1121
+ rows: any[];
1122
+ rowCount: number | null;
1123
+ }>;
1124
+ }
1125
+ /** The part of a node-postgres Pool this store uses. */
1126
+ interface PgPool extends PgClient {
1127
+ connect(): Promise<PgClient & {
1128
+ release(err?: unknown): void;
1129
+ }>;
1130
+ }
1131
+ interface PostgresStoreOptions {
1132
+ /** Table name, optionally schema-qualified. Default `nomos_acts`. */
1133
+ table?: string;
1134
+ }
1135
+ declare function postgresStore(pool: PgPool, opts?: PostgresStoreOptions): AcceptStore<PgClient> & {
1136
+ schema: string;
1137
+ migrate(): Promise<void>;
1138
+ };
1139
+
1140
+ /**
1141
+ * Certificates and revocations, as the carrier and the relying party need them.
1142
+ *
1143
+ * presentedCertificates(available, act) NOMOS-SPEC-009 0.2.0 §6.5: exactly the certificates an Act presents
1144
+ * signRevocation(parent, target, reason) NOMOS-SPEC-007 rev. 1.10 §5.1: revoke a key or one certificate
1145
+ * signRevocationList(signer, …) rev. 1.10 §5.3: a list a relying party can check for itself
1146
+ * revocationSource({ url, root, … }) rev. 1.10 §5.3a, §5.6: current revocations for accept(), fail closed when stale
1147
+ */
1148
+
1149
+ declare const MAX_PRESENTED = 20;
1150
+ /** The kids an Act relies on: its seal's key, every witness's and every approver's. */
1151
+ declare function reliedKids(act: any): string[];
1152
+ /** NOMOS-SPEC-009 0.2.0 §6.5: the closure of `available` over the kids `act` relies on, each
1153
+ * certificate once. Deterministic, so two carriers with the same certificates present the same set. */
1154
+ declare function presentedCertificates(available: KeyCertificate$2[], act: any): KeyCertificate$2[];
1155
+ /** NOMOS-SPEC-007 rev. 1.10 §5.1: `parent` revokes a key it certified, or one certificate it issued. */
1156
+ declare function signRevocation(parent: Signer, target: {
1157
+ kid: string;
1158
+ } | {
1159
+ certificate: KeyCertificate$2;
1160
+ }, reason: string, issuedAt?: Date): Promise<RevocationStatement>;
1161
+ /** NOMOS-SPEC-007 rev. 1.10 §5.3: a signed, dated list. `keyCerts` should be the closure over
1162
+ * the signers and what they revoke (and the list signer), so any relying party can check it. */
1163
+ declare function signRevocationList(signer: Signer, statements: RevocationStatement[], keyCerts?: KeyCertificate$2[], generatedAt?: Date): Promise<RevocationList>;
1164
+ /** The certificates a revocation list should carry (rev. 1.10 §5.3): the closure over every
1165
+ * statement's signer and target, and the list's own signer, within the publisher's certificates. */
1166
+ declare function revocationListCertificates(available: KeyCertificate$2[], statements: RevocationStatement[], listSignerKid: string): KeyCertificate$2[];
1167
+ declare class RevocationUnavailable extends Error {
1168
+ readonly retryAfterSeconds: number;
1169
+ constructor(message: string, retryAfterSeconds: number);
1170
+ }
1171
+ interface RevocationSourceOptions {
1172
+ /** The issuer's revocation list (its NOMOS-SPEC-009 `revocations_url`). */
1173
+ url: string;
1174
+ /** The root you pin: statements count only from parents it reaches; the list's date only from a signer it reaches. */
1175
+ root: string;
1176
+ /** How old the newest current list may be before accept() refuses to commit (rev. 1.10 §5.6). Policy, not protocol. Default 3600. */
1177
+ maxAgeSeconds?: number;
1178
+ /** Your own certificates, for statements whose certificates the list does not carry. */
1179
+ ownCerts?: KeyCertificate$2[];
1180
+ /** How long to reuse a fetched list before fetching again. Default 60 s, as the reference deployment publishes. */
1181
+ refreshSeconds?: number;
1182
+ fetch?: typeof fetch;
1183
+ now?: () => Date;
1184
+ }
1185
+ /**
1186
+ * Current revocations from an issuer's list, for accept({ revocations }).
1187
+ *
1188
+ * Every counted statement is kept for good: a later fetch that fails, or a list that omits it,
1189
+ * never un-revokes a key (rev. 1.10 §5.6). When the newest list with an established `as_of` is
1190
+ * older than `maxAgeSeconds`, it throws RevocationUnavailable, and accept() refuses to commit
1191
+ * with 503 and Retry-After rather than acting as if nothing were revoked.
1192
+ */
1193
+ declare function revocationSource(o: RevocationSourceOptions): () => Promise<{
1194
+ kids: Set<string>;
1195
+ certs: Set<string>;
1196
+ }>;
1197
+
1198
+ /**
1199
+ * certificateRegistry() — an institution's certificates and revocations, managed rather than
1200
+ * minted in code.
1201
+ *
1202
+ * const registry = certificateRegistry({ root: ROOT_PUBLIC_PEM, store: postgresRegistryStore(pool) });
1203
+ * await registry.issue({ parent: rootSigner, child: finance, scope: 'claim:budget_remaining', days: 365 });
1204
+ * await registry.revokeKey({ parent: rootSigner, kid: lostPhone.kid, reason: 'Phone lost' });
1205
+ * issuer({ …, keyCerts: () => registry.pool(), revocations: () => registry.revocationList(listSigner) });
1206
+ * witness({ …, keyCerts: await registry.chainFor(finance.kid) });
1207
+ *
1208
+ * Everything it writes is exactly NOMOS-SPEC-007: certificates (§3), revocation statements and
1209
+ * lists (rev. 1.10 §5). It refuses, at issue time, what a relying party would refuse later: a
1210
+ * parent the root does not reach, a scope wider than the parent's, a suite the parent may not
1211
+ * sign under, a malformed scope. Nothing it publishes is trusted because the registry published
1212
+ * it: every relying party checks it again.
1213
+ */
1214
+
1215
+ /** Where a registry keeps its certificates and revocation statements. Append-only. */
1216
+ interface RegistryStore {
1217
+ certificates(): Promise<KeyCertificate$2[]>;
1218
+ addCertificate(c: KeyCertificate$2): Promise<void>;
1219
+ statements(): Promise<RevocationStatement[]>;
1220
+ addStatement(s: RevocationStatement): Promise<void>;
1221
+ }
1222
+ /** In memory, for tests and development. */
1223
+ declare function memoryRegistryStore(): RegistryStore;
1224
+ declare class RegistryError extends Error {
1225
+ readonly code: string;
1226
+ constructor(message: string, code: string);
1227
+ }
1228
+ interface IssueOptions {
1229
+ parent: Signer;
1230
+ child: {
1231
+ kid: string;
1232
+ publicKeyPem: string;
1233
+ };
1234
+ scope?: string;
1235
+ /** Validity: `expiresAt`, or `days` from now. */
1236
+ expiresAt?: Date;
1237
+ days?: number;
1238
+ issuedAt?: Date;
1239
+ }
1240
+ declare function certificateRegistry(o: {
1241
+ root: string;
1242
+ store: RegistryStore;
1243
+ now?: () => Date;
1244
+ }): {
1245
+ rootKid: string;
1246
+ pool: (filter?: (c: KeyCertificate$2) => boolean) => Promise<KeyCertificate$2[]>;
1247
+ /** NOMOS-SPEC-007 §3: certify `child` under `parent`. Refuses anything a verifier would refuse. */
1248
+ issue(io: IssueOptions): Promise<KeyCertificate$2>;
1249
+ /** rev. 1.10 §5.1: `parent` revokes a key it certified. The key is dead on every path. */
1250
+ revokeKey(io: {
1251
+ parent: Signer;
1252
+ kid: string;
1253
+ reason: string;
1254
+ }): Promise<RevocationStatement>;
1255
+ /** rev. 1.10 §5.1: withdraw one certificate; the key stays valid under any other. */
1256
+ revokeCertificate(io: {
1257
+ parent: Signer;
1258
+ fingerprint: string;
1259
+ reason: string;
1260
+ }): Promise<RevocationStatement>;
1261
+ /** The certificates that connect `kid` to the root: what a witness or approver returns with
1262
+ * what it signs (SPEC-009 0.2.0 §4, §5). */
1263
+ chainFor(kid: string): Promise<KeyCertificate$2[]>;
1264
+ /** How `kid` is reached from the root, and with which effective scopes, or why it is not. */
1265
+ check(kid: string): Promise<{
1266
+ ok: true;
1267
+ scopes: ScopeTerms[];
1268
+ } | {
1269
+ ok: false;
1270
+ reason: string;
1271
+ }>;
1272
+ certificates: () => Promise<KeyCertificate$2[]>;
1273
+ statements: () => Promise<RevocationStatement[]>;
1274
+ /** rev. 1.10 §5.3: the signed list, carrying the certificates that make it checkable. The
1275
+ * signer should be reached from the root, or the list establishes no date (§5.3). */
1276
+ revocationList(signer: Signer): Promise<RevocationList>;
1277
+ };
1278
+ type CertificateRegistry = ReturnType<typeof certificateRegistry>;
1279
+ /** The registry in your own Postgres (two append-only tables), for an issuer that runs on more
1280
+ * than one instance. Same structural pool as postgresStore(). */
1281
+ declare function postgresRegistryStore(pool: {
1282
+ query(text: string, values?: unknown[]): Promise<{
1283
+ rows: any[];
1284
+ }>;
1285
+ }, opts?: {
1286
+ prefix?: string;
1287
+ }): RegistryStore & {
1288
+ schema: string;
1289
+ migrate(): Promise<void>;
1290
+ };
1291
+
1292
+ /** A registration's authenticator data, and the passkey's public key as canonical SPKI PEM. */
1293
+ declare function readAttestation(attestationObject: Uint8Array): {
1294
+ authData: Uint8Array;
1295
+ flags: number;
1296
+ credentialId: Uint8Array;
1297
+ publicKeyPem: string;
1298
+ };
1299
+ interface EnrolmentClaims {
1300
+ approver: string;
1301
+ roles: string[];
1302
+ origin: string;
1303
+ expires_at: string;
1304
+ nonce: string;
1305
+ }
1306
+ /** Sign a single-use enrolment link for one person (`nomos enroll` does this). */
1307
+ declare function signEnrolmentToken(authority: Signer, c: {
1308
+ approver: string;
1309
+ roles: string[];
1310
+ origin: string;
1311
+ expiresAt: Date;
1312
+ }): Promise<string>;
1313
+ /** The claims of a valid, unexpired link for this origin, or the reason it is not one. */
1314
+ declare function verifyEnrolmentToken(token: string, authorityPem: string, origin: string, now: Date): EnrolmentClaims | {
1315
+ error: string;
1316
+ };
1317
+ interface PasskeyCredential {
1318
+ credential_id: string;
1319
+ approver: string;
1320
+ roles: string[];
1321
+ kid: string;
1322
+ public_key_pem: string;
1323
+ label: string;
1324
+ created_at: string;
1325
+ }
1326
+ interface PendingApproval {
1327
+ id: string;
1328
+ role: string;
1329
+ act: any;
1330
+ status: 'pending' | 'approved' | 'refused';
1331
+ created_at: string;
1332
+ /** Every ceremony offered, by its challenge: the consent fields fixed before the person was
1333
+ * asked (§4.5). Append-only, so asking again never invalidates a ceremony already in flight. */
1334
+ attempts: Record<string, Attempt>;
1335
+ consent?: any;
1336
+ key_certs?: KeyCertificate[];
1337
+ }
1338
+ interface Attempt {
1339
+ credential_id: string;
1340
+ signed_at: string;
1341
+ expires_at: string;
1342
+ }
1343
+ interface PasskeyStore {
1344
+ /** Marks an enrolment link used. false if it already was: a link works once. */
1345
+ claimToken(nonce: string): Promise<boolean>;
1346
+ tokenUsed(nonce: string): Promise<boolean>;
1347
+ saveEnrolmentChallenge(nonce: string, challenge: string): Promise<void>;
1348
+ enrolmentChallenge(nonce: string): Promise<string | null>;
1349
+ addCredential(c: PasskeyCredential): Promise<void>;
1350
+ credentials(): Promise<PasskeyCredential[]>;
1351
+ /** A new request. */
1352
+ createPending(p: PendingApproval): Promise<void>;
1353
+ pending(id: string): Promise<PendingApproval | null>;
1354
+ /** Adds one ceremony, only while the request is pending. false otherwise. */
1355
+ addAttempt(id: string, challenge: string, a: Attempt): Promise<boolean>;
1356
+ /** pending → approved or refused, exactly once: false if the request was no longer pending.
1357
+ * The only transition out of pending, so no stale write can undo an approval. */
1358
+ resolvePending(id: string, outcome: {
1359
+ status: 'approved';
1360
+ consent: any;
1361
+ key_certs: KeyCertificate[];
1362
+ } | {
1363
+ status: 'refused';
1364
+ }): Promise<boolean>;
1365
+ }
1366
+ declare function memoryPasskeyStore(): PasskeyStore;
1367
+ /** The same store in Postgres, for an approval service on more than one instance. */
1368
+ declare function postgresPasskeyStore(pool: {
1369
+ query(text: string, values?: unknown[]): Promise<{
1370
+ rows: any[];
1371
+ rowCount: number | null;
1372
+ }>;
1373
+ }, opts?: {
1374
+ prefix?: string;
1375
+ }): PasskeyStore & {
1376
+ schema: string;
1377
+ migrate(): Promise<void>;
1378
+ };
1379
+ interface PasskeyApproverOptions {
1380
+ origin: string;
1381
+ roles: string[];
1382
+ registry: CertificateRegistry;
1383
+ /** Certifies passkeys. Certified with `consent:<the roles it may enrol>` and no `approver` term. */
1384
+ enroller: Signer;
1385
+ /** The public key whose signed enrolment links this service honours (an administrator's). */
1386
+ enrolmentAuthority: string;
1387
+ store?: PasskeyStore;
1388
+ /** WebAuthn relying-party id. Default: the origin's hostname. */
1389
+ rpId?: string;
1390
+ rpName?: string;
1391
+ /** How long a passkey's certificate is valid. Default 365 days. */
1392
+ certificateDays?: number;
1393
+ /** List the people who may approve, by name and device, on the approval page. Default false: the
1394
+ * approval link goes to the carrier, which is not trusted with your roster, so the person types
1395
+ * their approver id and is shown only their own devices. */
1396
+ listApprovers?: boolean;
1397
+ /** Called for every new request, e.g. to notify the people who can approve it (email, chat). */
1398
+ onPending?: (request: {
1399
+ id: string;
1400
+ role: string;
1401
+ act: any;
1402
+ approvalUrl: string;
1403
+ }) => void | Promise<void>;
1404
+ now?: () => Date;
1405
+ }
1406
+ declare function passkeyApprover(o: PasskeyApproverOptions): {
1407
+ store: PasskeyStore;
1408
+ fetch: (request: Request) => Promise<Response>;
1409
+ express: () => (req: any, res: any, next?: () => void) => Promise<any>;
1410
+ node: () => (req: any, res: any, next?: () => void) => Promise<any>;
1411
+ };
1412
+
1413
+ type ActStatus = 'committed' | 'escalated' | 'incomplete' | 'denied' | 'refused' | 'replayed';
1414
+ interface ActResult {
1415
+ status: ActStatus;
1416
+ /** The relying party's verdict, exactly as it returned it (SPEC-009 §6.2). */
1417
+ verdict: Record<string, any>;
1418
+ /** When committed: the receipt, and what the relying party's commit returned. */
1419
+ receipt?: Record<string, any>;
1420
+ result?: unknown;
1421
+ /** When incomplete: the facts that could still change the outcome, and why each is missing. */
1422
+ missing?: Array<{
1423
+ fact: string;
1424
+ source: string | null;
1425
+ why: string;
1426
+ }>;
1427
+ /** When escalated and not approved in time: where a person can approve. */
1428
+ approvalUrl?: string;
1429
+ /** The Act as submitted, for your records. */
1430
+ act: any;
1431
+ /** What happened, in one sentence. */
1432
+ summary: string;
1433
+ }
1434
+ interface ActOptions {
1435
+ /** The relying party: its origin or any URL on it. */
1436
+ to: string;
1437
+ action: Action;
1438
+ /** Which authority to act under, when the relying party accepts several for this action type. */
1439
+ authority?: string;
1440
+ /** Facts the carrier supplies itself (inputs whose declared source is `presenter`). */
1441
+ presenterFacts?: Record<string, unknown>;
1442
+ /** Credentials for witnesses that need them: origin → headers (SPEC-009 §3.3 `access`). */
1443
+ witnessHeaders?: Record<string, Record<string, string>>;
1444
+ /** Wait up to this long for a person to approve, in ms. Default: until the Act expires. */
1445
+ approvalTimeoutMs?: number;
1446
+ /** Called once per pending approval with the page a person can approve on. */
1447
+ onApproval?: (approval: {
1448
+ role: string;
1449
+ url?: string;
1450
+ actDigest: string;
1451
+ }) => void;
1452
+ /** Use a specific fetch (tests, proxies). */
1453
+ fetch?: typeof fetch;
1454
+ /** Poll interval for pending approvals, ms. Default 1000. */
1455
+ pollMs?: number;
1456
+ }
1457
+ declare class NomosActError extends Error {
1458
+ constructor(message: string);
1459
+ }
1460
+ declare function act(o: ActOptions): Promise<ActResult>;
1461
+
1462
+ interface IssuerOptions {
1463
+ /** Your public origin, e.g. https://policy.acme.example */
1464
+ origin: string;
1465
+ issuerId: string;
1466
+ /** The key that sealed the authorities; it also signs in-force statements (SPEC-008 §5.4). */
1467
+ signer: Signer;
1468
+ /** Sealed artifacts, each the version currently in force. */
1469
+ authorities: any[];
1470
+ /** The pool carriers select from (SPEC-009 0.2.0 §3.2, §6.5): at least the certificates for your
1471
+ * sealing keys. May hold more than 20. A function is read on every request, so a certificate
1472
+ * registry can change it without a restart. */
1473
+ keyCerts: KeyCertificate[] | (() => KeyCertificate[] | Promise<KeyCertificate[]>);
1474
+ /** Your signed revocation list (SPEC-007 rev. 1.10 §5.3), served at /nomos/revocations and
1475
+ * advertised as revocations_url. */
1476
+ revocations?: () => RevocationList | Promise<RevocationList>;
1477
+ witnesses?: string[];
1478
+ approvals?: Array<{
1479
+ role: string;
1480
+ endpoint: string;
1481
+ }>;
1482
+ revocationsUrl?: string;
1483
+ }
1484
+ declare function issuer(o: IssuerOptions): {
1485
+ fetch: (request: Request) => Promise<Response>;
1486
+ express: () => (req: any, res: any, next?: () => void) => Promise<any>;
1487
+ node: () => (req: any, res: any, next?: () => void) => Promise<any>;
1488
+ document: () => IssuerDocument;
1489
+ resolveDocument: () => Promise<IssuerDocument>;
1490
+ };
1491
+ interface WitnessOptions {
1492
+ origin: string;
1493
+ witnessId: string;
1494
+ /** A key certified for exactly these claims (SPEC-007 rev. 1.8 §3.4.1). */
1495
+ signer: Signer;
1496
+ /** Each claim this witness states, and how to read its current value for a subject. Return
1497
+ * undefined when the subject is unknown. */
1498
+ claims: Record<string, (about: string | null) => unknown | Promise<unknown>>;
1499
+ /** How long a statement stays true, at most, in seconds. Default 900. */
1500
+ maxValiditySeconds?: number;
1501
+ /** Your access control (SPEC-009 §3.3): return false to refuse a requester. */
1502
+ authorize?: (request: {
1503
+ claim: string;
1504
+ about: string | null;
1505
+ }) => boolean | Promise<boolean>;
1506
+ /** The certificates connecting your key toward the roots, returned with every statement
1507
+ * (SPEC-009 0.2.0 §4) so the issuer document need not list them. */
1508
+ keyCerts?: KeyCertificate[];
1509
+ access?: string;
1510
+ }
1511
+ declare function witness(o: WitnessOptions): {
1512
+ fetch: (request: Request) => Promise<Response>;
1513
+ express: () => (req: any, res: any, next?: () => void) => Promise<any>;
1514
+ node: () => (req: any, res: any, next?: () => void) => Promise<any>;
1515
+ document: () => WitnessDocument;
1516
+ };
1517
+ interface ApproverOptions {
1518
+ origin: string;
1519
+ /** The person's key, certified with `consent:<role> approver:<their id>` (SPEC-007 rev. 1.9 §3.7). */
1520
+ signer: Signer;
1521
+ roles: string[];
1522
+ /** The certificates connecting the person's key toward the roots, returned with every consent
1523
+ * (SPEC-009 0.2.0 §5) so the issuer document need not list every approver. */
1524
+ keyCerts?: KeyCertificate[];
1525
+ /** 'page' (default): a person approves on a page this handler serves. 'auto': approve every
1526
+ * request at once — development only. Or a function that decides. */
1527
+ decide?: 'page' | 'auto' | ((request: {
1528
+ role: string;
1529
+ act: any;
1530
+ }) => boolean | Promise<boolean>);
1531
+ }
1532
+ interface Pending {
1533
+ role: string;
1534
+ act: any;
1535
+ status: 'pending' | 'approved' | 'refused' | 'expired';
1536
+ consent?: any;
1537
+ }
1538
+ declare function approver(o: ApproverOptions): {
1539
+ fetch: (request: Request) => Promise<Response>;
1540
+ express: () => (req: any, res: any, next?: () => void) => Promise<any>;
1541
+ node: () => (req: any, res: any, next?: () => void) => Promise<any>;
1542
+ pending: Map<string, Pending>;
1543
+ };
1544
+
1545
+ 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 CertificateRegistry, type ChainVerdictDecision, type ConservedStateInfo, type ConservedStateReceipt, type Contradiction, type DetectContradictionsParams, type DetectContradictionsResult, type EnrolmentClaims, type GenerateGovernanceParams, type GenerateGovernanceResult, type IssueOptions, type IssuerDocument, type IssuerOptions, type KeyCertificate$1 as KeyCertificate, type ListArtifactsParams, MAX_PRESENTED, 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 PasskeyApproverOptions, type PasskeyCredential, type PasskeyStore, type PendingApproval, type PgClient, type PgPool, type PostgresStoreOptions, type Receipt, RegistryError, type RegistryStore, type RelyingPartyDocument, type RequestOptions, type Reservation, type ReserveByActParams, type ReserveByQueryParams, type ReserveParams, type RevocationSourceOptions, RevocationUnavailable, 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, certificateRegistry, certify, fetchDocument, generateSigner, issuer, kidOf, localSigner, memoryPasskeyStore, memoryRegistryStore, memoryStore, nomos, originOf, passkeyApprover, postgresPasskeyStore, postgresRegistryStore, postgresStore, presentedCertificates, readAttestation, reliedKids, revocationListCertificates, revocationSource, seal, seededSigner, signConsent, signEnrolmentToken, signInForce, signRevocation, signRevocationList, signTestimony, statusFor, verifyChain, verifyEnrolmentToken, witness };