@agent-score/commerce 1.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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/dist/_response-DmziuJz6.d.mts +137 -0
  4. package/dist/_response-rbK0zM7y.d.ts +137 -0
  5. package/dist/api/index.d.mts +1 -0
  6. package/dist/api/index.d.ts +1 -0
  7. package/dist/api/index.js +37 -0
  8. package/dist/api/index.js.map +1 -0
  9. package/dist/api/index.mjs +14 -0
  10. package/dist/api/index.mjs.map +1 -0
  11. package/dist/challenge/index.d.mts +523 -0
  12. package/dist/challenge/index.d.ts +523 -0
  13. package/dist/challenge/index.js +354 -0
  14. package/dist/challenge/index.js.map +1 -0
  15. package/dist/challenge/index.mjs +318 -0
  16. package/dist/challenge/index.mjs.map +1 -0
  17. package/dist/core.d.mts +252 -0
  18. package/dist/core.d.ts +252 -0
  19. package/dist/core.js +500 -0
  20. package/dist/core.js.map +1 -0
  21. package/dist/core.mjs +472 -0
  22. package/dist/core.mjs.map +1 -0
  23. package/dist/discovery/index.d.mts +382 -0
  24. package/dist/discovery/index.d.ts +382 -0
  25. package/dist/discovery/index.js +675 -0
  26. package/dist/discovery/index.js.map +1 -0
  27. package/dist/discovery/index.mjs +630 -0
  28. package/dist/discovery/index.mjs.map +1 -0
  29. package/dist/identity/express.d.mts +44 -0
  30. package/dist/identity/express.d.ts +44 -0
  31. package/dist/identity/express.js +777 -0
  32. package/dist/identity/express.js.map +1 -0
  33. package/dist/identity/express.mjs +738 -0
  34. package/dist/identity/express.mjs.map +1 -0
  35. package/dist/identity/fastify.d.mts +63 -0
  36. package/dist/identity/fastify.d.ts +63 -0
  37. package/dist/identity/fastify.js +780 -0
  38. package/dist/identity/fastify.js.map +1 -0
  39. package/dist/identity/fastify.mjs +741 -0
  40. package/dist/identity/fastify.mjs.map +1 -0
  41. package/dist/identity/hono.d.mts +83 -0
  42. package/dist/identity/hono.d.ts +83 -0
  43. package/dist/identity/hono.js +779 -0
  44. package/dist/identity/hono.js.map +1 -0
  45. package/dist/identity/hono.mjs +740 -0
  46. package/dist/identity/hono.mjs.map +1 -0
  47. package/dist/identity/nextjs.d.mts +62 -0
  48. package/dist/identity/nextjs.d.ts +62 -0
  49. package/dist/identity/nextjs.js +784 -0
  50. package/dist/identity/nextjs.js.map +1 -0
  51. package/dist/identity/nextjs.mjs +747 -0
  52. package/dist/identity/nextjs.mjs.map +1 -0
  53. package/dist/identity/policy.d.mts +115 -0
  54. package/dist/identity/policy.d.ts +115 -0
  55. package/dist/identity/policy.js +81 -0
  56. package/dist/identity/policy.js.map +1 -0
  57. package/dist/identity/policy.mjs +53 -0
  58. package/dist/identity/policy.mjs.map +1 -0
  59. package/dist/identity/web.d.mts +82 -0
  60. package/dist/identity/web.d.ts +82 -0
  61. package/dist/identity/web.js +775 -0
  62. package/dist/identity/web.js.map +1 -0
  63. package/dist/identity/web.mjs +738 -0
  64. package/dist/identity/web.mjs.map +1 -0
  65. package/dist/index.d.mts +252 -0
  66. package/dist/index.d.ts +252 -0
  67. package/dist/index.js +432 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/index.mjs +388 -0
  70. package/dist/index.mjs.map +1 -0
  71. package/dist/payment/index.d.mts +716 -0
  72. package/dist/payment/index.d.ts +716 -0
  73. package/dist/payment/index.js +691 -0
  74. package/dist/payment/index.js.map +1 -0
  75. package/dist/payment/index.mjs +639 -0
  76. package/dist/payment/index.mjs.map +1 -0
  77. package/dist/signer-Cvdwn6Cs.d.mts +48 -0
  78. package/dist/signer-Cvdwn6Cs.d.ts +48 -0
  79. package/dist/stripe-multichain/index.d.mts +221 -0
  80. package/dist/stripe-multichain/index.d.ts +221 -0
  81. package/dist/stripe-multichain/index.js +243 -0
  82. package/dist/stripe-multichain/index.js.map +1 -0
  83. package/dist/stripe-multichain/index.mjs +199 -0
  84. package/dist/stripe-multichain/index.mjs.map +1 -0
  85. package/dist/wwwauthenticate-CU1eNvMQ.d.mts +37 -0
  86. package/dist/wwwauthenticate-CU1eNvMQ.d.ts +37 -0
  87. package/package.json +172 -0
