@payclaw/badge 0.7.1 → 0.8.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/README.md +68 -2
- package/dist/api/client.js +1 -1
- package/dist/api/client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +24 -11
- package/dist/index.js.map +1 -1
- package/dist/lib/device-auth.js +11 -3
- package/dist/lib/device-auth.js.map +1 -1
- package/dist/lib/parse-outcome.js +1 -0
- package/dist/lib/parse-outcome.js.map +1 -1
- package/dist/lib/report-badge-presented-handler.d.ts +7 -1
- package/dist/lib/report-badge-presented-handler.js +13 -2
- package/dist/lib/report-badge-presented-handler.js.map +1 -1
- package/dist/lib/report-badge.d.ts +1 -1
- package/dist/lib/report-badge.js +3 -1
- package/dist/lib/report-badge.js.map +1 -1
- package/dist/lib/storage.d.ts +5 -0
- package/dist/lib/storage.js +28 -0
- package/dist/lib/storage.js.map +1 -1
- package/dist/lib/ucp-manifest.d.ts +32 -0
- package/dist/lib/ucp-manifest.js +117 -0
- package/dist/lib/ucp-manifest.js.map +1 -0
- package/dist/lib/ucp-manifest.test.d.ts +1 -0
- package/dist/lib/ucp-manifest.test.js +92 -0
- package/dist/lib/ucp-manifest.test.js.map +1 -0
- package/dist/sampling.d.ts +4 -0
- package/dist/sampling.js +43 -6
- package/dist/sampling.js.map +1 -1
- package/dist/sampling.test.d.ts +1 -0
- package/dist/sampling.test.js +150 -0
- package/dist/sampling.test.js.map +1 -0
- package/dist/tools/getAgentIdentity.d.ts +9 -1
- package/dist/tools/getAgentIdentity.js +67 -10
- package/dist/tools/getAgentIdentity.js.map +1 -1
- package/dist/verify.d.ts +34 -0
- package/dist/verify.js +161 -0
- package/dist/verify.js.map +1 -0
- package/dist/verify.test.d.ts +1 -0
- package/dist/verify.test.js +177 -0
- package/dist/verify.test.js.map +1 -0
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Add to your MCP client config:
|
|
|
17
17
|
"command": "npx",
|
|
18
18
|
"args": ["-y", "@payclaw/badge"],
|
|
19
19
|
"env": {
|
|
20
|
-
"PAYCLAW_API_URL": "https://
|
|
20
|
+
"PAYCLAW_API_URL": "https://payclaw.io"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -64,6 +64,8 @@ The agent presents this disclosure to merchants. Merchants see a verified identi
|
|
|
64
64
|
|
|
65
65
|
## How It Works
|
|
66
66
|
|
|
67
|
+
### First use (device auth)
|
|
68
|
+
|
|
67
69
|
```
|
|
68
70
|
1. Your agent calls payclaw_getAgentIdentity
|
|
69
71
|
2. No key? Device auth flow triggers — code + URL appear in terminal
|
|
@@ -72,7 +74,31 @@ The agent presents this disclosure to merchants. Merchants see a verified identi
|
|
|
72
74
|
5. Every subsequent call uses the stored key automatically
|
|
73
75
|
```
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
### UCP-aware identity (with merchantUrl)
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
1. Agent calls payclaw_getAgentIdentity({ merchantUrl: 'https://store.com' })
|
|
81
|
+
2. PayClaw fetches store.com/.well-known/ucp manifest
|
|
82
|
+
3. If merchant declares io.payclaw.common.identity → returns checkoutPatch
|
|
83
|
+
4. Agent merges checkoutPatch into checkout payload
|
|
84
|
+
5. Agent calls payclaw_reportBadgePresented({ merchantUrl, verification_token })
|
|
85
|
+
6. Merchant calls verify(token) → gets PayClawIdentity
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
If the merchant doesn't support UCP, a valid token is still returned — nothing breaks. No card is issued. No money moves. Badge is the identity layer — the credential that lets authorized agents through while bot defenses stay intact.
|
|
89
|
+
|
|
90
|
+
### Extended Auth (optional)
|
|
91
|
+
|
|
92
|
+
When enabled, PayClaw checks back with your agent 7 seconds after badge presentation to confirm whether the merchant accepted or denied. Results are logged to your dashboard.
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
"env": {
|
|
96
|
+
"PAYCLAW_API_URL": "https://payclaw.io",
|
|
97
|
+
"PAYCLAW_EXTENDED_AUTH": "true"
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Without it, your agent reports outcomes via `payclaw_reportBadgeOutcome` when it knows the result.
|
|
76
102
|
|
|
77
103
|
## Tools
|
|
78
104
|
|
|
@@ -80,6 +106,46 @@ No card is issued. No money moves. Badge is the identity layer — the credentia
|
|
|
80
106
|
|------|-------------|
|
|
81
107
|
| `payclaw_getAgentIdentity` | Declare identity, get UCP-compatible verification token |
|
|
82
108
|
| `payclaw_reportBadgePresented` | Signal that you presented your Badge to a merchant |
|
|
109
|
+
| `payclaw_reportBadgeOutcome` | Report whether merchant accepted or denied the badge |
|
|
110
|
+
| `payclaw_reportBadgeNotPresented` | Report that the badge was not presented |
|
|
111
|
+
|
|
112
|
+
## For Merchants: Verify a Badge
|
|
113
|
+
|
|
114
|
+
Badge is the package merchants install for local JWT verification — no API call to PayClaw, no uptime dependency.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npm install @payclaw/badge
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import { verify } from '@payclaw/badge/verify'
|
|
122
|
+
|
|
123
|
+
const identity = await verify(req.body['io.payclaw.common.identity']?.token)
|
|
124
|
+
|
|
125
|
+
if (identity) {
|
|
126
|
+
// Verified — identity.userId, identity.agentId, identity.scopes, etc.
|
|
127
|
+
// Apply tier pricing, skip CAPTCHAs, fast-track checkout
|
|
128
|
+
}
|
|
129
|
+
// null = no badge or invalid — proceed as guest
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`verify()` fetches PayClaw's JWKS once, caches for 1 hour, and verifies the ES256 signature locally via Web Crypto API. Zero runtime dependencies. Works in Node.js 18+ and Cloudflare Workers. Never throws — returns `null` on any error.
|
|
133
|
+
|
|
134
|
+
Full verification docs + Python example: [github.com/payclaw/ucp-agent-badge](https://github.com/payclaw/ucp-agent-badge#merchant-verification)
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## What's New (v0.8.0)
|
|
139
|
+
|
|
140
|
+
| Capability | Description |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `verify()` export | Merchant-side JWT verification — `import { verify } from '@payclaw/badge/verify'`. Zero dependencies, Web Crypto only. |
|
|
143
|
+
| UCP-aware `getAgentIdentity` | Pass `merchantUrl` — fetches merchant manifest, returns `checkoutPatch` when `io.payclaw.common.identity` is declared |
|
|
144
|
+
| `reportBadgePresented` with `merchantUrl` | Preferred over `merchant`; includes optional `checkoutSessionId` for UCP session tracking |
|
|
145
|
+
| SSRF-protected manifest fetcher | HTTPS-only, private IP blocking, 5-minute domain cache |
|
|
146
|
+
| Trip lifecycle hardening | `onServerClose` resolves as `inconclusive`; orphan token recovery on restart |
|
|
147
|
+
|
|
148
|
+
---
|
|
83
149
|
|
|
84
150
|
## Need Payment Too?
|
|
85
151
|
|
package/dist/api/client.js
CHANGED
|
@@ -78,7 +78,7 @@ export async function getAgentIdentity(sessionId, merchant) {
|
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
export function isApiMode() {
|
|
81
|
-
return !!process.env.PAYCLAW_API_URL;
|
|
81
|
+
return !!process.env.PAYCLAW_API_URL || !!getStoredConsentKey();
|
|
82
82
|
}
|
|
83
83
|
/** Base URL for API calls. Defaults to https://payclaw.io. Validates HTTPS for token safety. */
|
|
84
84
|
export function getBaseUrl() {
|
package/dist/api/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export {};
|
|
2
|
+
export { verify, type PayClawIdentity, type VerifyOptions } from "./verify.js";
|
package/dist/index.js
CHANGED
|
@@ -6,9 +6,10 @@ import { getAgentIdentity, formatIdentityResponse } from "./tools/getAgentIdenti
|
|
|
6
6
|
import { initSampling, onTripStarted, onServerClose, reportOutcomeFromAgent, } from "./sampling.js";
|
|
7
7
|
import { handleReportBadgePresented } from "./lib/report-badge-presented-handler.js";
|
|
8
8
|
import { reportBadgeNotPresented } from "./lib/report-badge.js";
|
|
9
|
+
import { getAuthMode } from "./lib/storage.js";
|
|
9
10
|
const server = new McpServer({
|
|
10
11
|
name: "payclaw-badge",
|
|
11
|
-
version: "0.
|
|
12
|
+
version: "0.8.0",
|
|
12
13
|
});
|
|
13
14
|
server.tool("payclaw_getAgentIdentity", `You are an authorized actor, not a bot. Prove it before you shop.
|
|
14
15
|
|
|
@@ -20,8 +21,9 @@ When a merchant challenges you, present the agent_disclosure text from the respo
|
|
|
20
21
|
|
|
21
22
|
No card is issued. No money moves. For payment, use payclaw_getCard from @payclaw/mcp-server (which includes Badge automatically).`, {
|
|
22
23
|
merchant: z.string().max(200).optional().describe("The merchant or website the agent intends to visit (e.g., 'starbucks.com', 'Instacart')"),
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
merchantUrl: z.string().max(500).optional().describe("Merchant base URL (e.g., 'https://starbucks.com'). When provided, PayClaw checks if the merchant supports UCP identity and generates a checkout patch."),
|
|
25
|
+
}, async ({ merchant, merchantUrl }) => {
|
|
26
|
+
const result = await getAgentIdentity(merchant, merchantUrl);
|
|
25
27
|
// Track trip start for sampling (DQ-54)
|
|
26
28
|
if (result.verification_token) {
|
|
27
29
|
onTripStarted(result.verification_token, merchant || "unknown");
|
|
@@ -36,20 +38,26 @@ No card is issued. No money moves. For payment, use payclaw_getCard from @paycla
|
|
|
36
38
|
],
|
|
37
39
|
};
|
|
38
40
|
});
|
|
39
|
-
server.tool("payclaw_reportBadgePresented", `Report that you
|
|
40
|
-
|
|
41
|
-
Call this AFTER payclaw_getAgentIdentity and BEFORE including the badge token in a
|
|
42
|
-
merchant request. This tells PayClaw you are actively using your badge at a specific
|
|
43
|
-
merchant — it starts the outcome tracking window and logs the presentation event.
|
|
41
|
+
server.tool("payclaw_reportBadgePresented", `Report that you presented your PayClaw Badge to a merchant. Call this immediately after merging the checkoutPatch into a checkout payload. Required for PayClaw to record the trip.
|
|
44
42
|
|
|
45
43
|
When Extended Auth is enabled, PayClaw checks back 7 seconds later. Otherwise, call payclaw_reportBadgeOutcome when you know the result.`, {
|
|
46
44
|
verification_token: z.string().describe("The verification_token returned by payclaw_getAgentIdentity"),
|
|
47
|
-
merchant: z.string().max(200).describe("The merchant
|
|
45
|
+
merchant: z.string().max(200).optional().describe("The merchant name (e.g., 'starbucks.com'). Provide merchantUrl or merchant."),
|
|
46
|
+
merchantUrl: z.string().max(500).optional().describe("The merchant base URL (e.g., 'https://starbucks.com'). Preferred over merchant."),
|
|
48
47
|
context: z
|
|
49
48
|
.enum(["arrival", "addtocart", "checkout", "other"])
|
|
50
49
|
.optional()
|
|
51
|
-
.describe("Optional:
|
|
52
|
-
|
|
50
|
+
.describe("Optional: in what state you presented (arrival, addtocart, checkout, other)"),
|
|
51
|
+
checkoutSessionId: z.string().optional().describe("UCP checkout session ID if available"),
|
|
52
|
+
}, async ({ verification_token, merchant, merchantUrl, context, checkoutSessionId }) => {
|
|
53
|
+
const resolvedMerchant = merchantUrl || merchant;
|
|
54
|
+
if (!resolvedMerchant) {
|
|
55
|
+
return {
|
|
56
|
+
content: [{ type: "text", text: "✗ Error: merchantUrl or merchant is required." }],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return handleReportBadgePresented(verification_token, resolvedMerchant, context, checkoutSessionId);
|
|
60
|
+
});
|
|
53
61
|
server.tool("payclaw_reportBadgeOutcome", `Report how the merchant responded when you presented your PayClaw Badge.
|
|
54
62
|
|
|
55
63
|
Call this after payclaw_reportBadgePresented when you know whether the merchant accepted or denied you. Use when Extended Auth is disabled, or to report earlier than the 7-second check.`, {
|
|
@@ -99,9 +107,14 @@ async function main() {
|
|
|
99
107
|
process.exit(0);
|
|
100
108
|
});
|
|
101
109
|
process.stderr.write("PayClaw Badge server running on stdio\n");
|
|
110
|
+
if (process.env.VITEST !== "true") {
|
|
111
|
+
process.stderr.write(`[PayClaw] Auth: ${getAuthMode()}\n`);
|
|
112
|
+
}
|
|
102
113
|
}
|
|
103
114
|
main().catch((err) => {
|
|
104
115
|
process.stderr.write(`Fatal error: ${err}\n`);
|
|
105
116
|
process.exit(1);
|
|
106
117
|
});
|
|
118
|
+
// Re-export verify for merchant-side use: import { verify } from '@payclaw/badge'
|
|
119
|
+
export { verify } from "./verify.js";
|
|
107
120
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACvF,OAAO,EACL,YAAY,EACZ,aAAa,EAEb,aAAa,EACb,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/device-auth.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Canonical: badge-server | Synced: 0.7.3 | Do not edit in mcp-server
|
|
1
2
|
import { storeConsentKey } from "./storage.js";
|
|
2
3
|
const DEFAULT_API_URL = "https://payclaw.io";
|
|
3
4
|
const FETCH_TIMEOUT_MS = 10_000;
|
|
@@ -5,8 +6,15 @@ function getBaseUrl() {
|
|
|
5
6
|
const url = process.env.PAYCLAW_API_URL;
|
|
6
7
|
if (url && url.trim().length > 0) {
|
|
7
8
|
const trimmed = url.trim().replace(/\/+$/, "");
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
try {
|
|
10
|
+
const parsed = new URL(trimmed);
|
|
11
|
+
const isLoopback = ["localhost", "127.0.0.1", "::1"].includes(parsed.hostname);
|
|
12
|
+
if (parsed.protocol === "https:" || (parsed.protocol === "http:" && isLoopback)) {
|
|
13
|
+
return trimmed;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// fall through to DEFAULT_API_URL
|
|
10
18
|
}
|
|
11
19
|
}
|
|
12
20
|
return DEFAULT_API_URL;
|
|
@@ -44,7 +52,7 @@ export async function initiateDeviceAuth() {
|
|
|
44
52
|
throw new Error("Invalid device auth response");
|
|
45
53
|
}
|
|
46
54
|
const interval = Math.max(1, Number(data.interval) || 5);
|
|
47
|
-
const expiresIn = Number(data.expires_in) || 600;
|
|
55
|
+
const expiresIn = Math.max(1, Number(data.expires_in) || 600);
|
|
48
56
|
return { ...data, interval, expires_in: expiresIn };
|
|
49
57
|
}
|
|
50
58
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-auth.js","sourceRoot":"","sources":["../../src/lib/device-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAC7C,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC,SAAS,UAAU;IACjB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACxC,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC/C,IAAI,OAAO,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"device-auth.js","sourceRoot":"","sources":["../../src/lib/device-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-outcome.js","sourceRoot":"","sources":["../../src/lib/parse-outcome.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,eAAe,GAAG;IACtB,KAAK;IACL,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,OAAO;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,SAAS;CACV,CAAC;AAEF,MAAM,UAAU,aAAa,CAC3B,IAAY;IAEZ,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,cAAc,CAAC;IAE7D,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAExC,kEAAkE;IAClE,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC;QACjE,OAAO,UAAU,CAAC;IAEpB,uFAAuF;IACvF,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,UAAU,KAAK,WAAW;QAAE,OAAO,cAAc,CAAC;IAEtD,oFAAoF;IACpF,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEpE,uFAAuF;IACvF,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAEvD,OAAO,cAAc,CAAC;AACxB,CAAC"}
|
|
1
|
+
{"version":3,"file":"parse-outcome.js","sourceRoot":"","sources":["../../src/lib/parse-outcome.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE;;;GAGG;AAEH,MAAM,eAAe,GAAG;IACtB,KAAK;IACL,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,OAAO;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,SAAS;IACT,SAAS;CACV,CAAC;AAEF,MAAM,UAAU,aAAa,CAC3B,IAAY;IAEZ,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,cAAc,CAAC;IAE7D,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAExC,kEAAkE;IAClE,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC;QACjE,OAAO,UAAU,CAAC;IAEpB,uFAAuF;IACvF,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,UAAU,KAAK,WAAW;QAAE,OAAO,cAAc,CAAC;IAEtD,oFAAoF;IACpF,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEpE,uFAAuF;IACvF,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAEvD,OAAO,cAAc,CAAC;AACxB,CAAC"}
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
* Handler for payclaw_reportBadgePresented tool.
|
|
3
3
|
* Extracted for testability (BUG-01.1 integration tests).
|
|
4
4
|
*/
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Idempotency (duplicate row prevention) and expired-token status
|
|
7
|
+
* (`status: 'expired_presentation'`) are enforced by the API server,
|
|
8
|
+
* not here. The MCP server is stateless — it has no DB access and
|
|
9
|
+
* cannot check trip_id uniqueness or decode token expiry authoritatively.
|
|
10
|
+
*/
|
|
11
|
+
export declare function handleReportBadgePresented(verification_token: string, merchant: string, context?: "arrival" | "addtocart" | "checkout" | "other", checkoutSessionId?: string): Promise<{
|
|
6
12
|
content: Array<{
|
|
7
13
|
type: "text";
|
|
8
14
|
text: string;
|
|
@@ -1,14 +1,25 @@
|
|
|
1
|
+
// Canonical: badge-server | Synced: 0.7.3 | Do not edit in mcp-server
|
|
1
2
|
/**
|
|
2
3
|
* Handler for payclaw_reportBadgePresented tool.
|
|
3
4
|
* Extracted for testability (BUG-01.1 integration tests).
|
|
4
5
|
*/
|
|
5
6
|
import { onIdentityPresented } from "../sampling.js";
|
|
6
7
|
import { reportBadgePresented } from "./report-badge.js";
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Idempotency (duplicate row prevention) and expired-token status
|
|
10
|
+
* (`status: 'expired_presentation'`) are enforced by the API server,
|
|
11
|
+
* not here. The MCP server is stateless — it has no DB access and
|
|
12
|
+
* cannot check trip_id uniqueness or decode token expiry authoritatively.
|
|
13
|
+
*/
|
|
14
|
+
export async function handleReportBadgePresented(verification_token, merchant, context, checkoutSessionId) {
|
|
8
15
|
onIdentityPresented(verification_token, merchant);
|
|
9
|
-
await reportBadgePresented(verification_token, merchant, context);
|
|
16
|
+
await reportBadgePresented(verification_token, merchant, context, checkoutSessionId);
|
|
10
17
|
return {
|
|
11
18
|
content: [
|
|
19
|
+
{
|
|
20
|
+
type: "text",
|
|
21
|
+
text: JSON.stringify({ recorded: true }),
|
|
22
|
+
},
|
|
12
23
|
{
|
|
13
24
|
type: "text",
|
|
14
25
|
text: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report-badge-presented-handler.js","sourceRoot":"","sources":["../../src/lib/report-badge-presented-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,kBAA0B,EAC1B,QAAgB,EAChB,OAAwD;
|
|
1
|
+
{"version":3,"file":"report-badge-presented-handler.js","sourceRoot":"","sources":["../../src/lib/report-badge-presented-handler.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,kBAA0B,EAC1B,QAAgB,EAChB,OAAwD,EACxD,iBAA0B;IAE1B,mBAAmB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAClD,MAAM,oBAAoB,CAAC,kBAAkB,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACrF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;aACzC;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE;oBACJ,kCAAkC,QAAQ,EAAE;oBAC5C,EAAE;oBACF,eAAe,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI;oBAClD,eAAe,QAAQ,EAAE;oBACzB,iDAAiD;oBACjD,EAAE;oBACF,2DAA2D;oBAC3D,2BAA2B,kBAAkB,EAAE;iBAChD,CAAC,IAAI,CAAC,IAAI,CAAC;aACb;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Uses getStoredConsentKey for OAuth users; PAYCLAW_API_KEY for legacy.
|
|
4
4
|
* Synced from mcp-server (BUG-01.1).
|
|
5
5
|
*/
|
|
6
|
-
export declare function reportBadgePresented(verificationToken: string, merchant: string, context?: "arrival" | "addtocart" | "checkout" | "other"): Promise<void>;
|
|
6
|
+
export declare function reportBadgePresented(verificationToken: string, merchant: string, context?: "arrival" | "addtocart" | "checkout" | "other", checkoutSessionId?: string): Promise<void>;
|
|
7
7
|
export declare function reportBadgeNotPresented(verificationToken: string, merchant: string, reason: "abandoned" | "merchant_didnt_ask" | "other"): Promise<void>;
|
package/dist/lib/report-badge.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Canonical: badge-server | Synced: 0.7.3 | Do not edit in mcp-server
|
|
1
2
|
/**
|
|
2
3
|
* POST identity_presented to /api/badge/report.
|
|
3
4
|
* Uses getStoredConsentKey for OAuth users; PAYCLAW_API_KEY for legacy.
|
|
@@ -5,7 +6,7 @@
|
|
|
5
6
|
*/
|
|
6
7
|
import { getStoredConsentKey } from "./storage.js";
|
|
7
8
|
const DEFAULT_API_URL = "https://payclaw.io";
|
|
8
|
-
export async function reportBadgePresented(verificationToken, merchant, context) {
|
|
9
|
+
export async function reportBadgePresented(verificationToken, merchant, context, checkoutSessionId) {
|
|
9
10
|
const apiUrl = process.env.PAYCLAW_API_URL || DEFAULT_API_URL;
|
|
10
11
|
const key = getStoredConsentKey();
|
|
11
12
|
if (!key)
|
|
@@ -22,6 +23,7 @@ export async function reportBadgePresented(verificationToken, merchant, context)
|
|
|
22
23
|
event_type: "identity_presented",
|
|
23
24
|
merchant,
|
|
24
25
|
...(context && { presentation_context: context }),
|
|
26
|
+
...(checkoutSessionId && { checkout_session_id: checkoutSessionId }),
|
|
25
27
|
}),
|
|
26
28
|
});
|
|
27
29
|
if (!res.ok) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report-badge.js","sourceRoot":"","sources":["../../src/lib/report-badge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,iBAAyB,EACzB,QAAgB,EAChB,OAAwD;
|
|
1
|
+
{"version":3,"file":"report-badge.js","sourceRoot":"","sources":["../../src/lib/report-badge.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,iBAAyB,EACzB,QAAgB,EAChB,OAAwD,EACxD,iBAA0B;IAE1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,eAAe,CAAC;IAC9D,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO;IAEjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,mBAAmB,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,GAAG,EAAE;gBAC9B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,kBAAkB,EAAE,iBAAiB;gBACrC,UAAU,EAAE,oBAAoB;gBAChC,QAAQ;gBACR,GAAG,CAAC,OAAO,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,CAAC;gBACjD,GAAG,CAAC,iBAAiB,IAAI,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,CAAC;aACrE,CAAC;SACH,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wCAAwC,GAAG,CAAC,MAAM,MAAM,IAAI,IAAI,CACjE,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,iBAAyB,EACzB,QAAgB,EAChB,MAAoD;IAEpD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,eAAe,CAAC;IAC9D,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO;IAEjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,mBAAmB,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,GAAG,EAAE;gBAC9B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,kBAAkB,EAAE,iBAAiB;gBACrC,UAAU,EAAE,qBAAqB;gBACjC,QAAQ;gBACR,MAAM;aACP,CAAC;SACH,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,2CAA2C,GAAG,CAAC,MAAM,MAAM,IAAI,IAAI,CACpE,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;AACH,CAAC"}
|
package/dist/lib/storage.d.ts
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
* 3. In-memory (current process only)
|
|
6
6
|
*/
|
|
7
7
|
export declare function getStoredConsentKey(): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Returns a human-readable description of the active auth mode.
|
|
10
|
+
* Used for startup logging — never exposes full key values.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getAuthMode(): string;
|
|
8
13
|
/**
|
|
9
14
|
* Store consent key to ~/.payclaw/consent_key.
|
|
10
15
|
* Creates directory if needed. Falls back to memory if file write fails.
|
package/dist/lib/storage.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Canonical: badge-server | Synced: 0.7.3 | Do not edit in mcp-server
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import os from "node:os";
|
|
@@ -34,6 +35,33 @@ export function getStoredConsentKey() {
|
|
|
34
35
|
}
|
|
35
36
|
return memoryConsentKey;
|
|
36
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns a human-readable description of the active auth mode.
|
|
40
|
+
* Used for startup logging — never exposes full key values.
|
|
41
|
+
*/
|
|
42
|
+
export function getAuthMode() {
|
|
43
|
+
const envKey = process.env.PAYCLAW_API_KEY;
|
|
44
|
+
if (envKey && envKey.trim().length > 0) {
|
|
45
|
+
const masked = envKey.trim().substring(0, 8) + "****";
|
|
46
|
+
return `API key (${masked})`;
|
|
47
|
+
}
|
|
48
|
+
const filePath = getConsentKeyPath();
|
|
49
|
+
try {
|
|
50
|
+
if (fs.existsSync(filePath)) {
|
|
51
|
+
const content = fs.readFileSync(filePath, "utf8").trim();
|
|
52
|
+
if (content.length > 0) {
|
|
53
|
+
return "consent key (~/.payclaw/consent_key)";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// File read failed
|
|
59
|
+
}
|
|
60
|
+
if (memoryConsentKey) {
|
|
61
|
+
return "consent key (in-memory)";
|
|
62
|
+
}
|
|
63
|
+
return "none (device flow will trigger on first tool call)";
|
|
64
|
+
}
|
|
37
65
|
/**
|
|
38
66
|
* Store consent key to ~/.payclaw/consent_key.
|
|
39
67
|
* Creates directory if needed. Falls back to memory if file write fails.
|
package/dist/lib/storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/lib/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAEvC,oEAAoE;AACpE,IAAI,gBAAgB,GAAkB,IAAI,CAAC;AAE3C,SAAS,iBAAiB;IACxB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC3C,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YACzD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yCAAyC;IAC3C,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAa;IACjD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,gBAAgB,GAAG,OAAO,CAAC;IAE3B,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;IAClE,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/lib/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UCP manifest fetcher — checks if a merchant supports io.payclaw.common.identity.
|
|
3
|
+
*
|
|
4
|
+
* Fetches {merchantUrl}/.well-known/ucp, caches per domain for 5 minutes.
|
|
5
|
+
* Never throws — returns null on any error.
|
|
6
|
+
*/
|
|
7
|
+
interface UCPCapability {
|
|
8
|
+
version: string;
|
|
9
|
+
spec?: string;
|
|
10
|
+
schema?: string;
|
|
11
|
+
extends?: string;
|
|
12
|
+
config?: {
|
|
13
|
+
required?: boolean;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
interface UCPManifest {
|
|
17
|
+
capabilities?: Record<string, UCPCapability | UCPCapability[]>;
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
export declare function fetchUCPManifest(merchantUrl: string): Promise<UCPManifest | null>;
|
|
21
|
+
export interface PayClawCapability {
|
|
22
|
+
version: string;
|
|
23
|
+
required: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function findPayClawCapability(manifest: UCPManifest): PayClawCapability | null;
|
|
26
|
+
export declare function isVersionCompatible(version: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Reset the manifest cache. Useful for testing.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export declare function _resetManifestCache(): void;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UCP manifest fetcher — checks if a merchant supports io.payclaw.common.identity.
|
|
3
|
+
*
|
|
4
|
+
* Fetches {merchantUrl}/.well-known/ucp, caches per domain for 5 minutes.
|
|
5
|
+
* Never throws — returns null on any error.
|
|
6
|
+
*/
|
|
7
|
+
const EXTENSION_NAME = "io.payclaw.common.identity";
|
|
8
|
+
const FETCH_TIMEOUT_MS = 3000;
|
|
9
|
+
const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
10
|
+
const manifestCache = new Map();
|
|
11
|
+
function normalizeDomain(url) {
|
|
12
|
+
try {
|
|
13
|
+
const u = new URL(url.endsWith("/") ? url.slice(0, -1) : url);
|
|
14
|
+
return u.origin;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Bare domain like "starbucks.com" — try with https://
|
|
18
|
+
try {
|
|
19
|
+
return new URL("https://" + url.replace(/\/+$/, "")).origin;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return url.replace(/\/+$/, "");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function isPublicOrigin(origin) {
|
|
27
|
+
let hostname;
|
|
28
|
+
try {
|
|
29
|
+
hostname = new URL(origin).hostname;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Block non-https (except in tests)
|
|
35
|
+
if (!origin.startsWith("https://") && !process.env.VITEST)
|
|
36
|
+
return false;
|
|
37
|
+
// Block localhost and loopback
|
|
38
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1")
|
|
39
|
+
return false;
|
|
40
|
+
if (hostname.endsWith(".localhost"))
|
|
41
|
+
return false;
|
|
42
|
+
// Block private/reserved IPv4 ranges
|
|
43
|
+
const ipv4Match = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
|
|
44
|
+
if (ipv4Match) {
|
|
45
|
+
const [, a, b] = ipv4Match.map(Number);
|
|
46
|
+
if (a === 10)
|
|
47
|
+
return false; // 10.0.0.0/8
|
|
48
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
49
|
+
return false; // 172.16.0.0/12
|
|
50
|
+
if (a === 192 && b === 168)
|
|
51
|
+
return false; // 192.168.0.0/16
|
|
52
|
+
if (a === 169 && b === 254)
|
|
53
|
+
return false; // 169.254.0.0/16 (link-local + metadata)
|
|
54
|
+
if (a === 0)
|
|
55
|
+
return false; // 0.0.0.0/8
|
|
56
|
+
}
|
|
57
|
+
// Block IPv6 loopback/link-local
|
|
58
|
+
if (hostname.startsWith("[")) {
|
|
59
|
+
const inner = hostname.slice(1, -1).toLowerCase();
|
|
60
|
+
if (inner === "::1" || inner.startsWith("fe80:") || inner.startsWith("fc") || inner.startsWith("fd"))
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
export async function fetchUCPManifest(merchantUrl) {
|
|
66
|
+
const domain = normalizeDomain(merchantUrl);
|
|
67
|
+
// SSRF protection: only fetch from public origins
|
|
68
|
+
if (!isPublicOrigin(domain))
|
|
69
|
+
return null;
|
|
70
|
+
// Check cache
|
|
71
|
+
const cached = manifestCache.get(domain);
|
|
72
|
+
if (cached && (Date.now() - cached.fetchedAt) < CACHE_TTL_MS) {
|
|
73
|
+
return cached.data;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const res = await fetch(`${domain}/.well-known/ucp`, {
|
|
77
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok) {
|
|
80
|
+
manifestCache.set(domain, { data: null, fetchedAt: Date.now() });
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const data = (await res.json());
|
|
84
|
+
manifestCache.set(domain, { data, fetchedAt: Date.now() });
|
|
85
|
+
return data;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
manifestCache.set(domain, { data: null, fetchedAt: Date.now() });
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function findPayClawCapability(manifest) {
|
|
93
|
+
const caps = manifest.capabilities;
|
|
94
|
+
if (!caps || !(EXTENSION_NAME in caps))
|
|
95
|
+
return null;
|
|
96
|
+
const entry = caps[EXTENSION_NAME];
|
|
97
|
+
// Handle both array-wrapped and plain object forms
|
|
98
|
+
const cap = Array.isArray(entry) ? entry[0] : entry;
|
|
99
|
+
if (!cap || typeof cap.version !== "string")
|
|
100
|
+
return null;
|
|
101
|
+
return {
|
|
102
|
+
version: cap.version,
|
|
103
|
+
required: cap.config?.required === true,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const COMPATIBLE_VERSIONS = ["2026-01-11"];
|
|
107
|
+
export function isVersionCompatible(version) {
|
|
108
|
+
return COMPATIBLE_VERSIONS.includes(version);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Reset the manifest cache. Useful for testing.
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
114
|
+
export function _resetManifestCache() {
|
|
115
|
+
manifestCache.clear();
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=ucp-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ucp-manifest.js","sourceRoot":"","sources":["../../src/lib/ucp-manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,cAAc,GAAG,4BAA4B,CAAC;AACpD,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;AAoBhD,MAAM,aAAa,GAAG,IAAI,GAAG,EAA0B,CAAC;AAExD,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC9D,OAAO,CAAC,CAAC,MAAM,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;QACvD,IAAI,CAAC;YACH,OAAO,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oCAAoC;IACpC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAExE,+BAA+B;IAC/B,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAC7F,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,KAAK,CAAC;IAElD,qCAAqC;IACrC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACjE,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC,CAA0B,aAAa;QAClE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO,KAAK,CAAC,CAAG,gBAAgB;QACrE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC,CAAa,iBAAiB;QACvE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC,CAAa,yCAAyC;QAC/F,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,CAA4B,YAAY;IACpE,CAAC;IAED,iCAAiC;IACjC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;IACrH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAmB;IACxD,MAAM,MAAM,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAE5C,kDAAkD;IAClD,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,cAAc;IACd,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,YAAY,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,kBAAkB,EAAE;YACnD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC;SAC9C,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgB,CAAC;QAC/C,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAOD,MAAM,UAAU,qBAAqB,CAAC,QAAqB;IACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC;IACnC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,cAAc,IAAI,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;IACnC,mDAAmD;IACnD,MAAM,GAAG,GAA8B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC/E,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAEzD,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAG,CAAC,YAAY,CAAC,CAAC;AAE3C,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,OAAO,mBAAmB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,aAAa,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|