@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.mjs CHANGED
@@ -30,7 +30,7 @@ function getTrustLevel(score) {
30
30
  }
31
31
 
32
32
  // src/version.ts
33
- var SDK_VERSION = "5.20.0";
33
+ var SDK_VERSION = "5.21.1";
34
34
 
35
35
  // src/http.ts
36
36
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -3801,37 +3801,23 @@ var VerificationGatewayClient = class {
3801
3801
  }
3802
3802
  return json4.data;
3803
3803
  }
3804
- /**
3805
- * 5.20.0 (round 29.1): change an endpoint's OPERATIONAL URLs with this
3806
- * client's API key — `PATCH /api/endpoints/:id`. Accepts the key of the
3807
- * endpoint's owner, or a personal key of an individual with an active seat
3808
- * in the owning organisation. Policy (rules, trust floor, challenge, edge
3809
- * config) stays dashboard-only. `null` clears a field. The owner is alerted
3810
- * when `eventsUrl` changes.
3811
- *
3812
- * @param endpointId the ASTRAE id (defaults to the client's `counterpartyId`)
3813
- * @returns the endpoint as stored, plus `changed` (the fields that changed)
3814
- * @throws AstraSyncError — 400 `UNKNOWN_FIELDS` / validation, 401/403, 404
3815
- */
3816
- async updateEndpoint(endpointId, patch) {
3817
- return this.endpointCall("PATCH", endpointId, "", patch);
3818
- }
3819
3804
  /**
3820
3805
  * 5.20.0 (round 29.1): ask AstraSync to send ONE signed step-up event to the
3821
3806
  * endpoint's Events URL now — `POST /api/endpoints/:id/events/test`.
3822
3807
  * Delivered synchronously, outside the event outbox (random `eventId`, no
3823
3808
  * retries), signed with the endpoint's webhook secret like a real event.
3824
- * Without `approvalId` the payload is synthetic (a kit acknowledges and
3825
- * ignores it). With the id of a held kit approval at this endpoint the
3826
- * payload is the real one, so your resume path runs: `approved` makes the
3827
- * kit re-confirm (held again — nothing is charged); `denied` / `expired` /
3828
- * `lapsed` release the session.
3809
+ * The payload is synthetic (`approvalId: "test_…"`); a kit acknowledges and
3810
+ * ignores it.
3811
+ *
3812
+ * 5.21.0 (shops' item 48): synthetic only. Sending a real held approval's
3813
+ * payload (which releases or re-drives that checkout) is dashboard-only, so
3814
+ * a leaked API key can't do it.
3829
3815
  *
3830
3816
  * Resolves even when your endpoint refused the event (`delivered: false`,
3831
3817
  * with `responseCode` / `error`).
3832
3818
  */
3833
3819
  async sendTestEvent(endpointId, options) {
3834
- return this.endpointCall("POST", endpointId, "/events/test", options);
3820
+ return this.endpointCall("POST", endpointId, "/events/test", { type: options.type });
3835
3821
  }