@@ -0,0 +1,252 @@
1
+ import { AgentScoreData } from './core.js';
2
+ export { AgentIdentity, AgentMemoryHint, AgentScoreCore, AgentScoreCoreOptions, CreateSessionOnMissing, DenialCode, DenialReason, EvaluateOutcome, VerifyWalletSignerMatchOptions, VerifyWalletSignerResult, buildAgentMemoryHint } from './core.js';
3
+ export { P as PaymentSigner, S as SignerNetwork, a as extractPaymentSigner, e as extractPaymentSignerAddress, r as readX402PaymentHeader } from './signer-Cvdwn6Cs.js';
4
+ export { F as FIXABLE_DENIAL_REASONS, b as buildContactSupportNextSteps, a as buildSignerMismatchBody, d as denialReasonStatus, c as denialReasonToBody, i as isFixableDenial, v as verificationAgentInstructions } from './_response-rbK0zM7y.js';
5
+ export { EnforcementMode, GateResult, IdentityStatus, PolicyBlock, policyToGateOptions, runGateWithEnforcement, shippingCountryAllowed, shippingStateAllowed } from './identity/policy.js';
6
+
7
+ /**
8
+ * Google A2A (Agent-to-Agent) Signed Agent Cards builder.
9
+ *
10
+ * Compose the JSON payload for an A2A v1.0 Signed Agent Card that includes the
11
+ * agent's AgentScore identity claims. Returned object is the unsigned card body —
12
+ * the merchant (or agent) signs it with their wallet / signing key before publishing.
13
+ *
14
+ * Why publish: A2A is a Linux Foundation standard with 150+ orgs (Microsoft, AWS,
15
+ * Salesforce in production). Signed Agent Cards let any A2A-compatible reader discover
16
+ * an agent's verified-identity claims without per-platform integration. AgentScore
17
+ * publishing operator identity in this format means our identity travels with the agent
18
+ * across A2A-aware ecosystems.
19
+ *
20
+ * Spec reference: https://a2a-protocol.org/latest/
21
+ */
22
+
23
+ interface A2AAgentCardCapabilities {
24
+ /** Endpoints the agent exposes — `[{ name: "purchase", path: "/purchase", method: "POST" }, ...]`. */
25
+ endpoints?: {
26
+ name: string;
27
+ path?: string;
28
+ method?: string;
29
+ }[];
30
+ /** Free-form skill tags — `["wine-purchase", "regulated-commerce", ...]`. */
31
+ skills?: string[];
32
+ }
33
+ interface A2AAgentCardIdentity {
34
+ /** Issuer of the identity claims — always `"https://agentscore.sh"` for the AgentScore-issued card. */
35
+ issuer: string;
36
+ /** Operator id under AgentScore. */
37
+ operator_id: string;
38
+ /** KYC tier. */
39
+ kyc_level: string;
40
+ /** Sanctions screening result. */
41
+ sanctions_clear: boolean;
42
+ /** Age bracket. */
43
+ age_bracket: string;
44
+ /** Jurisdiction (ISO-3166-1 alpha-2 or empty). */
45
+ jurisdiction: string;
46
+ /** ISO-8601 timestamp of last verification refresh. */
47
+ verified_at: string | null;
48
+ /** Verify URL where the identity was minted. */
49
+ verify_url: string;
50
+ }
51
+ interface A2AAgentCard {
52
+ /** A2A protocol version. v1.0 was donated to Linux Foundation. */
53
+ protocol_version: string;
54
+ /** Card schema version (this builder emits v1). */
55
+ card_version: number;
56
+ /** Agent's display name. */
57
+ name: string;
58
+ /** One-line description shown to A2A consumers. */
59
+ description?: string;
60
+ /** Agent's canonical URL (homepage, Discord, repo, etc.). */
61
+ url?: string;
62
+ /** Agent capabilities — endpoints + skills. */
63
+ capabilities?: A2AAgentCardCapabilities;
64
+ /** AgentScore identity claims. Empty `null` when no identity is available (pre-KYC). */
65
+ identity: A2AAgentCardIdentity | null;
66
+ /** Vendor-specific extras merged at the top level. */
67
+ extras?: Record<string, unknown>;
68
+ }
69
+ interface BuildA2AAgentCardInput {
70
+ /** Display name for the agent — `"Martin Estate Wine Concierge"`, etc. */
71
+ name: string;
72
+ /** Optional one-line description. */
73
+ description?: string;
74
+ /** Agent's canonical URL. */
75
+ url?: string;
76
+ /** Capabilities — endpoints exposed + skill tags. */
77
+ capabilities?: A2AAgentCardCapabilities;
78
+ /** AgentScore assess data — what `getAgentScoreData(c)` returns or what `assess()` returned directly.
79
+ * Pass `null` to emit a card with no identity claims (publishable but unverified). */
80
+ data?: AgentScoreData | null;
81
+ /** Override the default issuer URL. Default `"https://agentscore.sh"`. */
82
+ issuer?: string;
83
+ /** Override the verify URL. */
84
+ verifyUrl?: string;
85
+ /** Vendor-specific extras merged at the card top level. */
86
+ extras?: Record<string, unknown>;
87
+ }
88
+ /**
89
+ * Compose an A2A Signed Agent Card body with AgentScore identity claims included.
90
+ *
91
+ * Returns the UNSIGNED card. The vendor signs it with their wallet (typically using
92
+ * the same wallet they use for x402 / MPP payments) and publishes the signed envelope
93
+ * to wherever A2A consumers discover cards (a hosted endpoint, on-chain registry,
94
+ * agent-card-server, etc.). Signing is vendor-side because the agent's signing key
95
+ * never leaves their environment.
96
+ *
97
+ * Example:
98
+ * ```ts
99
+ * import { buildA2AAgentCard } from '@agent-score/commerce/identity/hono';
100
+ *
101
+ * app.get('/.well-known/agent-card', async (c) => {
102
+ * const data = getAgentScoreData(c);
103
+ * const card = buildA2AAgentCard({
104
+ * name: 'Martin Estate Wine Concierge',
105
+ * description: 'Buy regulated wines from Martin Estate via agent payments.',
106
+ * url: 'https://agents.martinestate.com',
107
+ * capabilities: {
108
+ * endpoints: [{ name: 'purchase', path: '/purchase', method: 'POST' }],
109
+ * skills: ['wine-purchase', 'regulated-commerce'],
110
+ * },
111
+ * data,
112
+ * });
113
+ * const signed = await yourSign(card);
114
+ * return c.json(signed);
115
+ * });
116
+ * ```
117
+ */
118
+ declare function buildA2AAgentCard(input: BuildA2AAgentCardInput): A2AAgentCard;
119
+
120
+ /**
121
+ * UCP (Universal Commerce Protocol) profile builder.
122
+ *
123
+ * Compose the JSON payload published at `/.well-known/ucp` per the UCP spec, with
124
+ * AgentScore identity claims attached as a capability. Returned object is the unsigned
125
+ * profile body — the merchant signs it (or wraps it in their JWKS-backed envelope)
126
+ * before publishing.
127
+ *
128
+ * Why publish: UCP is the Google-led cross-vendor standard (announced Jan 2026 at NRF
129
+ * with Shopify, Etsy, Wayfair, Target, Walmart, Adyen, Mastercard, Stripe, Visa, Amex,
130
+ * etc.). Every UCP-aware platform discovers a merchant via `/.well-known/ucp`, so
131
+ * shipping this profile means AgentScore-gated merchants are discoverable through the
132
+ * same surface every other UCP merchant uses.
133
+ *
134
+ * Spec reference: https://ucp.dev/
135
+ *
136
+ * UCP profiles do NOT carry KYC / sanctions / age / jurisdiction claims natively —
137
+ * identity in the UCP spec is "who signed this" (JWKS-backed). AgentScore claims layer
138
+ * over UCP via a custom capability so consumers who care about verified-buyer identity
139
+ * can read them; consumers who don't care just see a normal UCP profile.
140
+ */
141
+
142
+ interface UCPSigningKey {
143
+ /** JWK kid (key id). */
144
+ kid: string;
145
+ /** JWK kty (key type) — typically `EC`, `RSA`, or `OKP`. */
146
+ kty: string;
147
+ /** JWK alg (signing algorithm) — typically `ES256`, `RS256`, or `EdDSA`. */
148
+ alg?: string;
149
+ /** JWK use — typically `sig`. */
150
+ use?: string;
151
+ /** JWK crv (curve) for EC / OKP keys. */
152
+ crv?: string;
153
+ /** JWK x / y / n / e / etc. The full key material; passed through verbatim. */
154
+ [k: string]: unknown;
155
+ }
156
+ interface UCPService {
157
+ /** Transport binding — `rest` / `mcp` / `a2a` / `embedded`. */
158
+ type: string;
159
+ /** Service URL (or path for embedded). */
160
+ url?: string;
161
+ /** Optional version pin. */
162
+ version?: string;
163
+ /** Vendor-specific extras for the binding. */
164
+ [k: string]: unknown;
165
+ }
166
+ interface UCPCapability {
167
+ /** Capability name — `checkout`, `catalog`, `agentscore-identity`, etc. */
168
+ name: string;
169
+ /** URL of the JSON Schema describing this capability's payload. */
170
+ schema?: string;
171
+ /** Capability version — semver or date-stamp per UCP convention. */
172
+ version?: string;
173
+ /** Vendor-specific extras for the capability. */
174
+ [k: string]: unknown;
175
+ }
176
+ interface UCPPaymentHandler {
177
+ /** Handler name — `stripe`, `tempo`, `x402-base`, `x402-solana`, etc. */
178
+ name: string;
179
+ /** Handler config — recipient address, profile id, etc. */
180
+ config?: Record<string, unknown>;
181
+ }
182
+ interface UCPProfile {
183
+ /** UCP spec version (date-stamped). */
184
+ version: string;
185
+ /** URL of the UCP spec. */
186
+ spec: string;
187
+ /** URL of this profile's JSON schema. */
188
+ schema?: string;
189
+ /** Display name of the merchant / agent surface. */
190
+ name?: string;
191
+ /** Service bindings — REST, MCP, A2A, embedded transports. */
192
+ services: UCPService[];
193
+ /** Capabilities offered (with schema URLs). */
194
+ capabilities: UCPCapability[];
195
+ /** Payment handlers offered — typically the rails the merchant accepts. */
196
+ payment_handlers: UCPPaymentHandler[];
197
+ /** JWKS — REQUIRED by spec. The merchant signs requests with a private key whose
198
+ * public counterpart is listed here. Verifiers fetch this profile, find the kid, and
199
+ * validate signatures. */
200
+ signing_keys: UCPSigningKey[];
201
+ /** Vendor-specific extras at the top level. */
202
+ [k: string]: unknown;
203
+ }
204
+ interface BuildUCPProfileInput {
205
+ /** UCP spec version. Default `"2026-04-17"` (current at time of writing). */
206
+ version?: string;
207
+ /** Display name for the merchant / agent surface. */
208
+ name?: string;
209
+ /** Service transport bindings. At minimum, the agent's primary REST endpoint. */
210
+ services: UCPService[];
211
+ /** Capabilities offered. AgentScore identity is auto-added as a capability when `data` is provided. */
212
+ capabilities?: UCPCapability[];
213
+ /** Payment handlers — rails the merchant accepts. */
214
+ payment_handlers?: UCPPaymentHandler[];
215
+ /** JWKS — public keys the merchant signs requests with. REQUIRED by spec. */
216
+ signing_keys: UCPSigningKey[];
217
+ /** AgentScore assess data — adds an `agentscore-identity` capability + claims block when present. */
218
+ data?: AgentScoreData | null;
219
+ /** Optional override for the AgentScore capability schema URL. */
220
+ agentscoreSchemaUrl?: string;
221
+ /** Vendor-specific extras at the top level. */
222
+ extras?: Record<string, unknown>;
223
+ }
224
+ /**
225
+ * Compose a UCP profile body for `/.well-known/ucp` publication. Merges AgentScore
226
+ * identity claims into the `capabilities` array as an `agentscore-identity` capability
227
+ * so UCP-aware consumers can discover verified-buyer claims alongside the standard
228
+ * UCP transport metadata.
229
+ *
230
+ * Example:
231
+ * ```ts
232
+ * import { buildUCPProfile } from '@agent-score/commerce/identity/hono';
233
+ *
234
+ * app.get('/.well-known/ucp', async (c) => {
235
+ * const data = getAgentScoreData(c);
236
+ * return c.json(buildUCPProfile({
237
+ * name: 'Martin Estate',
238
+ * services: [{ type: 'rest', url: 'https://agents.martinestate.com' }],
239
+ * payment_handlers: [
240
+ * { name: 'tempo', config: { recipient: TEMPO_ADDR } },
241
+ * { name: 'stripe', config: { profile_id: STRIPE_PROFILE_ID } },
242
+ * ],
243
+ * signing_keys: [{ kid: 'me-2026-04', kty: 'EC', alg: 'ES256', crv: 'P-256', x: '...', y: '...' }],
244
+ * data,
245
+ * }));
246
+ * });
247
+ * ```
248
+ */
249
+ declare function buildUCPProfile(input: BuildUCPProfileInput): UCPProfile;
250
+ declare const AGENTSCORE_UCP_CAPABILITY = "agentscore-identity";
251
+
252
+ export { type A2AAgentCard, type A2AAgentCardCapabilities, type A2AAgentCardIdentity, AGENTSCORE_UCP_CAPABILITY, AgentScoreData, type BuildA2AAgentCardInput, type BuildUCPProfileInput, type UCPCapability, type UCPPaymentHandler, type UCPProfile, type UCPService, type UCPSigningKey, buildA2AAgentCard, buildUCPProfile };
package/dist/index.js ADDED
@@ -0,0 +1,432 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AGENTSCORE_UCP_CAPABILITY: () => AGENTSCORE_UCP_CAPABILITY,
24
+ FIXABLE_DENIAL_REASONS: () => FIXABLE_DENIAL_REASONS,
25
+ buildA2AAgentCard: () => buildA2AAgentCard,
26
+ buildAgentMemoryHint: () => buildAgentMemoryHint,
27
+ buildContactSupportNextSteps: () => buildContactSupportNextSteps,
28
+ buildSignerMismatchBody: () => buildSignerMismatchBody,
29
+ buildUCPProfile: () => buildUCPProfile,
30
+ denialReasonStatus: () => denialReasonStatus,
31
+ denialReasonToBody: () => denialReasonToBody,
32
+ extractPaymentSigner: () => extractPaymentSigner,
33
+ extractPaymentSignerAddress: () => extractPaymentSignerAddress,
34
+ isFixableDenial: () => isFixableDenial,
35
+ policyToGateOptions: () => policyToGateOptions,
36
+ readX402PaymentHeader: () => readX402PaymentHeader,
37
+ runGateWithEnforcement: () => runGateWithEnforcement,
38
+ shippingCountryAllowed: () => shippingCountryAllowed,
39
+ shippingStateAllowed: () => shippingStateAllowed,
40
+ verificationAgentInstructions: () => verificationAgentInstructions
41
+ });
42
+ module.exports = __toCommonJS(index_exports);
43
+
44
+ // src/core.ts
45
+ var CANONICAL_AGENTSCORE_API = "https://api.agentscore.sh";
46
+ var WALLET_SIGNER_MISMATCH_INSTRUCTIONS = JSON.stringify({
47
+ action: "resign_or_switch_to_operator_token",
48
+ steps: [
49
+ "Preferred: re-submit the payment signed by expected_signer (or any entry in linked_wallets \u2014 same-operator wallets are fungible) and retry with the same X-Wallet-Address.",
50
+ "Alternative: drop X-Wallet-Address and retry with X-Operator-Token. Use a stored opc_... if you have one; otherwise retry this request with NO identity header \u2014 the merchant will mint a verification session in the 403 body (verify_url + poll_secret). Share verify_url with the user, poll, receive a fresh opc_..."
51
+ ],
52
+ user_message: "The payment signer resolves to a different operator than X-Wallet-Address. Re-sign from expected_signer or any linked_wallets entry, or switch to X-Operator-Token."
53
+ });
54
+ var WALLET_AUTH_REQUIRES_WALLET_SIGNING_INSTRUCTIONS = JSON.stringify({
55
+ action: "switch_to_operator_token",
56
+ steps: [
57
+ "This payment rail (Stripe SPT, card) carries no wallet signature \u2014 X-Wallet-Address cannot be verified against the payment.",
58
+ "Drop X-Wallet-Address and retry with X-Operator-Token. If you do not have a stored opc_..., retry with no identity header to receive a verification session."
59
+ ],
60
+ user_message: "Wallet-address identity is only supported on wallet-signing rails (Tempo MPP, x402). On Stripe or card, use X-Operator-Token instead."
61
+ });
62
+ var INVALID_CREDENTIAL_INSTRUCTIONS = JSON.stringify({
63
+ action: "switch_token_or_restart_session",
64
+ steps: [
65
+ "The X-Operator-Token you sent does not match any credential. This is a permanent state \u2014 retrying with the same token will keep failing.",
66
+ "If you have other stored opc_... credentials, retry with one of them.",
67
+ "Otherwise drop X-Operator-Token and retry with no identity header \u2014 the merchant will mint a fresh verification session in the 403 body (verify_url + poll_secret) so the user can re-verify and you can poll for a new operator_token."
68
+ ],
69
+ user_message: "The operator_token is not recognized. Use a different stored token, or restart the verification session flow to mint a new one."
70
+ });
71
+ function buildAgentMemoryHint() {
72
+ const api = CANONICAL_AGENTSCORE_API;
73
+ return {
74
+ save_for_future_agentscore_gates: true,
75
+ pattern_summary: "AgentScore is a cross-merchant identity substrate for agent commerce. Any endpoint that returns 403 missing_identity / identity_verification_required or 402 challenges referencing AgentScore uses the same identity system. One KYC works across all AgentScore merchants \u2014 no re-verification per site. Save this pattern (and the endpoints below) to persistent memory so future AgentScore encounters skip the cold-start session flow.",
76
+ quickstart: "https://docs.agentscore.sh/guides/agent-identity",
77
+ identity_check_endpoint: `${api}/v1/credentials`,
78
+ identity_paths: {
79
+ wallet: "If paying from a crypto wallet you have used before on any AgentScore merchant, send `X-Wallet-Address: 0x...`. Shortest path; no token lifecycle to manage.",
80
+ operator_token: "For any rail (Stripe SPT, card, or a wallet you have not linked yet), send `X-Operator-Token: opc_...`. Reusable across merchants until the token expires."
81
+ },
82
+ bootstrap: "If you have neither a linked wallet nor a valid operator_token, follow the session/verify flow in the per-request `agent_instructions` block. This happens at most once per agent identity \u2014 after first verification, the operator_token and any subsequently used wallet are reusable everywhere.",
83
+ do_not_persist_in_memory: ["operator_token", "poll_secret"],
84
+ persist_in_credential_store: ["operator_token"]
85
+ };
86
+ }
87
+
88
+ // src/signer.ts
89
+ async function extractPaymentSigner(request, x402PaymentHeader) {
90
+ const authHeader = request.headers.get("authorization");
91
+ if (authHeader) {
92
+ try {
93
+ const moduleName = "mppx";
94
+ const mppx = await import(moduleName).catch(() => null);
95
+ if (mppx?.Credential?.extractPaymentScheme(authHeader)) {
96
+ const credential = mppx.Credential.fromRequest(request);
97
+ const source = credential.source;
98
+ const match = source?.match(/^did:pkh:eip155:\d+:(0x[0-9a-fA-F]{40})$/);
99
+ if (match) return { address: match[1].toLowerCase(), network: "evm" };
100
+ }
101
+ } catch (err) {
102
+ console.warn("[gate] MPP signer extraction failed:", err instanceof Error ? err.message : err);
103
+ }
104
+ }
105
+ if (x402PaymentHeader) {
106
+ try {
107
+ const decoded = atob(x402PaymentHeader);
108
+ const parsed = JSON.parse(decoded);
109
+ const network = parsed?.accepted?.network ?? "";
110
+ if (network.startsWith("eip155:")) {
111
+ const from = parsed?.payload?.authorization?.from;
112
+ if (typeof from === "string" && /^0x[0-9a-fA-F]{40}$/.test(from)) {
113
+ return { address: from.toLowerCase(), network: "evm" };
114
+ }
115
+ } else if (network.startsWith("solana:")) {
116
+ const transaction = parsed?.payload?.transaction;
117
+ if (typeof transaction === "string") {
118
+ const moduleName = "@x402/svm";
119
+ const svm = await import(moduleName).catch(() => null);
120
+ if (svm?.decodeTransactionFromPayload && svm.getTokenPayerFromTransaction) {
121
+ const tx = svm.decodeTransactionFromPayload({ transaction });
122
+ const payer = svm.getTokenPayerFromTransaction(tx);
123
+ if (typeof payer === "string" && payer.length > 0) return { address: payer, network: "solana" };
124
+ }
125
+ }
126
+ } else {
127
+ const from = parsed?.payload?.authorization?.from;
128
+ if (typeof from === "string" && /^0x[0-9a-fA-F]{40}$/.test(from)) {
129
+ return { address: from.toLowerCase(), network: "evm" };
130
+ }
131
+ }
132
+ } catch (err) {
133
+ console.warn("[gate] x402 signer extraction failed:", err instanceof Error ? err.message : err);
134
+ }
135
+ }
136
+ return null;
137
+ }
138
+ async function extractPaymentSignerAddress(request, x402PaymentHeader) {
139
+ const result = await extractPaymentSigner(request, x402PaymentHeader);
140
+ return result?.address ?? null;
141
+ }
142
+ function readX402PaymentHeader(request) {
143
+ return request.headers.get("payment-signature") ?? request.headers.get("x-payment") ?? void 0;
144
+ }
145
+
146
+ // src/_denial.ts
147
+ var FIXABLE_DENIAL_REASONS = /* @__PURE__ */ new Set([
148
+ "kyc_required",
149
+ "kyc_pending",
150
+ "kyc_failed",
151
+ "jurisdiction_restricted"
152
+ ]);
153
+ function isFixableDenial(reasons) {
154
+ if (!reasons || reasons.length === 0) return true;
155
+ return reasons.every((r) => FIXABLE_DENIAL_REASONS.has(r));
156
+ }
157
+ function denialReasonStatus(reason) {
158
+ if (reason.code === "token_expired" || reason.code === "invalid_credential") return 401;
159
+ if (reason.code === "api_error") return 503;
160
+ return 403;
161
+ }
162
+ function buildSignerMismatchBody(input) {
163
+ const { result } = input;
164
+ if (result.kind === "pass" || result.kind === "api_error") return null;
165
+ const learnMoreUrl = input.learnMoreUrl ?? "https://docs.agentscore.sh/guides/agent-identity";
166
+ if (result.kind === "wallet_signer_mismatch") {
167
+ const linkedWallets = result.linkedWallets ?? [];
168
+ const userMessage = input.userMessage ?? (linkedWallets.length > 0 ? `Sign the payment with one of the wallets linked to this operator: ${linkedWallets.join(", ")}. Then retry.` : "Sign the payment with the same wallet you claimed via X-Wallet-Address, or switch to X-Operator-Token for rail-independent identity.");
169
+ return {
170
+ error: {
171
+ code: "wallet_signer_mismatch",
172
+ message: "Payment signer does not match the wallet claimed via X-Wallet-Address. The signer and the claimed wallet must both resolve to the same AgentScore operator."
173
+ },
174
+ claimed_operator: result.claimedOperator,
175
+ actual_signer_operator: result.actualSignerOperator ?? null,
176
+ expected_signer: result.expectedSigner,
177
+ actual_signer: result.actualSigner,
178
+ linked_wallets: linkedWallets,
179
+ next_steps: {
180
+ action: "regenerate_payment_from_linked_wallet",
181
+ user_message: userMessage,
182
+ learn_more_url: learnMoreUrl
183
+ }
184
+ };
185
+ }
186
+ return {
187
+ error: {
188
+ code: "wallet_auth_requires_wallet_signing",
189
+ message: "Wallet-auth requires a payment rail that carries a wallet signature (Tempo MPP, x402). Stripe SPT and card rails have no wallet signer; switch to X-Operator-Token to use those."
190
+ },
191
+ next_steps: {
192
+ action: "switch_to_operator_token",
193
+ user_message: input.userMessage ?? "Drop the X-Wallet-Address header and retry with X-Operator-Token (works on every payment rail).",
194
+ learn_more_url: learnMoreUrl
195
+ }
196
+ };
197
+ }
198
+ function buildContactSupportNextSteps(supportEmail, message) {
199
+ return {
200
+ action: "contact_support",
201
+ support_email: supportEmail,
202
+ user_message: message ?? `If you believe this denial is in error, contact support at ${supportEmail} with your order details.`
203
+ };
204
+ }
205
+ function verificationAgentInstructions(input = {}) {
206
+ const baseSteps = [
207
+ "Present the verify_url directly to the user \u2014 it is a complete, ready-to-open URL with the session token already embedded (e.g. https://agentscore.sh/verify?session=sess_...). Do NOT modify or construct the URL yourself.",
208
+ `Immediately begin polling poll_url every ${input.pollIntervalSeconds ?? 5} seconds with header X-Poll-Secret set to poll_secret. The user will complete verification in their browser while you poll in the background.`,
209
+ "The user visits the URL, signs in, completes identity verification (photo ID + selfie via Stripe Identity), and closes the tab. They do NOT need to copy or paste anything back to you.",
210
+ 'When your poll returns status "verified", extract operator_token from the response. This is a one-time value \u2014 save it immediately. Subsequent polls return status "consumed" without the token.',
211
+ input.retryStep ?? "Retry the original merchant request with header X-Operator-Token set to the operator_token value."
212
+ ];
213
+ return {
214
+ action: "poll_for_credential",
215
+ user_action: input.userAction ?? "The user must visit verify_url to complete identity verification before this request can proceed",
216
+ steps: input.extraSteps ? [...baseSteps, ...input.extraSteps] : baseSteps,
217
+ poll_interval_seconds: input.pollIntervalSeconds ?? 5,
218
+ poll_secret_header: "X-Poll-Secret",
219
+ retry_token_header: "X-Operator-Token",
220
+ timeout_seconds: input.timeoutSeconds ?? 3600,
221
+ ...input.orderTtl ? { order_ttl: input.orderTtl } : {},
222
+ ...input.extra ?? {}
223
+ };
224
+ }
225
+
226
+ // src/_response.ts
227
+ var DEFAULT_MESSAGES = {
228
+ missing_identity: "No identity provided. Send X-Wallet-Address (wallet) or X-Operator-Token (credential).",
229
+ identity_verification_required: "Identity verification is required to access this resource. Visit verify_url to complete KYC.",
230
+ wallet_not_trusted: "The wallet does not meet the merchant compliance policy.",
231
+ api_error: "AgentScore is unreachable. This is transient \u2014 retry in a few seconds.",
232
+ payment_required: "AgentScore tier does not support assess. Contact support.",
233
+ wallet_signer_mismatch: "Payment signer does not match the wallet claimed via X-Wallet-Address. The signer and the claimed wallet must both resolve to the same AgentScore operator.",
234
+ wallet_auth_requires_wallet_signing: "X-Wallet-Address was sent with a rail that has no wallet signature (Stripe SPT / card). Switch to X-Operator-Token, or use a wallet-signing rail (Tempo MPP, x402).",
235
+ token_expired: "The operator token is expired or revoked. A fresh verification session has been minted \u2014 visit verify_url to mint a new token.",
236
+ invalid_credential: "The operator token is not recognized. Switch to a different stored token, or drop the header to bootstrap a fresh session."
237
+ };
238
+ var RESERVED_FIELDS = /* @__PURE__ */ new Set([
239
+ "error",
240
+ "decision",
241
+ "reasons",
242
+ "verify_url",
243
+ "session_id",
244
+ "poll_secret",
245
+ "poll_url",
246
+ "agent_instructions",
247
+ "agent_memory",
248
+ "claimed_operator",
249
+ "actual_signer_operator",
250
+ "expected_signer",
251
+ "actual_signer",
252
+ "linked_wallets"
253
+ ]);
254
+ function denialReasonToBody(reason) {
255
+ const message = reason.message ?? DEFAULT_MESSAGES[reason.code];
256
+ const body = { error: { code: reason.code, message } };
257
+ if (reason.decision) body.decision = reason.decision;
258
+ if (reason.reasons) body.reasons = reason.reasons;
259
+ if (reason.verify_url) body.verify_url = reason.verify_url;
260
+ if (reason.session_id) body.session_id = reason.session_id;
261
+ if (reason.poll_secret) body.poll_secret = reason.poll_secret;
262
+ if (reason.poll_url) body.poll_url = reason.poll_url;
263
+ if (reason.agent_instructions) body.agent_instructions = reason.agent_instructions;
264
+ if (reason.agent_memory) body.agent_memory = reason.agent_memory;
265
+ if (reason.claimed_operator) body.claimed_operator = reason.claimed_operator;
266
+ if (reason.code === "wallet_signer_mismatch") body.actual_signer_operator = reason.actual_signer_operator ?? null;
267
+ if (reason.expected_signer) body.expected_signer = reason.expected_signer;
268
+ if (reason.actual_signer) body.actual_signer = reason.actual_signer;
269
+ if (reason.linked_wallets && reason.linked_wallets.length > 0) body.linked_wallets = reason.linked_wallets;
270
+ if (reason.code === "api_error" && !(reason.extra && reason.extra.next_steps)) {
271
+ body.next_steps = { action: "retry", retry_after_seconds: 5 };
272
+ }
273
+ if (reason.extra) {
274
+ for (const [key, value] of Object.entries(reason.extra)) {
275
+ if (RESERVED_FIELDS.has(key)) {
276
+ console.warn(`[gate] onBeforeSession returned reserved field "${key}" \u2014 ignoring to preserve gate authority`);
277
+ continue;
278
+ }
279
+ body[key] = value;
280
+ }
281
+ }
282
+ return body;
283
+ }
284
+
285
+ // src/identity/a2a.ts
286
+ var PROTOCOL_VERSION = "1.0";
287
+ var CARD_VERSION = 1;
288
+ function buildA2AAgentCard(input) {
289
+ const issuer = input.issuer ?? "https://agentscore.sh";
290
+ let identity = null;
291
+ if (input.data) {
292
+ const operatorId = input.data.resolved_operator ?? null;
293
+ if (operatorId) {
294
+ const operatorVerification = input.data.operator_verification;
295
+ const accountVerification = input.data.account_verification;
296
+ identity = {
297
+ issuer,
298
+ operator_id: operatorId,
299
+ kyc_level: accountVerification?.kyc_level ?? operatorVerification?.level ?? "none",
300
+ sanctions_clear: accountVerification?.sanctions_clear === true,
301
+ age_bracket: accountVerification?.age_bracket ?? "unknown",
302
+ jurisdiction: accountVerification?.jurisdiction ?? "",
303
+ verified_at: accountVerification?.verified_at ?? operatorVerification?.verified_at ?? null,
304
+ verify_url: input.verifyUrl ?? input.data.verify_url ?? `${issuer}/verify`
305
+ };
306
+ }
307
+ }
308
+ const card = {
309
+ protocol_version: PROTOCOL_VERSION,
310
+ card_version: CARD_VERSION,
311
+ name: input.name,
312
+ identity
313
+ };
314
+ if (input.description !== void 0) card.description = input.description;
315
+ if (input.url !== void 0) card.url = input.url;
316
+ if (input.capabilities !== void 0) card.capabilities = input.capabilities;
317
+ if (input.extras !== void 0) card.extras = input.extras;
318
+ return card;
319
+ }
320
+
321
+ // src/identity/ucp.ts
322
+ var DEFAULT_VERSION = "2026-04-17";
323
+ var SPEC_URL = "https://ucp.dev/";
324
+ var AGENTSCORE_CAPABILITY_NAME = "agentscore-identity";
325
+ var AGENTSCORE_CAPABILITY_VERSION = "1";
326
+ function buildUCPProfile(input) {
327
+ const baseCapabilities = [...input.capabilities ?? []];
328
+ if (input.data) {
329
+ const operatorId = input.data.resolved_operator;
330
+ if (operatorId) {
331
+ const operatorVerification = input.data.operator_verification;
332
+ const accountVerification = input.data.account_verification;
333
+ const claims = {
334
+ operator_id: operatorId,
335
+ kyc_level: accountVerification?.kyc_level ?? operatorVerification?.level ?? "none",
336
+ sanctions_clear: accountVerification?.sanctions_clear === true,
337
+ age_bracket: accountVerification?.age_bracket ?? "unknown",
338
+ jurisdiction: accountVerification?.jurisdiction ?? "",
339
+ verified_at: accountVerification?.verified_at ?? operatorVerification?.verified_at ?? null,
340
+ verify_url: input.data.verify_url ?? null,
341
+ issuer: "https://agentscore.sh"
342
+ };
343
+ baseCapabilities.push({
344
+ name: AGENTSCORE_CAPABILITY_NAME,
345
+ version: AGENTSCORE_CAPABILITY_VERSION,
346
+ schema: input.agentscoreSchemaUrl ?? "https://agentscore.sh/schemas/ucp/agentscore-identity.v1.json",
347
+ claims
348
+ });
349
+ }
350
+ }
351
+ const profile = {
352
+ version: input.version ?? DEFAULT_VERSION,
353
+ spec: SPEC_URL,
354
+ services: input.services,
355
+ capabilities: baseCapabilities,
356
+ payment_handlers: input.payment_handlers ?? [],
357
+ signing_keys: input.signing_keys
358
+ };
359
+ if (input.name !== void 0) profile.name = input.name;
360
+ if (input.extras) Object.assign(profile, input.extras);
361
+ return profile;
362
+ }
363
+ var AGENTSCORE_UCP_CAPABILITY = AGENTSCORE_CAPABILITY_NAME;
364
+
365
+ // src/identity/policy.ts
366
+ function policyToGateOptions(policy, base) {
367
+ if (!policy || !policy.enforcement) return null;
368
+ return {
369
+ apiKey: base.apiKey,
370
+ ...base.baseUrl !== void 0 && { baseUrl: base.baseUrl },
371
+ ...policy.requireKyc !== void 0 && { requireKyc: policy.requireKyc },
372
+ ...policy.requireSanctionsClear !== void 0 && {
373
+ requireSanctionsClear: policy.requireSanctionsClear
374
+ },
375
+ ...policy.minAge !== void 0 && { minAge: policy.minAge },
376
+ ...policy.allowedJurisdictions !== void 0 && {
377
+ allowedJurisdictions: [...policy.allowedJurisdictions]
378
+ }
379
+ };
380
+ }
381
+ async function runGateWithEnforcement(enforcement, runGate) {
382
+ if (!runGate || !enforcement) return { status: "anonymous" };
383
+ const outcome = await runGate();
384
+ if (outcome.ok) return { status: "verified" };
385
+ if (enforcement === "hard") {
386
+ return {
387
+ status: "denied",
388
+ denialStatus: outcome.status,
389
+ denialBody: outcome.body,
390
+ ...outcome.reason !== void 0 && { denialReason: outcome.reason }
391
+ };
392
+ }
393
+ return {
394
+ status: "unverified",
395
+ denialStatus: outcome.status,
396
+ denialBody: outcome.body,
397
+ ...outcome.reason !== void 0 && { denialReason: outcome.reason }
398
+ };
399
+ }
400
+ function shippingCountryAllowed(country, policy) {
401
+ if (!policy?.allowedShippingCountries || policy.allowedShippingCountries.length === 0) return true;
402
+ const allowed = new Set(policy.allowedShippingCountries.map((c) => c.toUpperCase()));
403
+ return allowed.has(country.toUpperCase());
404
+ }
405
+ function shippingStateAllowed(state, country, policy) {
406
+ if (!policy?.allowedShippingStates || policy.allowedShippingStates.length === 0) return true;
407
+ if (country.toUpperCase() !== "US") return true;
408
+ const allowed = new Set(policy.allowedShippingStates.map((s) => s.toUpperCase()));
409
+ return allowed.has(state.toUpperCase());
410
+ }
411
+ // Annotate the CommonJS export names for ESM import in node:
412
+ 0 && (module.exports = {
413
+ AGENTSCORE_UCP_CAPABILITY,
414
+ FIXABLE_DENIAL_REASONS,
415
+ buildA2AAgentCard,
416
+ buildAgentMemoryHint,
417
+ buildContactSupportNextSteps,
418
+ buildSignerMismatchBody,
419
+ buildUCPProfile,
420
+ denialReasonStatus,
421
+ denialReasonToBody,
422
+ extractPaymentSigner,
423
+ extractPaymentSignerAddress,
424
+ isFixableDenial,
425
+ policyToGateOptions,
426
+ readX402PaymentHeader,
427
+ runGateWithEnforcement,
428
+ shippingCountryAllowed,
429
+ shippingStateAllowed,
430
+ verificationAgentInstructions
431
+ });
432
+ //# sourceMappingURL=index.js.map