@astrasyncai/verification-gateway 5.20.0 → 5.21.1

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 (95) hide show
  1. package/CHANGELOG.md +62 -3
  2. package/README.md +2 -2
  3. package/dist/adapters/express.d.mts +1 -1
  4. package/dist/adapters/express.d.ts +1 -1
  5. package/dist/adapters/express.js +1 -1
  6. package/dist/adapters/express.js.map +1 -1
  7. package/dist/adapters/express.mjs +1 -1
  8. package/dist/adapters/express.mjs.map +1 -1
  9. package/dist/adapters/mcp.d.mts +1 -1
  10. package/dist/adapters/mcp.d.ts +1 -1
  11. package/dist/adapters/mcp.js +1 -1
  12. package/dist/adapters/mcp.js.map +1 -1
  13. package/dist/adapters/mcp.mjs +1 -1
  14. package/dist/adapters/mcp.mjs.map +1 -1
  15. package/dist/adapters/nextjs.d.mts +1 -1
  16. package/dist/adapters/nextjs.d.ts +1 -1
  17. package/dist/adapters/nextjs.js +1 -1
  18. package/dist/adapters/nextjs.js.map +1 -1
  19. package/dist/adapters/nextjs.mjs +1 -1
  20. package/dist/adapters/nextjs.mjs.map +1 -1
  21. package/dist/adapters/sdk.d.mts +8 -31
  22. package/dist/adapters/sdk.d.ts +8 -31
  23. package/dist/adapters/sdk.js +8 -22
  24. package/dist/adapters/sdk.js.map +1 -1
  25. package/dist/adapters/sdk.mjs +8 -22
  26. package/dist/adapters/sdk.mjs.map +1 -1
  27. package/dist/agent/index.js +1 -1
  28. package/dist/agent/index.js.map +1 -1
  29. package/dist/agent/index.mjs +1 -1
  30. package/dist/agent/index.mjs.map +1 -1
  31. package/dist/bin/astrasync-claude-hook.js +2 -2
  32. package/dist/bin/astrasync-codex-hook.js +2 -2
  33. package/dist/bin/astrasync-guard.js +2 -2
  34. package/dist/bin/astrasync.js +15 -2
  35. package/dist/browser/background.js +2 -2
  36. package/dist/browser/background.js.map +1 -1
  37. package/dist/browser/background.mjs +2 -2
  38. package/dist/browser/background.mjs.map +1 -1
  39. package/dist/cli/index.js +1 -1
  40. package/dist/cli/index.js.map +1 -1
  41. package/dist/cli/index.mjs +1 -1
  42. package/dist/cli/index.mjs.map +1 -1
  43. package/dist/codex/index.js +2 -2
  44. package/dist/codex/index.js.map +1 -1
  45. package/dist/codex/index.mjs +2 -2
  46. package/dist/codex/index.mjs.map +1 -1
  47. package/dist/cursor/extension.js +2 -2
  48. package/dist/cursor/extension.js.map +1 -1
  49. package/dist/cursor/extension.mjs +2 -2
  50. package/dist/cursor/extension.mjs.map +1 -1
  51. package/dist/edge-config.d.mts +1 -1
  52. package/dist/edge-config.d.ts +1 -1
  53. package/dist/edge-config.js +1 -1
  54. package/dist/edge-config.js.map +1 -1
  55. package/dist/edge-config.mjs +1 -1
  56. package/dist/edge-config.mjs.map +1 -1
  57. package/dist/edge-core/index.d.mts +1 -1
  58. package/dist/edge-core/index.d.ts +1 -1
  59. package/dist/edge-core/index.js +1 -1
  60. package/dist/edge-core/index.js.map +1 -1
  61. package/dist/edge-core/index.mjs +1 -1
  62. package/dist/edge-core/index.mjs.map +1 -1
  63. package/dist/gateway/gateway.js +2 -2
  64. package/dist/gateway/gateway.js.map +1 -1
  65. package/dist/gateway/gateway.mjs +2 -2
  66. package/dist/gateway/gateway.mjs.map +1 -1
  67. package/dist/git-trigger/git-hooks.d.mts +1 -1
  68. package/dist/git-trigger/git-hooks.d.ts +1 -1
  69. package/dist/index.d.mts +156 -34
  70. package/dist/index.d.ts +156 -34
  71. package/dist/index.js +327 -40
  72. package/dist/index.js.map +1 -1
  73. package/dist/index.mjs +319 -40
  74. package/dist/index.mjs.map +1 -1
  75. package/dist/registration/index.js +1 -1
  76. package/dist/registration/index.js.map +1 -1
  77. package/dist/registration/index.mjs +1 -1
  78. package/dist/registration/index.mjs.map +1 -1
  79. package/dist/transport/index.js +1 -1
  80. package/dist/transport/index.js.map +1 -1
  81. package/dist/transport/index.mjs +1 -1
  82. package/dist/transport/index.mjs.map +1 -1
  83. package/dist/{types-D37aSQ9c.d.mts → types-B4zhOAlq.d.mts} +5 -0
  84. package/dist/{types-Dn8tXnei.d.ts → types-CtBXnWuV.d.ts} +5 -0
  85. package/dist/{types-CxjqmPl-.d.mts → types-DHHyXtuZ.d.mts} +5 -0
  86. package/dist/{types-CxjqmPl-.d.ts → types-DHHyXtuZ.d.ts} +5 -0
  87. package/dist/ui/index.d.mts +1 -1
  88. package/dist/ui/index.d.ts +1 -1
  89. package/dist/verify.d.mts +1 -1
  90. package/dist/verify.d.ts +1 -1
  91. package/dist/verify.js +1 -1
  92. package/dist/verify.js.map +1 -1
  93. package/dist/verify.mjs +1 -1
  94. package/dist/verify.mjs.map +1 -1
  95. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ __export(src_exports, {
44
44
  DECLARED_SOURCE_MAX: () => DECLARED_SOURCE_MAX,
45
45
  DEFAULT_EDGE_CONFIG: () => DEFAULT_EDGE_CONFIG,
46
46
  DEFAULT_IDEMPOTENCY_TTL_MS: () => DEFAULT_IDEMPOTENCY_TTL_MS,
47
+ ISSUER_PROGRAM_HEADER: () => ISSUER_PROGRAM_HEADER,
47
48
  KYDRequiredError: () => KYDRequiredError,
48
49
  MAX_HEADERS: () => MAX_HEADERS,
49
50
  MAX_HEADER_VALUE_BYTES: () => MAX_HEADER_VALUE_BYTES,
@@ -102,6 +103,7 @@ __export(src_exports, {
102
103
  closedPaymentMandate: () => closedPaymentMandate,
103
104
  contentDigest: () => contentDigest,
104
105
  createAcpCheckoutKit: () => createAcpCheckoutKit,
106
+ createAgentCommerce: () => createAgentCommerce,
105
107
  createKbHop: () => createKbHop,
106
108
  createMcpMiddleware: () => createMcpMiddleware,
107
109
  createUcpCheckoutKit: () => createUcpCheckoutKit,
@@ -123,6 +125,7 @@ __export(src_exports, {
123
125
  fetchRoutes: () => fetchRoutes,
124
126
  fetchUcpProfile: () => fetchUcpProfile,
125
127
  finishIdempotent: () => finishIdempotent,
128
+ fromFeed: () => fromFeed,
126
129
  getCachedWellKnownUrls: () => getCachedWellKnownUrls,
127
130
  getEdgeConfig: () => getEdgeConfig,
128
131
  getTrustLevel: () => getTrustLevel,
@@ -138,6 +141,7 @@ __export(src_exports, {
138
141
  isVerificationUnavailable: () => isVerificationUnavailable,
139
142
  isVerifiedHopValidFor: () => isVerifiedHopValidFor,
140
143
  issueDelegateSdJwt: () => issueDelegateSdJwt,
144
+ issuerOfferPrice: () => issuerOfferPrice,
141
145
  matchEdgePathRule: () => matchEdgePathRule,
142
146
  matchPlatformSignature: () => matchPlatformSignature,
143
147
  matchRoutePattern: () => matchRoutePattern,
@@ -148,6 +152,7 @@ __export(src_exports, {
148
152
  onVerificationResult: () => onVerificationResult,
149
153
  openCheckoutMandate: () => openCheckoutMandate,
150
154
  openPaymentMandate: () => openPaymentMandate,
155
+ parseFeed: () => parseFeed,
151
156
  parseLocalPolicyYaml: () => parseYaml,
152
157
  parseMppCredential: () => parseMppCredential,
153
158
  parseUcpAgentHeader: () => parseUcpAgentHeader,
@@ -156,6 +161,8 @@ __export(src_exports, {
156
161
  parseX402Payment: () => parseX402Payment,
157
162
  pollStepUpStatus: () => pollStepUpStatus,
158
163
  prefetchWellKnown: () => prefetchWellKnown,
164
+ priceForAgent: () => priceForAgent,
165
+ pricingContextFrom: () => pricingContextFrom,
159
166
  quickVerify: () => quickVerify,
160
167
  recordDecision: () => recordDecision2,
161
168
  reportAttempt: () => reportAttempt,
@@ -169,6 +176,7 @@ __export(src_exports, {
169
176
  sdkFetch: () => sdkFetch,
170
177
  sendUcpWebhook: () => sendUcpWebhook,
171
178
  serializeVerifiedHop: () => serializeVerifiedHop,
179
+ serveAgentCatalog: () => serveAgentCatalog,
172
180
  setMcpMeta: () => setMcpMeta,
173
181
  signHttpRequest: () => signHttpRequest,
174
182
  signRootMandate: () => signRootMandate,
@@ -221,7 +229,7 @@ function getTrustLevel(score) {
221
229
  }
222
230
 
223
231
  // src/version.ts
224
- var SDK_VERSION = "5.20.0";
232
+ var SDK_VERSION = "5.21.1";
225
233
 
226
234
  // src/http.ts
227
235
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -3992,37 +4000,23 @@ var VerificationGatewayClient = class {
3992
4000
  }
3993
4001
  return json4.data;
3994
4002
  }
3995
- /**
3996
- * 5.20.0 (round 29.1): change an endpoint's OPERATIONAL URLs with this
3997
- * client's API key — `PATCH /api/endpoints/:id`. Accepts the key of the
3998
- * endpoint's owner, or a personal key of an individual with an active seat
3999
- * in the owning organisation. Policy (rules, trust floor, challenge, edge
4000
- * config) stays dashboard-only. `null` clears a field. The owner is alerted
4001
- * when `eventsUrl` changes.
4002
- *
4003
- * @param endpointId the ASTRAE id (defaults to the client's `counterpartyId`)
4004
- * @returns the endpoint as stored, plus `changed` (the fields that changed)
4005
- * @throws AstraSyncError — 400 `UNKNOWN_FIELDS` / validation, 401/403, 404
4006
- */
4007
- async updateEndpoint(endpointId, patch) {
4008
- return this.endpointCall("PATCH", endpointId, "", patch);
4009
- }
4010
4003
  /**
4011
4004
  * 5.20.0 (round 29.1): ask AstraSync to send ONE signed step-up event to the
4012
4005
  * endpoint's Events URL now — `POST /api/endpoints/:id/events/test`.
4013
4006
  * Delivered synchronously, outside the event outbox (random `eventId`, no
4014
4007
  * retries), signed with the endpoint's webhook secret like a real event.
4015
- * Without `approvalId` the payload is synthetic (a kit acknowledges and
4016
- * ignores it). With the id of a held kit approval at this endpoint the
4017
- * payload is the real one, so your resume path runs: `approved` makes the
4018
- * kit re-confirm (held again — nothing is charged); `denied` / `expired` /
4019
- * `lapsed` release the session.
4008
+ * The payload is synthetic (`approvalId: "test_…"`); a kit acknowledges and
4009
+ * ignores it.
4010
+ *
4011
+ * 5.21.0 (shops' item 48): synthetic only. Sending a real held approval's
4012
+ * payload (which releases or re-drives that checkout) is dashboard-only, so
4013
+ * a leaked API key can't do it.
4020
4014
  *
4021
4015
  * Resolves even when your endpoint refused the event (`delivered: false`,
4022
4016
  * with `responseCode` / `error`).
4023
4017
  */
4024
4018
  async sendTestEvent(endpointId, options) {
4025
- return this.endpointCall("POST", endpointId, "/events/test", options);
4019
+ return this.endpointCall("POST", endpointId, "/events/test", { type: options.type });
4026
4020
  }
4027
4021
  async endpointCall(method, endpointId, suffix, body) {
4028
4022
  const id = endpointId ?? this.config.counterpartyId;
@@ -9213,13 +9207,13 @@ function requireLoader() {
9213
9207
  throwError(state, "ill-formed argument of the YAML directive");
9214
9208
  }
9215
9209
  const major = parseInt(match[1], 10);
9216
- const minor = parseInt(match[2], 10);
9210
+ const minor2 = parseInt(match[2], 10);
9217
9211
  if (major !== 1) {
9218
9212
  throwError(state, "unacceptable YAML version of the document");
9219
9213
  }
9220
9214
  state.version = args[0];
9221
- state.checkLineBreaks = minor < 2;
9222
- if (minor !== 1 && minor !== 2) {
9215
+ state.checkLineBreaks = minor2 < 2;
9216
+ if (minor2 !== 1 && minor2 !== 2) {
9223
9217
  throwWarning(state, "unsupported YAML version of the document");
9224
9218
  }
9225
9219
  },
@@ -11715,6 +11709,228 @@ async function sendUcpWebhook(opts) {
11715
11709
  return { ok: false, status: last, attempts };
11716
11710
  }
11717
11711
 
11712
+ // src/ucp/agent-commerce.ts
11713
+ var ISSUER_PROGRAM_HEADER = "X-Astra-Issuer-Program";
11714
+ function issuerOfferPrice(priceMinor, percentOff) {
11715
+ if (!percentOff) return priceMinor;
11716
+ const pct = Math.min(100, Math.max(0, percentOff));
11717
+ return Math.max(0, Math.round(priceMinor * (1 - pct / 100)));
11718
+ }
11719
+ function priceForAgent(rules, sku, basePriceMinor, ctx) {
11720
+ const rule = rules?.products?.[sku];
11721
+ let price = rule?.priceMinor ?? basePriceMinor;
11722
+ if (ctx.verified && rules?.verifiedPercentOff) {
11723
+ price = issuerOfferPrice(price, rules.verifiedPercentOff);
11724
+ }
11725
+ const offer = ctx.verified && ctx.issuerProgram && rule?.issuerEligible !== false ? rules?.offers?.find((o) => o.program === ctx.issuerProgram) : void 0;
11726
+ if (offer?.pricePercentOff) {
11727
+ return {
11728
+ priceMinor: issuerOfferPrice(price, offer.pricePercentOff),
11729
+ regularMinor: price,
11730
+ issuerProgram: offer.program
11731
+ };
11732
+ }
11733
+ return { priceMinor: price };
11734
+ }
11735
+ function visibleToAgent(rules, sku, ctx) {
11736
+ if (!ctx.verified && rules?.hideFromUnverified) return false;
11737
+ return rules?.products?.[sku]?.visible !== false;
11738
+ }
11739
+ function createAgentCommerce(opts) {
11740
+ const f = opts.fetch ?? sdkFetch;
11741
+ let current = null;
11742
+ let kitReport;
11743
+ const refreshMs = opts.refreshMs ?? 5 * 6e4;
11744
+ async function refresh() {
11745
+ try {
11746
+ const headers = {
11747
+ Accept: "application/json",
11748
+ Authorization: `Bearer ${opts.apiKey}`,
11749
+ "X-AstraSync-SDK-Version": SDK_VERSION
11750
+ };
11751
+ if (kitReport) {
11752
+ headers["X-AstraSync-Kit-Report"] = Buffer.from(JSON.stringify(kitReport)).toString(
11753
+ "base64url"
11754
+ );
11755
+ }
11756
+ const res = await f(
11757
+ `${opts.apiBaseUrl.replace(/\/+$/, "")}/endpoints/${encodeURIComponent(
11758
+ opts.counterpartyId
11759
+ )}/agent-commerce`,
11760
+ { method: "GET", headers }
11761
+ );
11762
+ if (!res.ok) return;
11763
+ const body = await res.json();
11764
+ if (body.data && typeof body.data.version === "number") current = body.data;
11765
+ } catch {
11766
+ }
11767
+ }
11768
+ const timer = refreshMs > 0 ? setInterval(() => {
11769
+ void refresh();
11770
+ }, refreshMs) : null;
11771
+ timer?.unref?.();
11772
+ void refresh();
11773
+ return {
11774
+ rules: () => current,
11775
+ refresh,
11776
+ price: (sku, base, ctx) => priceForAgent(current, sku, base, ctx),
11777
+ visible: (sku, ctx) => visibleToAgent(current, sku, ctx),
11778
+ report: (r) => {
11779
+ kitReport = { ...kitReport, ...r };
11780
+ },
11781
+ stop: () => {
11782
+ if (timer) clearInterval(timer);
11783
+ }
11784
+ };
11785
+ }
11786
+ function pricingContextFrom(headers) {
11787
+ const astraId = headers.get("x-astra-id");
11788
+ const hop = parseVerifiedHop(headers.get(MCP_VERIFIED_HOP_HEADER.toLowerCase()));
11789
+ const verified = !!astraId && (!hop || hop.astraId === astraId && Date.now() - hop.checkedAt <= MCP_VERIFIED_HOP_MAX_AGE_MS);
11790
+ const program = headers.get(ISSUER_PROGRAM_HEADER.toLowerCase());
11791
+ return {
11792
+ verified,
11793
+ ...verified && program && /^[a-z0-9-]{2,40}$/.test(program) && { issuerProgram: program }
11794
+ };
11795
+ }
11796
+ function minor(value) {
11797
+ const n = typeof value === "number" ? value : Number(String(value ?? "").replace(/[^\d.]/g, ""));
11798
+ return Number.isFinite(n) && n >= 0 ? Math.round(n * 100) : null;
11799
+ }
11800
+ function fromFeed(url, options = {}) {
11801
+ const f = options.fetch ?? fetch;
11802
+ let cache4 = null;
11803
+ return async () => {
11804
+ if (cache4 && Date.now() - cache4.at < 6e4) return cache4.products;
11805
+ const res = await f(url, {
11806
+ headers: { Accept: "application/json, application/xml, text/csv" }
11807
+ });
11808
+ if (!res.ok) throw new Error(`Product feed ${url} answered ${res.status}`);
11809
+ const text = await res.text();
11810
+ const products = parseFeed(text, options.currency ?? "AUD");
11811
+ cache4 = { at: Date.now(), products };
11812
+ return products;
11813
+ };
11814
+ }
11815
+ function parseFeed(text, currency) {
11816
+ const trimmed = text.trimStart();
11817
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
11818
+ const json4 = JSON.parse(trimmed);
11819
+ const list = Array.isArray(json4) ? json4 : json4.products ?? json4.items ?? [];
11820
+ return list.flatMap((p) => {
11821
+ const variant = p.variants?.[0];
11822
+ const price = minor(variant?.price ?? p.price);
11823
+ const sku = String(variant?.sku || p.sku || p.id || "");
11824
+ if (!sku || price === null) return [];
11825
+ const images = Array.isArray(p.images) ? p.images.map(
11826
+ (i) => typeof i === "string" ? i : i.src ?? ""
11827
+ ) : [p.image_url, p.image].filter((x) => typeof x === "string");
11828
+ return [
11829
+ {
11830
+ sku,
11831
+ name: String(p.title ?? p.name ?? sku),
11832
+ priceMinor: price,
11833
+ currency: String(p.currency ?? currency),
11834
+ ...typeof p.description === "string" && { description: p.description },
11835
+ imageUrls: images.filter((u) => /^https:\/\//.test(u)),
11836
+ inStock: variant ? variant.available !== false : p.in_stock !== false
11837
+ }
11838
+ ];
11839
+ });
11840
+ }
11841
+ if (trimmed.startsWith("<")) {
11842
+ const items = trimmed.split(/<item[\s>]|<entry[\s>]/).slice(1);
11843
+ return items.flatMap((chunk) => {
11844
+ const tag = (name) => {
11845
+ const m = new RegExp(`<(?:g:)?${name}[^>]*>([\\s\\S]*?)</(?:g:)?${name}>`).exec(chunk);
11846
+ return m ? m[1].replace(/<!\[CDATA\[|\]\]>/g, "").trim() : void 0;
11847
+ };
11848
+ const sku = tag("id");
11849
+ const price = minor(tag("price"));
11850
+ if (!sku || price === null) return [];
11851
+ const extra = [...chunk.matchAll(/<g:additional_image_link>([^<]+)</g)].map(
11852
+ (m) => m[1].trim()
11853
+ );
11854
+ return [
11855
+ {
11856
+ sku,
11857
+ name: tag("title") ?? sku,
11858
+ priceMinor: price,
11859
+ currency: /[A-Z]{3}/.exec(tag("price") ?? "")?.[0] ?? currency,
11860
+ imageUrls: [tag("image_link"), ...extra].filter(
11861
+ (u) => !!u && /^https:\/\//.test(u)
11862
+ ),
11863
+ inStock: (tag("availability") ?? "in stock").replace(/_/g, " ") !== "out of stock"
11864
+ }
11865
+ ];
11866
+ });
11867
+ }
11868
+ const [head, ...rows] = trimmed.split(/\r?\n/).filter(Boolean);
11869
+ const cols = head.split(",").map((c) => c.trim().toLowerCase());
11870
+ const at = (r, ...names) => {
11871
+ const i = cols.findIndex((c) => names.includes(c));
11872
+ return i >= 0 ? r[i]?.trim() : void 0;
11873
+ };
11874
+ return rows.flatMap((line) => {
11875
+ const r = line.split(",");
11876
+ const sku = at(r, "id", "sku");
11877
+ const price = minor(at(r, "price"));
11878
+ if (!sku || price === null) return [];
11879
+ const image = at(r, "image_link", "image_url", "image");
11880
+ return [
11881
+ {
11882
+ sku,
11883
+ name: at(r, "title", "name") ?? sku,
11884
+ priceMinor: price,
11885
+ currency,
11886
+ imageUrls: image && /^https:\/\//.test(image) ? [image] : [],
11887
+ inStock: (at(r, "availability", "in_stock") ?? "in stock") !== "out of stock"
11888
+ }
11889
+ ];
11890
+ });
11891
+ }
11892
+ function serveAgentCatalog(opts) {
11893
+ return async (req, res) => {
11894
+ const ctx = pricingContextFrom({
11895
+ get: (name) => {
11896
+ const v = req.headers[name.toLowerCase()];
11897
+ return Array.isArray(v) ? v[0] ?? null : v ?? null;
11898
+ }
11899
+ });
11900
+ let products;
11901
+ try {
11902
+ products = await opts.products();
11903
+ } catch {
11904
+ res.status(503).json({ error: "catalog_unavailable" });
11905
+ return;
11906
+ }
11907
+ const rules = opts.commerce.rules();
11908
+ res.setHeader?.("Cache-Control", ctx.verified ? "private, no-store" : "public, max-age=60");
11909
+ res.json({
11910
+ products: products.filter((p) => opts.commerce.visible(p.sku, ctx)).map((p) => {
11911
+ const priced = opts.commerce.price(p.sku, p.priceMinor, ctx);
11912
+ const image = rules?.products?.[p.sku]?.imageUrl ?? p.imageUrls?.[0];
11913
+ return {
11914
+ sku: p.sku,
11915
+ name: p.name,
11916
+ ...p.description && { description: p.description },
11917
+ price: priced.priceMinor / 100,
11918
+ currency: p.currency,
11919
+ ...image && { image_url: image },
11920
+ in_stock: p.inStock !== false,
11921
+ ...p.url && { url: p.url },
11922
+ ...priced.issuerProgram && {
11923
+ issuer_offer: {
11924
+ program: priced.issuerProgram,
11925
+ regular_price: (priced.regularMinor ?? p.priceMinor) / 100
11926
+ }
11927
+ }
11928
+ };
11929
+ })
11930
+ });
11931
+ };
11932
+ }
11933
+
11718
11934
  // src/ucp/checkout-kit.ts
11719
11935
  var import_crypto8 = require("crypto");
11720
11936
  var import_jose3 = require("jose");
@@ -12533,6 +12749,7 @@ var clone = (v) => JSON.parse(JSON.stringify(v));
12533
12749
  var inFlight = (st) => st === "complete_in_progress" || st === "finishing";
12534
12750
  function createUcpCheckoutKit(opts) {
12535
12751
  const profile = buildUcpProfile(opts.profile);
12752
+ opts.agentCommerce?.report({ checkoutUrl: opts.profile.endpoint, protocols: ["ucp"] });
12536
12753
  const store = opts.store ?? new MemoryCheckoutStore();
12537
12754
  const idem = {
12538
12755
  store: opts.idempotencyStore ?? new MemoryIdempotencyStore(),
@@ -12706,9 +12923,7 @@ function createUcpCheckoutKit(opts) {
12706
12923
  delete s._approvalId;
12707
12924
  if (settled.status === "failed") {
12708
12925
  s.status = "ready_for_complete";
12709
- s.messages = [
12710
- ucpError("payment_failed", "The payment did not go through.", "recoverable")
12711
- ];
12926
+ s.messages = [ucpError("payment_failed", "The payment did not go through.", "recoverable")];
12712
12927
  await save(s);
12713
12928
  return;
12714
12929
  }
@@ -12742,9 +12957,10 @@ function createUcpCheckoutKit(opts) {
12742
12957
  const b = checkUcpAgentBinding(req.headers.get("ucp-agent"), identities);
12743
12958
  return b.ok ? null : b;
12744
12959
  }
12745
- async function priceLines(lines) {
12960
+ async function priceLines(lines, pricing = { verified: false }) {
12746
12961
  const out = [];
12747
12962
  const messages = [];
12963
+ let issuerProgram;
12748
12964
  for (const [i, l] of lines.entries()) {
12749
12965
  const q = Math.max(1, Math.floor(l.quantity ?? 1));
12750
12966
  const found = l.item?.id ? await opts.catalog(l.item.id, q) : null;
@@ -12760,6 +12976,22 @@ function createUcpCheckoutKit(opts) {
12760
12976
  );
12761
12977
  continue;
12762
12978
  }
12979
+ if (opts.agentCommerce) {
12980
+ if (!opts.agentCommerce.visible(item.id, pricing)) {
12981
+ messages.push(
12982
+ ucpError(
12983
+ "item_unavailable",
12984
+ `Item ${item.id} is unavailable.`,
12985
+ "recoverable",
12986
+ `$.line_items[${i}]`
12987
+ )
12988
+ );
12989
+ continue;
12990
+ }
12991
+ const priced = opts.agentCommerce.price(item.id, item.price, pricing);
12992
+ item.price = priced.priceMinor;
12993
+ if (priced.issuerProgram) issuerProgram = priced.issuerProgram;
12994
+ }
12763
12995
  const amount = item.price * q;
12764
12996
  out.push({
12765
12997
  id: `li_${i + 1}`,
@@ -12775,6 +13007,7 @@ function createUcpCheckoutKit(opts) {
12775
13007
  return {
12776
13008
  lines: out,
12777
13009
  messages,
13010
+ issuerProgram,
12778
13011
  totals: [
12779
13012
  { type: "subtotal", amount: sum },
12780
13013
  { type: "total", amount: sum }
@@ -12944,7 +13177,11 @@ function createUcpCheckoutKit(opts) {
12944
13177
  ...checkoutJwt && { checkoutJwt },
12945
13178
  valueMajor: total(s) / 100,
12946
13179
  agentArtifacts,
12947
- metadata: { kitSessionId: s.id, protocol: "ucp" }
13180
+ metadata: {
13181
+ kitSessionId: s.id,
13182
+ protocol: "ucp",
13183
+ ...s._issuerProgram && { issuerProgram: s._issuerProgram }
13184
+ }
12948
13185
  });
12949
13186
  const binding2 = await bindAgent(req, result);
12950
13187
  if (binding2) {
@@ -13083,7 +13320,11 @@ function createUcpCheckoutKit(opts) {
13083
13320
  attemptId: s._attemptId,
13084
13321
  ...checkoutJwt && { checkoutJwt },
13085
13322
  valueMajor: total(s) / 100,
13086
- metadata: { kitSessionId: s.id, protocol: "ucp" },
13323
+ metadata: {
13324
+ kitSessionId: s.id,
13325
+ protocol: "ucp",
13326
+ ...s._issuerProgram && { issuerProgram: s._issuerProgram }
13327
+ },
13087
13328
  resumed: { ...s._approvalId && { approvalId: s._approvalId } }
13088
13329
  });
13089
13330
  if (isHeld(result)) {
@@ -13198,7 +13439,10 @@ function createUcpCheckoutKit(opts) {
13198
13439
  const caller = await resolveCallerScope(req, reqCtx, opts.resolveCallerId) ?? fallbackScope("ucp-profile", ctx.profileUrl);
13199
13440
  if (req.method === "POST" && path === "/checkout-sessions") {
13200
13441
  return withIdempotency2(req, body, path, caller, async () => {
13201
- const priced = await priceLines(parsed.line_items ?? []);
13442
+ const priced = await priceLines(
13443
+ parsed.line_items ?? [],
13444
+ pricingContextFrom(req.headers)
13445
+ );
13202
13446
  const webhookUrl = ctx.plat.ucp.capabilities?.[UCP_ORDER_CAPABILITY]?.[0]?.config?.webhook_url;
13203
13447
  const s2 = {
13204
13448
  id: `chk_${(0, import_crypto8.randomUUID)().replace(/-/g, "")}`,
@@ -13215,7 +13459,8 @@ function createUcpCheckoutKit(opts) {
13215
13459
  ...typeof webhookUrl === "string" && /^https:\/\//.test(webhookUrl) && { _webhookUrl: webhookUrl },
13216
13460
  ...req.headers.get("x-astra-checkout-session") && {
13217
13461
  _astraCheckoutSessionId: req.headers.get("x-astra-checkout-session").slice(0, 64)
13218
- }
13462
+ },
13463
+ ...priced.issuerProgram && { _issuerProgram: priced.issuerProgram }
13219
13464
  };
13220
13465
  if (!priced.lines.length) {
13221
13466
  return json2(
@@ -13260,8 +13505,13 @@ function createUcpCheckoutKit(opts) {
13260
13505
  if (inFlight(s.status)) return busy(s);
13261
13506
  if (s.status === "requires_escalation") return heldNoEdit(s);
13262
13507
  if (parsed.line_items) {
13263
- const priced = await priceLines(parsed.line_items);
13508
+ const priced = await priceLines(
13509
+ parsed.line_items,
13510
+ pricingContextFrom(req.headers)
13511
+ );
13264
13512
  s.line_items = priced.lines;
13513
+ if (priced.issuerProgram) s._issuerProgram = priced.issuerProgram;
13514
+ else delete s._issuerProgram;
13265
13515
  s.totals = priced.totals;
13266
13516
  s.messages = priced.messages;
13267
13517
  s.status = priced.lines.length && !priced.messages.length ? "ready_for_complete" : "incomplete";
@@ -13907,6 +14157,7 @@ function heldBody2(text) {
13907
14157
  }
13908
14158
  }
13909
14159
  function createAcpCheckoutKit(opts) {
14160
+ opts.agentCommerce?.report({ protocols: ["acp"] });
13910
14161
  const mem = /* @__PURE__ */ new Map();
13911
14162
  const store = opts.store ?? {
13912
14163
  get: async (id) => mem.get(id) ?? null,
@@ -13959,9 +14210,10 @@ function createAcpCheckoutKit(opts) {
13959
14210
  ...s.order && { order: s.order }
13960
14211
  };
13961
14212
  }
13962
- async function price(items) {
14213
+ async function price(items, pricing = { verified: false }) {
13963
14214
  const lines = [];
13964
14215
  const messages = [];
14216
+ let issuerProgram;
13965
14217
  for (const [i, it] of items.entries()) {
13966
14218
  const q = Math.max(1, Math.floor(it.quantity ?? 1));
13967
14219
  const found = it.id ? await opts.catalog(it.id, q) : null;
@@ -13976,6 +14228,21 @@ function createAcpCheckoutKit(opts) {
13976
14228
  });
13977
14229
  continue;
13978
14230
  }
14231
+ if (opts.agentCommerce) {
14232
+ if (!opts.agentCommerce.visible(c.id, pricing)) {
14233
+ messages.push({
14234
+ type: "error",
14235
+ code: "not_found",
14236
+ content: `Item ${c.id} not found.`,
14237
+ resolution: "recoverable",
14238
+ param: `$.line_items[${i}]`
14239
+ });
14240
+ continue;
14241
+ }
14242
+ const priced = opts.agentCommerce.price(c.id, c.price, pricing);
14243
+ c.price = priced.priceMinor;
14244
+ if (priced.issuerProgram) issuerProgram = priced.issuerProgram;
14245
+ }
13979
14246
  const amount = c.price * q;
13980
14247
  lines.push({
13981
14248
  id: `li_${i + 1}`,
@@ -13999,6 +14266,7 @@ function createAcpCheckoutKit(opts) {
13999
14266
  return {
14000
14267
  lines,
14001
14268
  messages,
14269
+ issuerProgram,
14002
14270
  totals: [
14003
14271
  { type: "subtotal", amount: sum },
14004
14272
  { type: "total", amount: sum }
@@ -14150,7 +14418,11 @@ function createAcpCheckoutKit(opts) {
14150
14418
  attemptId,
14151
14419
  valueMajor: total2(s) / 100,
14152
14420
  agentArtifacts,
14153
- metadata: { kitSessionId: s.id, protocol: "acp" }
14421
+ metadata: {
14422
+ kitSessionId: s.id,
14423
+ protocol: "acp",
14424
+ ...s._issuerProgram && { issuerProgram: s._issuerProgram }
14425
+ }
14154
14426
  });
14155
14427
  if (isHeld(result)) {
14156
14428
  s.status = "pending_approval";
@@ -14287,7 +14559,11 @@ function createAcpCheckoutKit(opts) {
14287
14559
  astraId: s._astraId,
14288
14560
  attemptId: s._attemptId,
14289
14561
  valueMajor: total2(s) / 100,
14290
- metadata: { kitSessionId: s.id, protocol: "acp" },
14562
+ metadata: {
14563
+ kitSessionId: s.id,
14564
+ protocol: "acp",
14565
+ ...s._issuerProgram && { issuerProgram: s._issuerProgram }
14566
+ },
14291
14567
  resumed: { ...s._approvalId && { approvalId: s._approvalId } }
14292
14568
  });
14293
14569
  if (isHeld(result)) {
@@ -14405,7 +14681,7 @@ function createAcpCheckoutKit(opts) {
14405
14681
  const items = parsed.line_items ?? parsed.items;
14406
14682
  if (!items?.length)
14407
14683
  return apiError(400, "missing", "line_items is required.", "$.line_items");
14408
- const p = await price(items);
14684
+ const p = await price(items, pricingContextFrom(req.headers));
14409
14685
  const s2 = {
14410
14686
  id: `cs_${(0, import_crypto12.randomUUID)().replace(/-/g, "")}`,
14411
14687
  status: p.lines.length && !p.messages.length ? "ready_for_payment" : "not_ready_for_payment",
@@ -14416,7 +14692,8 @@ function createAcpCheckoutKit(opts) {
14416
14692
  _caller: caller,
14417
14693
  ...req.headers.get("x-astra-checkout-session") && {
14418
14694
  _astraCheckoutSessionId: req.headers.get("x-astra-checkout-session").slice(0, 64)
14419
- }
14695
+ },
14696
+ ...p.issuerProgram && { _issuerProgram: p.issuerProgram }
14420
14697
  };
14421
14698
  if (s2.status === "ready_for_payment") {
14422
14699
  const v = await validate(s2);
@@ -14445,7 +14722,9 @@ function createAcpCheckoutKit(opts) {
14445
14722
  );
14446
14723
  const items = parsed.line_items ?? parsed.items;
14447
14724
  if (items) {
14448
- const p = await price(items);
14725
+ const p = await price(items, pricingContextFrom(req.headers));
14726
+ if (p.issuerProgram) s._issuerProgram = p.issuerProgram;
14727
+ else delete s._issuerProgram;
14449
14728
  Object.assign(s, {
14450
14729
  line_items: p.lines,
14451
14730
  totals: p.totals,
@@ -14596,6 +14875,7 @@ function expressHandler(kit, options = {}) {
14596
14875
  DECLARED_SOURCE_MAX,
14597
14876
  DEFAULT_EDGE_CONFIG,
14598
14877
  DEFAULT_IDEMPOTENCY_TTL_MS,
14878
+ ISSUER_PROGRAM_HEADER,
14599
14879
  KYDRequiredError,
14600
14880
  MAX_HEADERS,
14601
14881
  MAX_HEADER_VALUE_BYTES,
@@ -14654,6 +14934,7 @@ function expressHandler(kit, options = {}) {
14654
14934
  closedPaymentMandate,
14655
14935
  contentDigest,
14656
14936
  createAcpCheckoutKit,
14937
+ createAgentCommerce,
14657
14938
  createKbHop,
14658
14939
  createMcpMiddleware,
14659
14940
  createUcpCheckoutKit,
@@ -14675,6 +14956,7 @@ function expressHandler(kit, options = {}) {
14675
14956
  fetchRoutes,
14676
14957
  fetchUcpProfile,
14677
14958
  finishIdempotent,
14959
+ fromFeed,
14678
14960
  getCachedWellKnownUrls,
14679
14961
  getEdgeConfig,
14680
14962
  getTrustLevel,
@@ -14690,6 +14972,7 @@ function expressHandler(kit, options = {}) {
14690
14972
  isVerificationUnavailable,
14691
14973
  isVerifiedHopValidFor,
14692
14974
  issueDelegateSdJwt,
14975
+ issuerOfferPrice,
14693
14976
  matchEdgePathRule,
14694
14977
  matchPlatformSignature,
14695
14978
  matchRoutePattern,
@@ -14700,6 +14983,7 @@ function expressHandler(kit, options = {}) {
14700
14983
  onVerificationResult,
14701
14984
  openCheckoutMandate,
14702
14985
  openPaymentMandate,
14986
+ parseFeed,
14703
14987
  parseLocalPolicyYaml,
14704
14988
  parseMppCredential,
14705
14989
  parseUcpAgentHeader,
@@ -14708,6 +14992,8 @@ function expressHandler(kit, options = {}) {
14708
14992
  parseX402Payment,
14709
14993
  pollStepUpStatus,
14710
14994
  prefetchWellKnown,
14995
+ priceForAgent,
14996
+ pricingContextFrom,
14711
14997
  quickVerify,
14712
14998
  recordDecision,
14713
14999
  reportAttempt,
@@ -14721,6 +15007,7 @@ function expressHandler(kit, options = {}) {
14721
15007
  sdkFetch,
14722
15008
  sendUcpWebhook,
14723
15009
  serializeVerifiedHop,
15010
+ serveAgentCatalog,
14724
15011
  setMcpMeta,
14725
15012
  signHttpRequest,
14726
15013
  signRootMandate,