@agent-score/commerce 2.4.0 → 2.5.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.
Files changed (59) hide show
  1. package/dist/challenge/index.d.mts +5 -1
  2. package/dist/challenge/index.d.ts +5 -1
  3. package/dist/challenge/index.js +11 -4
  4. package/dist/challenge/index.js.map +1 -1
  5. package/dist/challenge/index.mjs +11 -4
  6. package/dist/challenge/index.mjs.map +1 -1
  7. package/dist/{checkout-B-MIzYzW.d.ts → checkout-McfNpZJf.d.ts} +72 -1
  8. package/dist/{checkout-Bn7ZKIBD.d.mts → checkout-o17dIxHi.d.mts} +72 -1
  9. package/dist/core.d.mts +23 -1
  10. package/dist/core.d.ts +23 -1
  11. package/dist/core.js +25 -11
  12. package/dist/core.js.map +1 -1
  13. package/dist/core.mjs +25 -11
  14. package/dist/core.mjs.map +1 -1
  15. package/dist/discovery/index.d.mts +17 -2
  16. package/dist/discovery/index.d.ts +17 -2
  17. package/dist/discovery/index.js +14 -4
  18. package/dist/discovery/index.js.map +1 -1
  19. package/dist/discovery/index.mjs +14 -4
  20. package/dist/discovery/index.mjs.map +1 -1
  21. package/dist/gate-CWP10xPQ.d.mts +339 -0
  22. package/dist/gate-CWP10xPQ.d.ts +339 -0
  23. package/dist/identity/express.d.mts +26 -1
  24. package/dist/identity/express.d.ts +26 -1
  25. package/dist/identity/express.js +587 -13
  26. package/dist/identity/express.js.map +1 -1
  27. package/dist/identity/express.mjs +583 -12
  28. package/dist/identity/express.mjs.map +1 -1
  29. package/dist/identity/fastify.d.mts +12 -2
  30. package/dist/identity/fastify.d.ts +12 -2
  31. package/dist/identity/fastify.js +595 -13
  32. package/dist/identity/fastify.js.map +1 -1
  33. package/dist/identity/fastify.mjs +591 -12
  34. package/dist/identity/fastify.mjs.map +1 -1
  35. package/dist/identity/hono.d.mts +26 -1
  36. package/dist/identity/hono.d.ts +26 -1
  37. package/dist/identity/hono.js +576 -13
  38. package/dist/identity/hono.js.map +1 -1
  39. package/dist/identity/hono.mjs +572 -12
  40. package/dist/identity/hono.mjs.map +1 -1
  41. package/dist/identity/nextjs.d.mts +3 -0
  42. package/dist/identity/nextjs.d.ts +3 -0
  43. package/dist/identity/nextjs.js +581 -13
  44. package/dist/identity/nextjs.js.map +1 -1
  45. package/dist/identity/nextjs.mjs +577 -12
  46. package/dist/identity/nextjs.mjs.map +1 -1
  47. package/dist/identity/web.d.mts +24 -1
  48. package/dist/identity/web.d.ts +24 -1
  49. package/dist/identity/web.js +581 -13
  50. package/dist/identity/web.js.map +1 -1
  51. package/dist/identity/web.mjs +577 -12
  52. package/dist/identity/web.mjs.map +1 -1
  53. package/dist/index.d.mts +119 -3
  54. package/dist/index.d.ts +119 -3
  55. package/dist/index.js +893 -35
  56. package/dist/index.js.map +1 -1
  57. package/dist/index.mjs +873 -35
  58. package/dist/index.mjs.map +1 -1
  59. package/package.json +11 -11