3836
3822
  async endpointCall(method, endpointId, suffix, body) {
3837
3823
  const id = endpointId ?? this.config.counterpartyId;
@@ -9025,13 +9011,13 @@ function requireLoader() {
9025
9011
  throwError(state, "ill-formed argument of the YAML directive");
9026
9012
  }
9027
9013
  const major = parseInt(match[1], 10);
9028
- const minor = parseInt(match[2], 10);
9014
+ const minor2 = parseInt(match[2], 10);
9029
9015
  if (major !== 1) {
9030
9016
  throwError(state, "unacceptable YAML version of the document");
9031
9017
  }
9032
9018
  state.version = args[0];
9033
- state.checkLineBreaks = minor < 2;
9034
- if (minor !== 1 && minor !== 2) {
9019
+ state.checkLineBreaks = minor2 < 2;
9020
+ if (minor2 !== 1 && minor2 !== 2) {
9035
9021
  throwWarning(state, "unsupported YAML version of the document");
9036
9022
  }
9037
9023
  },
@@ -11527,6 +11513,228 @@ async function sendUcpWebhook(opts) {
11527
11513
  return { ok: false, status: last, attempts };
11528
11514
  }
11529
11515
 
11516
+ // src/ucp/agent-commerce.ts
11517
+ var ISSUER_PROGRAM_HEADER = "X-Astra-Issuer-Program";
11518
+ function issuerOfferPrice(priceMinor, percentOff) {
11519
+ if (!percentOff) return priceMinor;
11520
+ const pct = Math.min(100, Math.max(0, percentOff));
11521
+ return Math.max(0, Math.round(priceMinor * (1 - pct / 100)));
11522
+ }
11523
+ function priceForAgent(rules, sku, basePriceMinor, ctx) {
11524
+ const rule = rules?.products?.[sku];
11525
+ let price = rule?.priceMinor ?? basePriceMinor;
11526
+ if (ctx.verified && rules?.verifiedPercentOff) {
11527
+ price = issuerOfferPrice(price, rules.verifiedPercentOff);
11528
+ }
11529
+ const offer = ctx.verified && ctx.issuerProgram && rule?.issuerEligible !== false ? rules?.offers?.find((o) => o.program === ctx.issuerProgram) : void 0;
11530
+ if (offer?.pricePercentOff) {
11531
+ return {
11532
+ priceMinor: issuerOfferPrice(price, offer.pricePercentOff),
11533
+ regularMinor: price,
11534
+ issuerProgram: offer.program
11535
+ };
11536
+ }
11537
+ return { priceMinor: price };
11538
+ }
11539
+ function visibleToAgent(rules, sku, ctx) {
11540
+ if (!ctx.verified && rules?.hideFromUnverified) return false;
11541
+ return rules?.products?.[sku]?.visible !== false;
11542
+ }
11543
+ function createAgentCommerce(opts) {
11544
+ const f = opts.fetch ?? sdkFetch;
11545
+ let current = null;
11546
+ let kitReport;
11547
+ const refreshMs = opts.refreshMs ?? 5 * 6e4;
11548
+ async function refresh() {
11549
+ try {
11550
+ const headers = {
11551
+ Accept: "application/json",
11552
+ Authorization: `Bearer ${opts.apiKey}`,
11553
+ "X-AstraSync-SDK-Version": SDK_VERSION
11554
+ };
11555
+ if (kitReport) {
11556
+ headers["X-AstraSync-Kit-Report"] = Buffer.from(JSON.stringify(kitReport)).toString(
11557
+ "base64url"
11558
+ );
11559
+ }
11560
+ const res = await f(
11561
+ `${opts.apiBaseUrl.replace(/\/+$/, "")}/endpoints/${encodeURIComponent(
11562
+ opts.counterpartyId
11563
+ )}/agent-commerce`,
11564
+ { method: "GET", headers }
11565
+ );
11566
+ if (!res.ok) return;
11567
+ const body = await res.json();
11568
+ if (body.data && typeof body.data.version === "number") current = body.data;
11569
+ } catch {
11570
+ }
11571
+ }
11572
+ const timer = refreshMs > 0 ? setInterval(() => {
11573
+ void refresh();
11574
+ }, refreshMs) : null;
11575
+ timer?.unref?.();
11576
+ void refresh();
11577
+ return {
11578
+ rules: () => current,
11579
+ refresh,
11580
+ price: (sku, base, ctx) => priceForAgent(current, sku, base, ctx),
11581
+ visible: (sku, ctx) => visibleToAgent(current, sku, ctx),
11582
+ report: (r) => {
11583
+ kitReport = { ...kitReport, ...r };
11584
+ },
11585
+ stop: () => {
11586
+ if (timer) clearInterval(timer);
11587
+ }
11588
+ };
11589
+ }
11590
+ function pricingContextFrom(headers) {
11591
+ const astraId = headers.get("x-astra-id");
11592
+ const hop = parseVerifiedHop(headers.get(MCP_VERIFIED_HOP_HEADER.toLowerCase()));
11593
+ const verified = !!astraId && (!hop || hop.astraId === astraId && Date.now() - hop.checkedAt <= MCP_VERIFIED_HOP_MAX_AGE_MS);
11594
+ const program = headers.get(ISSUER_PROGRAM_HEADER.toLowerCase());
11595
+ return {
11596
+ verified,
11597
+ ...verified && program && /^[a-z0-9-]{2,40}$/.test(program) && { issuerProgram: program }
11598
+ };
11599
+ }
11600
+ function minor(value) {
11601
+ const n = typeof value === "number" ? value : Number(String(value ?? "").replace(/[^\d.]/g, ""));
11602
+ return Number.isFinite(n) && n >= 0 ? Math.round(n * 100) : null;
11603
+ }
11604
+ function fromFeed(url, options = {}) {
11605
+ const f = options.fetch ?? fetch;
11606
+ let cache4 = null;
11607
+ return async () => {
11608
+ if (cache4 && Date.now() - cache4.at < 6e4) return cache4.products;
11609
+ const res = await f(url, {
11610
+ headers: { Accept: "application/json, application/xml, text/csv" }
11611
+ });
11612
+ if (!res.ok) throw new Error(`Product feed ${url} answered ${res.status}`);
11613
+ const text = await res.text();
11614
+ const products = parseFeed(text, options.currency ?? "AUD");
11615
+ cache4 = { at: Date.now(), products };
11616
+ return products;
11617
+ };
11618
+ }
11619
+ function parseFeed(text, currency) {
11620
+ const trimmed = text.trimStart();
11621
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
11622
+ const json4 = JSON.parse(trimmed);
11623
+ const list = Array.isArray(json4) ? json4 : json4.products ?? json4.items ?? [];
11624
+ return list.flatMap((p) => {
11625
+ const variant = p.variants?.[0];
11626
+ const price = minor(variant?.price ?? p.price);
11627
+ const sku = String(variant?.sku || p.sku || p.id || "");
11628
+ if (!sku || price === null) return [];
11629
+ const images = Array.isArray(p.images) ? p.images.map(
11630
+ (i) => typeof i === "string" ? i : i.src ?? ""
11631
+ ) : [p.image_url, p.image].filter((x) => typeof x === "string");
11632
+ return [
11633
+ {
11634
+ sku,
11635
+ name: String(p.title ?? p.name ?? sku),
11636
+ priceMinor: price,
11637
+ currency: String(p.currency ?? currency),
11638
+ ...typeof p.description === "string" && { description: p.description },
11639
+ imageUrls: images.filter((u) => /^https:\/\//.test(u)),
11640
+ inStock: variant ? variant.available !== false : p.in_stock !== false
11641
+ }
11642
+ ];
11643
+ });
11644
+ }
11645
+ if (trimmed.startsWith("<")) {
11646
+ const items = trimmed.split(/<item[\s>]|<entry[\s>]/).slice(1);
11647
+ return items.flatMap((chunk) => {
11648
+ const tag = (name) => {
11649
+ const m = new RegExp(`<(?:g:)?${name}[^>]*>([\\s\\S]*?)</(?:g:)?${name}>`).exec(chunk);
11650
+ return m ? m[1].replace(/<!\[CDATA\[|\]\]>/g, "").trim() : void 0;
11651
+ };
11652
+ const sku = tag("id");
11653
+ const price = minor(tag("price"));
11654
+ if (!sku || price === null) return [];
11655
+ const extra = [...chunk.matchAll(/<g:additional_image_link>([^<]+)</g)].map(
11656
+ (m) => m[1].trim()
11657
+ );
11658
+ return [
11659
+ {
11660
+ sku,
11661
+ name: tag("title") ?? sku,
11662
+ priceMinor: price,
11663
+ currency: /[A-Z]{3}/.exec(tag("price") ?? "")?.[0] ?? currency,
11664
+ imageUrls: [tag("image_link"), ...extra].filter(
11665
+ (u) => !!u && /^https:\/\//.test(u)
11666
+ ),
11667
+ inStock: (tag("availability") ?? "in stock").replace(/_/g, " ") !== "out of stock"
11668
+ }
11669
+ ];
11670
+ });
11671
+ }
11672
+ const [head, ...rows] = trimmed.split(/\r?\n/).filter(Boolean);
11673
+ const cols = head.split(",").map((c) => c.trim().toLowerCase());
11674
+ const at = (r, ...names) => {
11675
+ const i = cols.findIndex((c) => names.includes(c));
11676
+ return i >= 0 ? r[i]?.trim() : void 0;
11677
+ };
11678
+ return rows.flatMap((line) => {
11679
+ const r = line.split(",");
11680
+ const sku = at(r, "id", "sku");
11681
+ const price = minor(at(r, "price"));
11682
+ if (!sku || price === null) return [];
11683
+ const image = at(r, "image_link", "image_url", "image");
11684
+ return [
11685
+ {
11686
+ sku,
11687
+ name: at(r, "title", "name") ?? sku,
11688
+ priceMinor: price,
11689
+ currency,
11690
+ imageUrls: image && /^https:\/\//.test(image) ? [image] : [],
11691
+ inStock: (at(r, "availability", "in_stock") ?? "in stock") !== "out of stock"
11692
+ }
11693
+ ];
11694
+ });
11695
+ }
11696
+ function serveAgentCatalog(opts) {
11697
+ return async (req, res) => {
11698
+ const ctx = pricingContextFrom({
11699
+ get: (name) => {
11700
+ const v = req.headers[name.toLowerCase()];
11701
+ return Array.isArray(v) ? v[0] ?? null : v ?? null;
11702
+ }
11703
+ });
11704
+ let products;
11705
+ try {
11706
+ products = await opts.products();
11707
+ } catch {
11708
+ res.status(503).json({ error: "catalog_unavailable" });
11709
+ return;
11710
+ }
11711
+ const rules = opts.commerce.rules();
11712
+ res.setHeader?.("Cache-Control", ctx.verified ? "private, no-store" : "public, max-age=60");
11713
+ res.json({
11714
+ products: products.filter((p) => opts.commerce.visible(p.sku, ctx)).map((p) => {
11715
+ const priced = opts.commerce.price(p.sku, p.priceMinor, ctx);
11716
+ const image = rules?.products?.[p.sku]?.imageUrl ?? p.imageUrls?.[0];
11717
+ return {
11718
+ sku: p.sku,
11719
+ name: p.name,
11720
+ ...p.description && { description: p.description },
11721
+ price: priced.priceMinor / 100,
11722
+ currency: p.currency,
11723
+ ...image && { image_url: image },
11724
+ in_stock: p.inStock !== false,
11725
+ ...p.url && { url: p.url },
11726
+ ...priced.issuerProgram && {
11727
+ issuer_offer: {
11728
+ program: priced.issuerProgram,
11729
+ regular_price: (priced.regularMinor ?? p.priceMinor) / 100
11730
+ }
11731
+ }
11732
+ };
11733
+ })
11734
+ });
11735
+ };
11736
+ }
11737
+
11530
11738
  // src/ucp/checkout-kit.ts
11531
11739
  import { createHash as createHash10, randomUUID as randomUUID2 } from "crypto";
11532
11740
  import { CompactSign as CompactSign2 } from "jose";
@@ -12350,6 +12558,7 @@ var clone = (v) => JSON.parse(JSON.stringify(v));
12350
12558
  var inFlight = (st) => st === "complete_in_progress" || st === "finishing";
12351
12559
  function createUcpCheckoutKit(opts) {
12352
12560
  const profile = buildUcpProfile(opts.profile);
12561
+ opts.agentCommerce?.report({ checkoutUrl: opts.profile.endpoint, protocols: ["ucp"] });
12353
12562
  const store = opts.store ?? new MemoryCheckoutStore();
12354
12563
  const idem = {
12355
12564
  store: opts.idempotencyStore ?? new MemoryIdempotencyStore(),
@@ -12523,9 +12732,7 @@ function createUcpCheckoutKit(opts) {
12523
12732
  delete s._approvalId;
12524
12733
  if (settled.status === "failed") {
12525
12734
  s.status = "ready_for_complete";
12526
- s.messages = [
12527
- ucpError("payment_failed", "The payment did not go through.", "recoverable")
12528
- ];
12735
+ s.messages = [ucpError("payment_failed", "The payment did not go through.", "recoverable")];
12529
12736
  await save(s);
12530
12737
  return;
12531
12738
  }
@@ -12559,9 +12766,10 @@ function createUcpCheckoutKit(opts) {
12559
12766
  const b = checkUcpAgentBinding(req.headers.get("ucp-agent"), identities);
12560
12767
  return b.ok ? null : b;
12561
12768
  }
12562
- async function priceLines(lines) {
12769
+ async function priceLines(lines, pricing = { verified: false }) {
12563
12770
  const out = [];
12564
12771
  const messages = [];
12772
+ let issuerProgram;
12565
12773
  for (const [i, l] of lines.entries()) {
12566
12774
  const q = Math.max(1, Math.floor(l.quantity ?? 1));
12567
12775
  const found = l.item?.id ? await opts.catalog(l.item.id, q) : null;
@@ -12577,6 +12785,22 @@ function createUcpCheckoutKit(opts) {
12577
12785
  );
12578
12786
  continue;
12579
12787
  }
12788
+ if (opts.agentCommerce) {
12789
+ if (!opts.agentCommerce.visible(item.id, pricing)) {
12790
+ messages.push(
12791
+ ucpError(
12792
+ "item_unavailable",
12793
+ `Item ${item.id} is unavailable.`,
12794
+ "recoverable",
12795
+ `$.line_items[${i}]`
12796
+ )
12797
+ );
12798
+ continue;
12799
+ }
12800
+ const priced = opts.agentCommerce.price(item.id, item.price, pricing);
12801
+ item.price = priced.priceMinor;
12802
+ if (priced.issuerProgram) issuerProgram = priced.issuerProgram;
12803
+ }
12580
12804
  const amount = item.price * q;
12581
12805
  out.push({
12582
12806
  id: `li_${i + 1}`,
@@ -12592,6 +12816,7 @@ function createUcpCheckoutKit(opts) {
12592
12816
  return {
12593
12817
  lines: out,
12594
12818
  messages,
12819
+ issuerProgram,
12595
12820
  totals: [
12596
12821
  { type: "subtotal", amount: sum },
12597
12822
  { type: "total", amount: sum }
@@ -12761,7 +12986,11 @@ function createUcpCheckoutKit(opts) {
12761
12986
  ...checkoutJwt && { checkoutJwt },
12762
12987
  valueMajor: total(s) / 100,
12763
12988
  agentArtifacts,
12764
- metadata: { kitSessionId: s.id, protocol: "ucp" }
12989
+ metadata: {
12990
+ kitSessionId: s.id,
12991
+ protocol: "ucp",
12992
+ ...s._issuerProgram && { issuerProgram: s._issuerProgram }
12993
+ }
12765
12994
  });
12766
12995
  const binding2 = await bindAgent(req, result);
12767
12996
  if (binding2) {
@@ -12900,7 +13129,11 @@ function createUcpCheckoutKit(opts) {
12900
13129
  attemptId: s._attemptId,
12901
13130
  ...checkoutJwt && { checkoutJwt },
12902
13131
  valueMajor: total(s) / 100,
12903
- metadata: { kitSessionId: s.id, protocol: "ucp" },
13132
+ metadata: {
13133
+ kitSessionId: s.id,
13134
+ protocol: "ucp",
13135
+ ...s._issuerProgram && { issuerProgram: s._issuerProgram }
13136
+ },
12904
13137
  resumed: { ...s._approvalId && { approvalId: s._approvalId } }
12905
13138
  });
12906
13139
  if (isHeld(result)) {
@@ -13015,7 +13248,10 @@ function createUcpCheckoutKit(opts) {
13015
13248
  const caller = await resolveCallerScope(req, reqCtx, opts.resolveCallerId) ?? fallbackScope("ucp-profile", ctx.profileUrl);
13016
13249
  if (req.method === "POST" && path === "/checkout-sessions") {
13017
13250
  return withIdempotency2(req, body, path, caller, async () => {
13018
- const priced = await priceLines(parsed.line_items ?? []);
13251
+ const priced = await priceLines(
13252
+ parsed.line_items ?? [],
13253
+ pricingContextFrom(req.headers)
13254
+ );
13019
13255
  const webhookUrl = ctx.plat.ucp.capabilities?.[UCP_ORDER_CAPABILITY]?.[0]?.config?.webhook_url;
13020
13256
  const s2 = {
13021
13257
  id: `chk_${randomUUID2().replace(/-/g, "")}`,
@@ -13032,7 +13268,8 @@ function createUcpCheckoutKit(opts) {
13032
13268
  ...typeof webhookUrl === "string" && /^https:\/\//.test(webhookUrl) && { _webhookUrl: webhookUrl },
13033
13269
  ...req.headers.get("x-astra-checkout-session") && {
13034
13270
  _astraCheckoutSessionId: req.headers.get("x-astra-checkout-session").slice(0, 64)
13035
- }
13271
+ },
13272
+ ...priced.issuerProgram && { _issuerProgram: priced.issuerProgram }
13036
13273
  };
13037
13274
  if (!priced.lines.length) {
13038
13275
  return json2(
@@ -13077,8 +13314,13 @@ function createUcpCheckoutKit(opts) {
13077
13314
  if (inFlight(s.status)) return busy(s);
13078
13315
  if (s.status === "requires_escalation") return heldNoEdit(s);
13079
13316
  if (parsed.line_items) {
13080
- const priced = await priceLines(parsed.line_items);
13317
+ const priced = await priceLines(
13318
+ parsed.line_items,
13319
+ pricingContextFrom(req.headers)
13320
+ );
13081
13321
  s.line_items = priced.lines;
13322
+ if (priced.issuerProgram) s._issuerProgram = priced.issuerProgram;
13323
+ else delete s._issuerProgram;
13082
13324
  s.totals = priced.totals;
13083
13325
  s.messages = priced.messages;
13084
13326
  s.status = priced.lines.length && !priced.messages.length ? "ready_for_complete" : "incomplete";
@@ -13735,6 +13977,7 @@ function heldBody2(text) {
13735
13977
  }
13736
13978
  }
13737
13979
  function createAcpCheckoutKit(opts) {
13980
+ opts.agentCommerce?.report({ protocols: ["acp"] });
13738
13981
  const mem = /* @__PURE__ */ new Map();
13739
13982
  const store = opts.store ?? {
13740
13983
  get: async (id) => mem.get(id) ?? null,
@@ -13787,9 +14030,10 @@ function createAcpCheckoutKit(opts) {
13787
14030
  ...s.order && { order: s.order }
13788
14031
  };
13789
14032
  }
13790
- async function price(items) {
14033
+ async function price(items, pricing = { verified: false }) {
13791
14034
  const lines = [];
13792
14035
  const messages = [];
14036
+ let issuerProgram;
13793
14037
  for (const [i, it] of items.entries()) {
13794
14038
  const q = Math.max(1, Math.floor(it.quantity ?? 1));
13795
14039
  const found = it.id ? await opts.catalog(it.id, q) : null;
@@ -13804,6 +14048,21 @@ function createAcpCheckoutKit(opts) {
13804
14048
  });
13805
14049
  continue;
13806
14050
  }
14051
+ if (opts.agentCommerce) {
14052
+ if (!opts.agentCommerce.visible(c.id, pricing)) {
14053
+ messages.push({
14054
+ type: "error",
14055
+ code: "not_found",
14056
+ content: `Item ${c.id} not found.`,
14057
+ resolution: "recoverable",
14058
+ param: `$.line_items[${i}]`
14059
+ });
14060
+ continue;
14061
+ }
14062
+ const priced = opts.agentCommerce.price(c.id, c.price, pricing);
14063
+ c.price = priced.priceMinor;
14064
+ if (priced.issuerProgram) issuerProgram = priced.issuerProgram;
14065
+ }
13807
14066
  const amount = c.price * q;
13808
14067
  lines.push({
13809
14068
  id: `li_${i + 1}`,
@@ -13827,6 +14086,7 @@ function createAcpCheckoutKit(opts) {
13827
14086
  return {
13828
14087
  lines,
13829
14088
  messages,
14089
+ issuerProgram,
13830
14090
  totals: [
13831
14091
  { type: "subtotal", amount: sum },
13832
14092
  { type: "total", amount: sum }
@@ -13978,7 +14238,11 @@ function createAcpCheckoutKit(opts) {
13978
14238
  attemptId,
13979
14239
  valueMajor: total2(s) / 100,
13980
14240
  agentArtifacts,
13981
- metadata: { kitSessionId: s.id, protocol: "acp" }
14241
+ metadata: {
14242
+ kitSessionId: s.id,
14243
+ protocol: "acp",
14244
+ ...s._issuerProgram && { issuerProgram: s._issuerProgram }
14245
+ }
13982
14246
  });
13983
14247
  if (isHeld(result)) {
13984
14248
  s.status = "pending_approval";
@@ -14115,7 +14379,11 @@ function createAcpCheckoutKit(opts) {
14115
14379
  astraId: s._astraId,
14116
14380
  attemptId: s._attemptId,
14117
14381
  valueMajor: total2(s) / 100,
14118
- metadata: { kitSessionId: s.id, protocol: "acp" },
14382
+ metadata: {
14383
+ kitSessionId: s.id,
14384
+ protocol: "acp",
14385
+ ...s._issuerProgram && { issuerProgram: s._issuerProgram }
14386
+ },
14119
14387
  resumed: { ...s._approvalId && { approvalId: s._approvalId } }
14120
14388
  });
14121
14389
  if (isHeld(result)) {
@@ -14233,7 +14501,7 @@ function createAcpCheckoutKit(opts) {
14233
14501
  const items = parsed.line_items ?? parsed.items;
14234
14502
  if (!items?.length)
14235
14503
  return apiError(400, "missing", "line_items is required.", "$.line_items");
14236
- const p = await price(items);
14504
+ const p = await price(items, pricingContextFrom(req.headers));
14237
14505
  const s2 = {
14238
14506
  id: `cs_${randomUUID3().replace(/-/g, "")}`,
14239
14507
  status: p.lines.length && !p.messages.length ? "ready_for_payment" : "not_ready_for_payment",
@@ -14244,7 +14512,8 @@ function createAcpCheckoutKit(opts) {
14244
14512
  _caller: caller,
14245
14513
  ...req.headers.get("x-astra-checkout-session") && {
14246
14514
  _astraCheckoutSessionId: req.headers.get("x-astra-checkout-session").slice(0, 64)
14247
- }
14515
+ },
14516
+ ...p.issuerProgram && { _issuerProgram: p.issuerProgram }
14248
14517
  };
14249
14518
  if (s2.status === "ready_for_payment") {
14250
14519
  const v = await validate(s2);
@@ -14273,7 +14542,9 @@ function createAcpCheckoutKit(opts) {
14273
14542
  );
14274
14543
  const items = parsed.line_items ?? parsed.items;
14275
14544
  if (items) {
14276
- const p = await price(items);
14545
+ const p = await price(items, pricingContextFrom(req.headers));
14546
+ if (p.issuerProgram) s._issuerProgram = p.issuerProgram;
14547
+ else delete s._issuerProgram;
14277
14548
  Object.assign(s, {
14278
14549
  line_items: p.lines,
14279
14550
  totals: p.totals,
@@ -14423,6 +14694,7 @@ export {
14423
14694
  DECLARED_SOURCE_MAX,
14424
14695
  DEFAULT_EDGE_CONFIG,
14425
14696
  DEFAULT_IDEMPOTENCY_TTL_MS,
14697
+ ISSUER_PROGRAM_HEADER,
14426
14698
  KYDRequiredError,
14427
14699
  MAX_HEADERS,
14428
14700
  MAX_HEADER_VALUE_BYTES,
@@ -14481,6 +14753,7 @@ export {
14481
14753
  closedPaymentMandate,
14482
14754
  contentDigest,
14483
14755
  createAcpCheckoutKit,
14756
+ createAgentCommerce,
14484
14757
  createKbHop,
14485
14758
  createMcpMiddleware,
14486
14759
  createUcpCheckoutKit,
@@ -14502,6 +14775,7 @@ export {
14502
14775
  fetchRoutes,
14503
14776
  fetchUcpProfile,
14504
14777
  finishIdempotent,
14778
+ fromFeed,
14505
14779
  getCachedWellKnownUrls,
14506
14780
  getEdgeConfig,
14507
14781
  getTrustLevel,
@@ -14517,6 +14791,7 @@ export {
14517
14791
  isVerificationUnavailable,
14518
14792
  isVerifiedHopValidFor,
14519
14793
  issueDelegateSdJwt,
14794
+ issuerOfferPrice,
14520
14795
  matchEdgePathRule,
14521
14796
  matchPlatformSignature,
14522
14797
  matchRoutePattern,
@@ -14527,6 +14802,7 @@ export {
14527
14802
  onVerificationResult,
14528
14803
  openCheckoutMandate,
14529
14804
  openPaymentMandate,
14805
+ parseFeed,
14530
14806
  parseYaml as parseLocalPolicyYaml,
14531
14807
  parseMppCredential,
14532
14808
  parseUcpAgentHeader,
@@ -14535,6 +14811,8 @@ export {
14535
14811
  parseX402Payment,
14536
14812
  pollStepUpStatus,
14537
14813
  prefetchWellKnown,
14814
+ priceForAgent,
14815
+ pricingContextFrom,
14538
14816
  quickVerify,
14539
14817
  recordDecision2 as recordDecision,
14540
14818
  reportAttempt,
@@ -14548,6 +14826,7 @@ export {
14548
14826
  sdkFetch,
14549
14827
  sendUcpWebhook,
14550
14828
  serializeVerifiedHop,
14829
+ serveAgentCatalog,
14551
14830
  setMcpMeta,
14552
14831
  signHttpRequest,
14553
14832
  signRootMandate,