@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.
- package/CHANGELOG.md +50 -3
- package/README.md +2 -2
- package/dist/adapters/express.d.mts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +1 -1
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +1 -1
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.d.ts +1 -1
- package/dist/adapters/mcp.js +1 -1
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +1 -1
- package/dist/adapters/nextjs.d.ts +1 -1
- package/dist/adapters/nextjs.js +1 -1
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +1 -1
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +8 -31
- package/dist/adapters/sdk.d.ts +8 -31
- package/dist/adapters/sdk.js +8 -22
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +8 -22
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +2 -2
- package/dist/bin/astrasync-codex-hook.js +2 -2
- package/dist/bin/astrasync-guard.js +2 -2
- package/dist/bin/astrasync.js +15 -2
- package/dist/browser/background.js +2 -2
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +2 -2
- package/dist/browser/background.mjs.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.js +2 -2
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +2 -2
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +2 -2
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +2 -2
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +1 -1
- package/dist/edge-config.d.ts +1 -1
- package/dist/edge-config.js +1 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +1 -1
- package/dist/edge-core/index.d.ts +1 -1
- package/dist/edge-core/index.js +1 -1
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +1 -1
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +2 -2
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +2 -2
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +1 -1
- package/dist/git-trigger/git-hooks.d.ts +1 -1
- package/dist/index.d.mts +152 -34
- package/dist/index.d.ts +152 -34
- package/dist/index.js +325 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +318 -40
- package/dist/index.mjs.map +1 -1
- package/dist/registration/index.js +1 -1
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/transport/index.js +1 -1
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-D37aSQ9c.d.mts → types-B4zhOAlq.d.mts} +5 -0
- package/dist/{types-Dn8tXnei.d.ts → types-CtBXnWuV.d.ts} +5 -0
- package/dist/{types-CxjqmPl-.d.mts → types-DHHyXtuZ.d.mts} +5 -0
- package/dist/{types-CxjqmPl-.d.ts → types-DHHyXtuZ.d.ts} +5 -0
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/verify.d.mts +1 -1
- package/dist/verify.d.ts +1 -1
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- 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.
|
|
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
|
-
*
|
|
4016
|
-
* ignores it
|
|
4017
|
-
*
|
|
4018
|
-
*
|
|
4019
|
-
*
|
|
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
|
|
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 =
|
|
9222
|
-
if (
|
|
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: {
|
|
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: {
|
|
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(
|
|
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(
|
|
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: {
|
|
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: {
|
|
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,
|