@@ -0,0 +1,339 @@
1
+ import { JWK } from 'jose';
2
+
3
+ /**
4
+ * AIP (Agentic Identity Protocol) token types and the claim contract.
5
+ *
6
+ * An Agent Identity Token (AIT) is a JWT signed by an Identity Provider (IdP). It binds a
7
+ * verified human's identity to the specific agent presenting it (via `cnf`, RFC 7800) and
8
+ * carries the trust level, authentication method, optional intent, and optional identity
9
+ * claims the IdP attests to.
10
+ *
11
+ * This module is the single source of truth for the claim shape on the verifier side. It
12
+ * encodes the spec's required / recommended / optional claims plus the AgentScore extension
13
+ * claims (sanctions, jurisdiction, structured id-verification, cross-merchant graph, payment
14
+ * signer) we carry when we act as a compliance IdP.
15
+ *
16
+ * Extensibility contract (per spec): the `identity` object is open. If a claim is present,
17
+ * the IdP attests to it; verifiers ignore claims they don't recognize. Absence is the
18
+ * "unknown" signal — IdPs do not ship `null` for "not checked".
19
+ */
20
+
21
+ /** Degree of human involvement in issuing this specific AIT. */
22
+ type TrustLevel = 'autonomous' | 'human_present' | 'human_confirmed';
23
+ /**
24
+ * Authentication Method Reference values (RFC 8176 / IANA AMR registry). Open set — these
25
+ * are the values relevant to agent identity; others are valid and pass through.
26
+ */
27
+ type AmrValue = 'face' | 'fpt' | 'hwk' | 'otp' | 'pin' | 'pwd' | 'sms' | 'swk' | 'user' | 'mfa';
28
+ /** RFC 7800 confirmation claim: binds the AIT to the agent's signing key. */
29
+ interface CnfClaim {
30
+ jwk: JWK;
31
+ }
32
+ /** Agent metadata. `provider` is required; `instance` is recommended. */
33
+ interface AgentClaim {
34
+ provider: string;
35
+ instance?: string;
36
+ }
37
+ /** How the user authorized THIS AIT (not prior authentication history). */
38
+ interface AuthClaim {
39
+ amr?: AmrValue[] | string[];
40
+ /** When the user authenticated for this token (Unix seconds). Mirrors OIDC `auth_time`. */
41
+ time?: number;
42
+ }
43
+ /** What the agent intends to do. Optional; verifiers may require it for non-read actions. */
44
+ interface IntentClaim {
45
+ actions?: string[];
46
+ description?: string;
47
+ }
48
+ /** AgentScore wallet-binding extension (orthogonal to `cnf`, which binds the agent key). */
49
+ interface PaymentSignerClaim {
50
+ address: string;
51
+ network: 'evm' | 'solana';
52
+ /** Relationship the IdP attests between signer and the operator graph. */
53
+ match?: 'linked_operator' | 'claimed_operator';
54
+ }
55
+ interface PaymentClaim {
56
+ signer?: PaymentSignerClaim;
57
+ }
58
+ /**
59
+ * Identity claims (presence == IdP attestation). Spec-defined fields plus AgentScore
60
+ * compliance extension claims. Open by contract — unknown fields are allowed and ignored.
61
+ */
62
+ interface IdentityClaim {
63
+ email?: string;
64
+ email_verified?: boolean;
65
+ name?: string;
66
+ phone?: string;
67
+ phone_verified?: boolean;
68
+ age_over_18?: boolean;
69
+ age_over_21?: boolean;
70
+ id_verified?: boolean;
71
+ id_verification?: {
72
+ provider?: string;
73
+ method?: string;
74
+ document_type?: string;
75
+ verified_at?: number;
76
+ };
77
+ /** ISO 3166-1 alpha-2, optionally with ISO 3166-2 subdivision (e.g. "US-CA"). */
78
+ jurisdiction?: string;
79
+ sanctions_clear?: boolean;
80
+ sanctions_checked_at?: number;
81
+ sanctions_providers?: string[];
82
+ linked_wallets?: Array<{
83
+ address: string;
84
+ network: 'evm' | 'solana';
85
+ }>;
86
+ merchants_paid?: number;
87
+ first_seen?: number;
88
+ [claim: string]: unknown;
89
+ }
90
+ /** The decoded AIT JWT payload. */
91
+ interface AitPayload {
92
+ aip_version: string;
93
+ iss: string;
94
+ sub: string;
95
+ iat: number;
96
+ exp: number;
97
+ cnf: CnfClaim;
98
+ agent: AgentClaim;
99
+ trust_level?: TrustLevel;
100
+ auth?: AuthClaim;
101
+ intent?: IntentClaim;
102
+ identity?: IdentityClaim;
103
+ payment?: PaymentClaim;
104
+ [claim: string]: unknown;
105
+ }
106
+ /** The decoded AIT JWT header. */
107
+ interface AitHeader {
108
+ alg: string;
109
+ typ?: string;
110
+ kid?: string;
111
+ [param: string]: unknown;
112
+ }
113
+ /**
114
+ * Structural validation of a decoded AIT payload. Confirms the required claims are present
115
+ * and well-typed, and enforces the one normative conditional in the spec: a
116
+ * `human_confirmed` token MUST carry at least one `auth.amr` value.
117
+ *
118
+ * This is shape/contract validation only — it does NOT verify signatures (that's the
119
+ * verifier pipeline) and does NOT apply trust policy (that's the gate / `/v1/assess`).
120
+ */
121
+ type AitValidationResult = {
122
+ ok: true;
123
+ payload: AitPayload;
124
+ } | {
125
+ ok: false;
126
+ reason: AitValidationFailure;
127
+ };
128
+ type AitValidationFailure = 'not_an_object' | 'missing_aip_version' | 'missing_iss' | 'missing_sub' | 'missing_iat' | 'missing_exp' | 'missing_cnf' | 'missing_agent_provider' | 'human_confirmed_without_amr';
129
+ /**
130
+ * Detect whether a decoded JWT payload is an AIT: per spec, an AIT is discriminated by the
131
+ * presence of `cnf` + `agent` claims (not the `typ` header).
132
+ */
133
+ declare const isAitShape: (payload: unknown) => boolean;
134
+ /** Validate the structural contract of a decoded AIT payload. */
135
+ declare const validateAitPayload: (payload: unknown) => AitValidationResult;
136
+
137
+ /**
138
+ * AIP IdP key discovery: fetch, cache, and select JWKS signing keys.
139
+ *
140
+ * Verifiers resolve an IdP's public keys from `https://{iss}/.well-known/agent-identity/jwks.json`
141
+ * (the spec's well-known path). This module owns:
142
+ *
143
+ * - **Trusted-issuer enforcement** — only `iss` values on the allowlist are fetched, compared
144
+ * after URL canonicalization (lowercase scheme+host, no default port, no trailing slash) so
145
+ * `https://issuer.example` and `https://issuer.example/` match.
146
+ * - **HTTPS-only** — JWKS over plain HTTP is MITM-vulnerable; we refuse it.
147
+ * - **Caching with a HARD cap** — we honor `Cache-Control: max-age` as advisory but never
148
+ * cache longer than {@link HARD_MAX_CACHE_SECONDS}, regardless of what the IdP sends. A
149
+ * compromised IdP can't pin stale keys with `max-age=31536000`.
150
+ * - **kid-miss refresh** — a lookup for a `kid` not in the cached set triggers one refetch
151
+ * (rotation may have published a new key inside the cache window).
152
+ * - **use:"sig" filtering** — only signing keys are returned.
153
+ *
154
+ * Pure-ish: the only I/O is `fetch`, injectable for tests.
155
+ */
156
+
157
+ /** The spec's well-known JWKS path, relative to the issuer origin. */
158
+ declare const JWKS_WELL_KNOWN_PATH = "/.well-known/agent-identity/jwks.json";
159
+ /** Hard ceiling on cache age, regardless of IdP-supplied Cache-Control. */
160
+ declare const HARD_MAX_CACHE_SECONDS = 86400;
161
+ type FetchLike = (url: string, init?: {
162
+ headers?: Record<string, string>;
163
+ }) => Promise<{
164
+ ok: boolean;
165
+ status: number;
166
+ headers: {
167
+ get(name: string): string | null;
168
+ };
169
+ json(): Promise<unknown>;
170
+ }>;
171
+ /** AgentScore's own AIT issuer. ALWAYS trusted by every {@link JwksCache} (and therefore every
172
+ * gate/adapter built on it) without the merchant listing it — this SDK is the AgentScore
173
+ * verifier, so a merchant can't accidentally fail to trust AgentScore-issued AITs. `trustedIssuers`
174
+ * only needs to name ADDITIONAL external issuers. */
175
+ declare const AGENTSCORE_CANONICAL_ISSUER = "https://agentscore.sh";
176
+ interface JwksCacheOptions {
177
+ /** ADDITIONAL external issuer URLs to trust beyond AgentScore's own (compared after
178
+ * canonicalization). AgentScore's canonical issuer is always trusted; omit/empty to accept
179
+ * only AgentScore-issued AITs. */
180
+ trustedIssuers?: string[];
181
+ /** Injectable fetch (defaults to global fetch). */
182
+ fetchImpl?: FetchLike;
183
+ /** Injectable clock (ms), for tests. */
184
+ now?: () => number;
185
+ /** User-Agent for JWKS requests. */
186
+ userAgent?: string;
187
+ }
188
+ type JwksLookupFailure = 'untrusted_issuer' | 'insecure_issuer' | 'fetch_failed' | 'malformed_jwks' | 'key_not_found';
189
+ type JwksLookupResult = {
190
+ ok: true;
191
+ key: JWK;
192
+ } | {
193
+ ok: false;
194
+ reason: JwksLookupFailure;
195
+ };
196
+ /**
197
+ * Canonicalize an issuer URL for trust-list comparison: lowercase scheme + host, drop the
198
+ * default port for the scheme, strip a trailing slash on an empty path. Returns null if the
199
+ * input is not a parseable absolute URL.
200
+ */
201
+ declare const canonicalizeIssuer: (iss: string) => string | null;
202
+ /**
203
+ * JWKS resolver bound to a trusted-issuer allowlist. One instance can serve many issuers;
204
+ * each issuer's key set is cached independently.
205
+ */
206
+ declare class JwksCache {
207
+ private readonly trusted;
208
+ private readonly fetchImpl;
209
+ private readonly now;
210
+ private readonly userAgent;
211
+ private readonly cache;
212
+ constructor(opts: JwksCacheOptions);
213
+ /** Is this issuer on the canonicalized trust list? */
214
+ isTrusted(iss: string): boolean;
215
+ /**
216
+ * Resolve the signing key for `(iss, kid)`. Enforces trust + HTTPS, serves from cache when
217
+ * fresh, and refetches once on a kid-miss before giving up.
218
+ */
219
+ getKey(iss: string, kid: string | undefined): Promise<JwksLookupResult>;
220
+ private select;
221
+ private refresh;
222
+ }
223
+
224
+ /**
225
+ * AIP Agent Identity Token (AIT) verification pipeline — the verifier orchestrator.
226
+ *
227
+ * This is the function a merchant gate calls. It executes the spec's verification steps over
228
+ * a presented request, composing the three foundation modules:
229
+ * - {@link ./jwks} — trusted-issuer enforcement + key discovery
230
+ * - {@link ./http-signature} — RFC 9421 proof-of-possession over the request
231
+ * - {@link ./types} — AIT structural contract
232
+ *
233
+ * Steps (per spec):
234
+ * 1. read the `Agent-Identity` header (one or more)
235
+ * 2. decode the JWT header (`kid`) + payload; confirm AIT shape (`cnf` + `agent`)
236
+ * 3. resolve the IdP's signing key from its JWKS (trusted-issuer + HTTPS enforced)
237
+ * 4. verify the IdP signature on the JWT (reject `alg:none`; key is Ed25519)
238
+ * 5. check `exp` / `iat` with skew
239
+ * 6. extract `cnf.jwk`
240
+ * 7. verify the RFC 9421 HTTP Message Signature with `cnf.jwk`
241
+ * 8. confirm the signature `keyid` == JWK thumbprint of `cnf.jwk` (done inside step 7)
242
+ *
243
+ * On success it returns the validated, signature-checked claims. On failure it returns a
244
+ * typed reason that maps onto AIP's wire error codes (the gate turns these into 401/403).
245
+ */
246
+
247
+ /** Header that carries the AIT JWT. */
248
+ declare const AGENT_IDENTITY_HEADER = "agent-identity";
249
+ /** Request fields the verifier needs. Framework-agnostic; adapters map their req onto this. */
250
+ interface VerifyRequestContext {
251
+ method: string;
252
+ authority: string;
253
+ path: string;
254
+ /** All `Agent-Identity` header values present on the request (one per IdP). */
255
+ agentIdentityHeaders: string[];
256
+ signatureInput: string | null;
257
+ signature: string | null;
258
+ }
259
+ interface VerifyAitOptions {
260
+ jwks: JwksCache;
261
+ now?: number;
262
+ maxSkewSeconds?: number;
263
+ }
264
+ /**
265
+ * Failure reasons, aligned with AIP wire error codes. The gate maps:
266
+ * no_token / malformed_token / invalid_signature / expired_token → 401
267
+ * untrusted_issuer / weak_auth / invalid_claims → 403
268
+ */
269
+ type VerifyAitFailure = 'no_token' | 'malformed_token' | 'untrusted_issuer' | 'key_unavailable' | 'idp_signature_invalid' | 'expired_token' | 'invalid_claims' | 'pop_signature_missing' | 'pop_signature_invalid';
270
+ interface VerifiedAit {
271
+ payload: AitPayload;
272
+ /** The issuer (canonical, as presented). */
273
+ iss: string;
274
+ /** The agent's bound public key (`cnf.jwk`). */
275
+ cnfJwk: AitPayload['cnf']['jwk'];
276
+ /** The raw JWT string that verified (the winning `Agent-Identity` header value, Bearer
277
+ * prefix stripped). Lets a gate forward the exact token to `/v1/assess` as `aip_token`. */
278
+ token: string;
279
+ }
280
+ type VerifyAitResult = {
281
+ ok: true;
282
+ ait: VerifiedAit;
283
+ } | {
284
+ ok: false;
285
+ reason: VerifyAitFailure;
286
+ };
287
+ /**
288
+ * Verify the AIP credential on a request. When multiple `Agent-Identity` headers are present,
289
+ * each is tried; the first that fully verifies AND whose `cnf.jwk` matches the request's
290
+ * RFC 9421 signature wins (all AITs on one request must share the same `cnf` key, so the PoP
291
+ * signature is checked once against the winning key).
292
+ */
293
+ declare const verifyAit: (ctx: VerifyRequestContext, opts: VerifyAitOptions) => Promise<VerifyAitResult>;
294
+
295
+ /**
296
+ * Framework-agnostic AIP gate orchestration.
297
+ *
298
+ * `verifyAitRequest` is the one call a framework adapter makes: hand it a standard `Request`
299
+ * plus a {@link JwksCache}, and it returns the verified AIT claims or a typed failure. The
300
+ * helpers here also map that failure onto the AIP wire contract — HTTP status + error code +
301
+ * an RFC 9457 problem-details body — so every adapter renders denials identically.
302
+ *
303
+ * This layer does identity *verification* only (is this a real, key-bound AIT from a trusted
304
+ * IdP?). Policy enrichment — sanctions, jurisdiction, cross-merchant graph — happens when the
305
+ * merchant additionally feeds the verified claims to `/v1/assess`; that's the gate's choice,
306
+ * not something this module forces.
307
+ */
308
+
309
+ interface AipGateOptions {
310
+ jwks: JwksCache;
311
+ now?: number;
312
+ maxSkewSeconds?: number;
313
+ }
314
+ type AipGateResult = {
315
+ ok: true;
316
+ ait: VerifiedAit;
317
+ } | {
318
+ ok: false;
319
+ failure: VerifyAitFailure;
320
+ };
321
+ /** Verify the AIP credential on a standard Fetch `Request` (Hono / Web / Next.js). */
322
+ declare const verifyAitRequest: (req: Request, opts: AipGateOptions) => Promise<AipGateResult>;
323
+ /** Map an internal verify failure to the AIP wire error code (per spec error taxonomy). */
324
+ declare const aipErrorCode: (failure: VerifyAitFailure) => string;
325
+ /** HTTP status for an AIP verify failure: 503 when our infra couldn't reach the IdP (retryable),
326
+ * 403 for trust/claims, 401 for auth-presence/signature. */
327
+ declare const aipErrorStatus: (failure: VerifyAitFailure) => 401 | 403 | 503;
328
+ /**
329
+ * Build an RFC 9457 problem-details body for an AIP verify failure. Adapters serialize this
330
+ * as `application/problem+json` with {@link aipErrorStatus}.
331
+ */
332
+ declare const buildAipErrorBody: (failure: VerifyAitFailure) => {
333
+ type: string;
334
+ title: string;
335
+ status: number;
336
+ detail: string;
337
+ };
338
+
339
+ export { AGENTSCORE_CANONICAL_ISSUER as A, HARD_MAX_CACHE_SECONDS as H, type IdentityClaim as I, JWKS_WELL_KNOWN_PATH as J, type TrustLevel as T, type VerifiedAit as V, AGENT_IDENTITY_HEADER as a, type AipGateOptions as b, type AipGateResult as c, type AitHeader as d, type AitPayload as e, type AitValidationResult as f, type AmrValue as g, type IntentClaim as h, JwksCache as i, type JwksCacheOptions as j, type JwksLookupResult as k, type VerifyAitFailure as l, type VerifyAitOptions as m, type VerifyAitResult as n, type VerifyRequestContext as o, aipErrorCode as p, aipErrorStatus as q, buildAipErrorBody as r, canonicalizeIssuer as s, isAitShape as t, verifyAit as u, validateAitPayload as v, verifyAitRequest as w };
@@ -0,0 +1,339 @@
1
+ import { JWK } from 'jose';
2
+
3
+ /**
4
+ * AIP (Agentic Identity Protocol) token types and the claim contract.
5
+ *
6
+ * An Agent Identity Token (AIT) is a JWT signed by an Identity Provider (IdP). It binds a
7
+ * verified human's identity to the specific agent presenting it (via `cnf`, RFC 7800) and
8
+ * carries the trust level, authentication method, optional intent, and optional identity
9
+ * claims the IdP attests to.
10
+ *
11
+ * This module is the single source of truth for the claim shape on the verifier side. It
12
+ * encodes the spec's required / recommended / optional claims plus the AgentScore extension
13
+ * claims (sanctions, jurisdiction, structured id-verification, cross-merchant graph, payment
14
+ * signer) we carry when we act as a compliance IdP.
15
+ *
16
+ * Extensibility contract (per spec): the `identity` object is open. If a claim is present,
17
+ * the IdP attests to it; verifiers ignore claims they don't recognize. Absence is the
18
+ * "unknown" signal — IdPs do not ship `null` for "not checked".
19
+ */
20
+
21
+ /** Degree of human involvement in issuing this specific AIT. */
22
+ type TrustLevel = 'autonomous' | 'human_present' | 'human_confirmed';
23
+ /**
24
+ * Authentication Method Reference values (RFC 8176 / IANA AMR registry). Open set — these
25
+ * are the values relevant to agent identity; others are valid and pass through.
26
+ */
27
+ type AmrValue = 'face' | 'fpt' | 'hwk' | 'otp' | 'pin' | 'pwd' | 'sms' | 'swk' | 'user' | 'mfa';
28
+ /** RFC 7800 confirmation claim: binds the AIT to the agent's signing key. */
29
+ interface CnfClaim {
30
+ jwk: JWK;
31
+ }
32
+ /** Agent metadata. `provider` is required; `instance` is recommended. */
33
+ interface AgentClaim {
34
+ provider: string;
35
+ instance?: string;
36
+ }
37
+ /** How the user authorized THIS AIT (not prior authentication history). */
38
+ interface AuthClaim {
39
+ amr?: AmrValue[] | string[];
40
+ /** When the user authenticated for this token (Unix seconds). Mirrors OIDC `auth_time`. */
41
+ time?: number;
42
+ }
43
+ /** What the agent intends to do. Optional; verifiers may require it for non-read actions. */
44
+ interface IntentClaim {
45
+ actions?: string[];
46
+ description?: string;
47
+ }
48
+ /** AgentScore wallet-binding extension (orthogonal to `cnf`, which binds the agent key). */
49
+ interface PaymentSignerClaim {
50
+ address: string;
51
+ network: 'evm' | 'solana';
52
+ /** Relationship the IdP attests between signer and the operator graph. */
53
+ match?: 'linked_operator' | 'claimed_operator';
54
+ }
55
+ interface PaymentClaim {
56
+ signer?: PaymentSignerClaim;
57
+ }
58
+ /**
59
+ * Identity claims (presence == IdP attestation). Spec-defined fields plus AgentScore
60
+ * compliance extension claims. Open by contract — unknown fields are allowed and ignored.
61
+ */
62
+ interface IdentityClaim {
63
+ email?: string;
64
+ email_verified?: boolean;
65
+ name?: string;
66
+ phone?: string;
67
+ phone_verified?: boolean;
68
+ age_over_18?: boolean;
69
+ age_over_21?: boolean;
70
+ id_verified?: boolean;
71
+ id_verification?: {
72
+ provider?: string;
73
+ method?: string;
74
+ document_type?: string;
75
+ verified_at?: number;
76
+ };
77
+ /** ISO 3166-1 alpha-2, optionally with ISO 3166-2 subdivision (e.g. "US-CA"). */
78
+ jurisdiction?: string;
79
+ sanctions_clear?: boolean;
80
+ sanctions_checked_at?: number;
81
+ sanctions_providers?: string[];
82
+ linked_wallets?: Array<{
83
+ address: string;
84
+ network: 'evm' | 'solana';
85
+ }>;
86
+ merchants_paid?: number;
87
+ first_seen?: number;
88
+ [claim: string]: unknown;
89
+ }
90
+ /** The decoded AIT JWT payload. */
91
+ interface AitPayload {
92
+ aip_version: string;
93
+ iss: string;
94
+ sub: string;
95
+ iat: number;
96
+ exp: number;
97
+ cnf: CnfClaim;
98
+ agent: AgentClaim;
99
+ trust_level?: TrustLevel;
100
+ auth?: AuthClaim;
101
+ intent?: IntentClaim;
102
+ identity?: IdentityClaim;
103
+ payment?: PaymentClaim;
104
+ [claim: string]: unknown;
105
+ }
106
+ /** The decoded AIT JWT header. */
107
+ interface AitHeader {
108
+ alg: string;
109
+ typ?: string;
110
+ kid?: string;
111
+ [param: string]: unknown;
112
+ }
113
+ /**
114
+ * Structural validation of a decoded AIT payload. Confirms the required claims are present
115
+ * and well-typed, and enforces the one normative conditional in the spec: a
116
+ * `human_confirmed` token MUST carry at least one `auth.amr` value.
117
+ *
118
+ * This is shape/contract validation only — it does NOT verify signatures (that's the
119
+ * verifier pipeline) and does NOT apply trust policy (that's the gate / `/v1/assess`).
120
+ */
121
+ type AitValidationResult = {
122
+ ok: true;
123
+ payload: AitPayload;
124
+ } | {
125
+ ok: false;
126
+ reason: AitValidationFailure;
127
+ };
128
+ type AitValidationFailure = 'not_an_object' | 'missing_aip_version' | 'missing_iss' | 'missing_sub' | 'missing_iat' | 'missing_exp' | 'missing_cnf' | 'missing_agent_provider' | 'human_confirmed_without_amr';
129
+ /**
130
+ * Detect whether a decoded JWT payload is an AIT: per spec, an AIT is discriminated by the
131
+ * presence of `cnf` + `agent` claims (not the `typ` header).
132
+ */
133
+ declare const isAitShape: (payload: unknown) => boolean;
134
+ /** Validate the structural contract of a decoded AIT payload. */
135
+ declare const validateAitPayload: (payload: unknown) => AitValidationResult;
136
+
137
+ /**
138
+ * AIP IdP key discovery: fetch, cache, and select JWKS signing keys.
139
+ *
140
+ * Verifiers resolve an IdP's public keys from `https://{iss}/.well-known/agent-identity/jwks.json`
141
+ * (the spec's well-known path). This module owns:
142
+ *
143
+ * - **Trusted-issuer enforcement** — only `iss` values on the allowlist are fetched, compared
144
+ * after URL canonicalization (lowercase scheme+host, no default port, no trailing slash) so
145
+ * `https://issuer.example` and `https://issuer.example/` match.
146
+ * - **HTTPS-only** — JWKS over plain HTTP is MITM-vulnerable; we refuse it.
147
+ * - **Caching with a HARD cap** — we honor `Cache-Control: max-age` as advisory but never
148
+ * cache longer than {@link HARD_MAX_CACHE_SECONDS}, regardless of what the IdP sends. A
149
+ * compromised IdP can't pin stale keys with `max-age=31536000`.
150
+ * - **kid-miss refresh** — a lookup for a `kid` not in the cached set triggers one refetch
151
+ * (rotation may have published a new key inside the cache window).
152
+ * - **use:"sig" filtering** — only signing keys are returned.
153
+ *
154
+ * Pure-ish: the only I/O is `fetch`, injectable for tests.
155
+ */
156
+
157
+ /** The spec's well-known JWKS path, relative to the issuer origin. */
158
+ declare const JWKS_WELL_KNOWN_PATH = "/.well-known/agent-identity/jwks.json";
159
+ /** Hard ceiling on cache age, regardless of IdP-supplied Cache-Control. */
160
+ declare const HARD_MAX_CACHE_SECONDS = 86400;
161
+ type FetchLike = (url: string, init?: {
162
+ headers?: Record<string, string>;
163
+ }) => Promise<{
164
+ ok: boolean;
165
+ status: number;
166
+ headers: {
167
+ get(name: string): string | null;
168
+ };
169
+ json(): Promise<unknown>;
170
+ }>;
171
+ /** AgentScore's own AIT issuer. ALWAYS trusted by every {@link JwksCache} (and therefore every
172
+ * gate/adapter built on it) without the merchant listing it — this SDK is the AgentScore
173
+ * verifier, so a merchant can't accidentally fail to trust AgentScore-issued AITs. `trustedIssuers`
174
+ * only needs to name ADDITIONAL external issuers. */
175
+ declare const AGENTSCORE_CANONICAL_ISSUER = "https://agentscore.sh";
176
+ interface JwksCacheOptions {
177
+ /** ADDITIONAL external issuer URLs to trust beyond AgentScore's own (compared after
178
+ * canonicalization). AgentScore's canonical issuer is always trusted; omit/empty to accept
179
+ * only AgentScore-issued AITs. */
180
+ trustedIssuers?: string[];
181
+ /** Injectable fetch (defaults to global fetch). */
182
+ fetchImpl?: FetchLike;
183
+ /** Injectable clock (ms), for tests. */
184
+ now?: () => number;
185
+ /** User-Agent for JWKS requests. */
186
+ userAgent?: string;
187
+ }
188
+ type JwksLookupFailure = 'untrusted_issuer' | 'insecure_issuer' | 'fetch_failed' | 'malformed_jwks' | 'key_not_found';
189
+ type JwksLookupResult = {
190
+ ok: true;
191
+ key: JWK;
192
+ } | {
193
+ ok: false;
194
+ reason: JwksLookupFailure;
195
+ };
196
+ /**
197
+ * Canonicalize an issuer URL for trust-list comparison: lowercase scheme + host, drop the
198
+ * default port for the scheme, strip a trailing slash on an empty path. Returns null if the
199
+ * input is not a parseable absolute URL.
200
+ */
201
+ declare const canonicalizeIssuer: (iss: string) => string | null;
202
+ /**
203
+ * JWKS resolver bound to a trusted-issuer allowlist. One instance can serve many issuers;
204
+ * each issuer's key set is cached independently.
205
+ */
206
+ declare class JwksCache {
207
+ private readonly trusted;
208
+ private readonly fetchImpl;
209
+ private readonly now;
210
+ private readonly userAgent;
211
+ private readonly cache;
212
+ constructor(opts: JwksCacheOptions);
213
+ /** Is this issuer on the canonicalized trust list? */
214
+ isTrusted(iss: string): boolean;
215
+ /**
216
+ * Resolve the signing key for `(iss, kid)`. Enforces trust + HTTPS, serves from cache when
217
+ * fresh, and refetches once on a kid-miss before giving up.
218
+ */
219
+ getKey(iss: string, kid: string | undefined): Promise<JwksLookupResult>;
220
+ private select;
221
+ private refresh;
222
+ }
223
+
224
+ /**
225
+ * AIP Agent Identity Token (AIT) verification pipeline — the verifier orchestrator.
226
+ *
227
+ * This is the function a merchant gate calls. It executes the spec's verification steps over
228
+ * a presented request, composing the three foundation modules:
229
+ * - {@link ./jwks} — trusted-issuer enforcement + key discovery
230
+ * - {@link ./http-signature} — RFC 9421 proof-of-possession over the request
231
+ * - {@link ./types} — AIT structural contract
232
+ *
233
+ * Steps (per spec):
234
+ * 1. read the `Agent-Identity` header (one or more)
235
+ * 2. decode the JWT header (`kid`) + payload; confirm AIT shape (`cnf` + `agent`)
236
+ * 3. resolve the IdP's signing key from its JWKS (trusted-issuer + HTTPS enforced)
237
+ * 4. verify the IdP signature on the JWT (reject `alg:none`; key is Ed25519)
238
+ * 5. check `exp` / `iat` with skew
239
+ * 6. extract `cnf.jwk`
240
+ * 7. verify the RFC 9421 HTTP Message Signature with `cnf.jwk`
241
+ * 8. confirm the signature `keyid` == JWK thumbprint of `cnf.jwk` (done inside step 7)
242
+ *
243
+ * On success it returns the validated, signature-checked claims. On failure it returns a
244
+ * typed reason that maps onto AIP's wire error codes (the gate turns these into 401/403).
245
+ */
246
+
247
+ /** Header that carries the AIT JWT. */
248
+ declare const AGENT_IDENTITY_HEADER = "agent-identity";
249
+ /** Request fields the verifier needs. Framework-agnostic; adapters map their req onto this. */
250
+ interface VerifyRequestContext {
251
+ method: string;
252
+ authority: string;
253
+ path: string;
254
+ /** All `Agent-Identity` header values present on the request (one per IdP). */
255
+ agentIdentityHeaders: string[];
256
+ signatureInput: string | null;
257
+ signature: string | null;
258
+ }
259
+ interface VerifyAitOptions {
260
+ jwks: JwksCache;
261
+ now?: number;
262
+ maxSkewSeconds?: number;
263
+ }
264
+ /**
265
+ * Failure reasons, aligned with AIP wire error codes. The gate maps:
266
+ * no_token / malformed_token / invalid_signature / expired_token → 401
267
+ * untrusted_issuer / weak_auth / invalid_claims → 403
268
+ */
269
+ type VerifyAitFailure = 'no_token' | 'malformed_token' | 'untrusted_issuer' | 'key_unavailable' | 'idp_signature_invalid' | 'expired_token' | 'invalid_claims' | 'pop_signature_missing' | 'pop_signature_invalid';
270
+ interface VerifiedAit {
271
+ payload: AitPayload;
272
+ /** The issuer (canonical, as presented). */
273
+ iss: string;
274
+ /** The agent's bound public key (`cnf.jwk`). */
275
+ cnfJwk: AitPayload['cnf']['jwk'];
276
+ /** The raw JWT string that verified (the winning `Agent-Identity` header value, Bearer
277
+ * prefix stripped). Lets a gate forward the exact token to `/v1/assess` as `aip_token`. */
278
+ token: string;
279
+ }
280
+ type VerifyAitResult = {
281
+ ok: true;
282
+ ait: VerifiedAit;
283
+ } | {
284
+ ok: false;
285
+ reason: VerifyAitFailure;
286
+ };
287
+ /**
288
+ * Verify the AIP credential on a request. When multiple `Agent-Identity` headers are present,
289
+ * each is tried; the first that fully verifies AND whose `cnf.jwk` matches the request's
290
+ * RFC 9421 signature wins (all AITs on one request must share the same `cnf` key, so the PoP
291
+ * signature is checked once against the winning key).
292
+ */
293
+ declare const verifyAit: (ctx: VerifyRequestContext, opts: VerifyAitOptions) => Promise<VerifyAitResult>;
294
+
295
+ /**
296
+ * Framework-agnostic AIP gate orchestration.
297
+ *
298
+ * `verifyAitRequest` is the one call a framework adapter makes: hand it a standard `Request`
299
+ * plus a {@link JwksCache}, and it returns the verified AIT claims or a typed failure. The
300
+ * helpers here also map that failure onto the AIP wire contract — HTTP status + error code +
301
+ * an RFC 9457 problem-details body — so every adapter renders denials identically.
302
+ *
303
+ * This layer does identity *verification* only (is this a real, key-bound AIT from a trusted
304
+ * IdP?). Policy enrichment — sanctions, jurisdiction, cross-merchant graph — happens when the
305
+ * merchant additionally feeds the verified claims to `/v1/assess`; that's the gate's choice,
306
+ * not something this module forces.
307
+ */
308
+
309
+ interface AipGateOptions {
310
+ jwks: JwksCache;
311
+ now?: number;
312
+ maxSkewSeconds?: number;
313
+ }
314
+ type AipGateResult = {
315
+ ok: true;
316
+ ait: VerifiedAit;
317
+ } | {
318
+ ok: false;
319
+ failure: VerifyAitFailure;
320
+ };
321
+ /** Verify the AIP credential on a standard Fetch `Request` (Hono / Web / Next.js). */
322
+ declare const verifyAitRequest: (req: Request, opts: AipGateOptions) => Promise<AipGateResult>;
323
+ /** Map an internal verify failure to the AIP wire error code (per spec error taxonomy). */
324
+ declare const aipErrorCode: (failure: VerifyAitFailure) => string;
325
+ /** HTTP status for an AIP verify failure: 503 when our infra couldn't reach the IdP (retryable),
326
+ * 403 for trust/claims, 401 for auth-presence/signature. */
327
+ declare const aipErrorStatus: (failure: VerifyAitFailure) => 401 | 403 | 503;
328
+ /**
329
+ * Build an RFC 9457 problem-details body for an AIP verify failure. Adapters serialize this
330
+ * as `application/problem+json` with {@link aipErrorStatus}.
331
+ */
332
+ declare const buildAipErrorBody: (failure: VerifyAitFailure) => {
333
+ type: string;
334
+ title: string;
335
+ status: number;
336
+ detail: string;
337
+ };
338
+
339
+ export { AGENTSCORE_CANONICAL_ISSUER as A, HARD_MAX_CACHE_SECONDS as H, type IdentityClaim as I, JWKS_WELL_KNOWN_PATH as J, type TrustLevel as T, type VerifiedAit as V, AGENT_IDENTITY_HEADER as a, type AipGateOptions as b, type AipGateResult as c, type AitHeader as d, type AitPayload as e, type AitValidationResult as f, type AmrValue as g, type IntentClaim as h, JwksCache as i, type JwksCacheOptions as j, type JwksLookupResult as k, type VerifyAitFailure as l, type VerifyAitOptions as m, type VerifyAitResult as n, type VerifyRequestContext as o, aipErrorCode as p, aipErrorStatus as q, buildAipErrorBody as r, canonicalizeIssuer as s, isAitShape as t, verifyAit as u, validateAitPayload as v, verifyAitRequest as w };