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