x402-surface-check 0.2.11 → 0.2.12
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 +2 -0
- package/bin/x402-surface-check.mjs +30 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ npx --yes x402-surface-check --endpoint --method POST https://x402.rpc.ankr.com/
|
|
|
15
15
|
## What It Checks
|
|
16
16
|
|
|
17
17
|
- Manifest endpoint discovery from `items[]`, `endpoints[]`, `x402Endpoints`, category arrays, resource strings, and OpenAPI paths
|
|
18
|
+
- Linked discovery documents via `discovery_url`, `discoveryUrl`, `resources_url`, or `resourcesUrl`
|
|
18
19
|
- No-payment HTTP 402 challenge shape
|
|
19
20
|
- x402 v1 and v2 price fields, including `accepts[]` and `schemes[]` challenge arrays
|
|
20
21
|
- MPP `WWW-Authenticate: Payment` and x402 V2 `WWW-Authenticate: X402 requirements=...` challenges
|
|
@@ -39,6 +40,7 @@ Recent public no-payment checks have found and verified real launch fixes:
|
|
|
39
40
|
- Spraay: resource echo and browser payment-header behavior verified clean. https://github.com/solana-foundation/pay-skills/pull/60#issuecomment-4455519760
|
|
40
41
|
- UZPROOF: schemes-style Solana x402 challenge and browser payment-header behavior verified clean. https://github.com/solana-foundation/pay-skills/pull/28#issuecomment-4455613892
|
|
41
42
|
- HYRE Agent: OpenAPI-declared prices found 10x below live 402 challenge prices. https://github.com/solana-foundation/pay-skills/pull/19#issuecomment-4455641258
|
|
43
|
+
- anchor-x402: multi-rail x402 challenges verified, with browser preflight blockers isolated before merge. https://github.com/solana-foundation/pay-skills/pull/47#issuecomment-4455678163
|
|
42
44
|
- Agent Trust Bench: live discovery URL and browser-compatibility notes for adversarial agent-payment resources. https://github.com/solana-foundation/pay-skills/pull/23#issuecomment-4455484414
|
|
43
45
|
|
|
44
46
|
Field notes and browser version: https://tateprograms.com/x402-surface-check.html
|
|
@@ -132,6 +132,15 @@ function endpointUrl(rawPath, baseUrl, sourceUrl) {
|
|
|
132
132
|
return new URL(value, base).toString()
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
function linkedDiscoveryUrl(document, sourceUrl) {
|
|
136
|
+
const rawUrl = document?.discovery_url
|
|
137
|
+
?? document?.discoveryUrl
|
|
138
|
+
?? document?.resources_url
|
|
139
|
+
?? document?.resourcesUrl
|
|
140
|
+
if (typeof rawUrl !== 'string' || !rawUrl.trim()) return ''
|
|
141
|
+
return endpointUrl(rawUrl, documentBaseUrl(document, sourceUrl), sourceUrl)
|
|
142
|
+
}
|
|
143
|
+
|
|
135
144
|
function operationExpectedPrice(operation) {
|
|
136
145
|
const price = operation?.['x-payment-info']?.price
|
|
137
146
|
?? operation?.['x-payment']?.price
|
|
@@ -620,6 +629,7 @@ function formatMarkdown(report) {
|
|
|
620
629
|
return [
|
|
621
630
|
'# x402 Public Surface Check',
|
|
622
631
|
'',
|
|
632
|
+
...(report.sourceDocument ? [`Source: ${report.sourceDocument.url}`] : []),
|
|
623
633
|
`Document: ${report.document.url}`,
|
|
624
634
|
`Checked: ${report.checkedAt}`,
|
|
625
635
|
'Scope: manifest/OpenAPI parsing, no-payment endpoint probes, and browser-style CORS preflight. No payment headers or paid calls.',
|
|
@@ -656,7 +666,8 @@ function formatMarkdown(report) {
|
|
|
656
666
|
}
|
|
657
667
|
|
|
658
668
|
async function runCheck(options) {
|
|
659
|
-
|
|
669
|
+
let sourceDocument = null
|
|
670
|
+
let document = options.endpoint
|
|
660
671
|
? {
|
|
661
672
|
status: 200,
|
|
662
673
|
ok: true,
|
|
@@ -665,9 +676,25 @@ async function runCheck(options) {
|
|
|
665
676
|
body: { text: '{}', json: {} },
|
|
666
677
|
}
|
|
667
678
|
: await fetchDocument(options.url)
|
|
668
|
-
|
|
679
|
+
let entries = options.endpoint
|
|
669
680
|
? [{ name: new URL(options.url).pathname.split('/').filter(Boolean).at(-1) ?? options.url, url: options.url, method: options.method || 'POST' }]
|
|
670
681
|
: (document.body.json ? endpointEntries(document.body.json, document.url, options.limit) : [])
|
|
682
|
+
|
|
683
|
+
if (!options.endpoint && entries.length === 0 && document.body.json) {
|
|
684
|
+
const discoveryUrl = linkedDiscoveryUrl(document.body.json, document.url)
|
|
685
|
+
if (discoveryUrl) {
|
|
686
|
+
const followedDocument = await fetchDocument(discoveryUrl)
|
|
687
|
+
const followedEntries = followedDocument.body.json
|
|
688
|
+
? endpointEntries(followedDocument.body.json, followedDocument.url, options.limit)
|
|
689
|
+
: []
|
|
690
|
+
if (followedEntries.length > 0) {
|
|
691
|
+
sourceDocument = document
|
|
692
|
+
document = followedDocument
|
|
693
|
+
entries = followedEntries
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
671
698
|
const origin = options.origin ?? new URL(document.url).origin
|
|
672
699
|
const challenges = []
|
|
673
700
|
const preflights = []
|
|
@@ -686,6 +713,7 @@ async function runCheck(options) {
|
|
|
686
713
|
origin,
|
|
687
714
|
challenges,
|
|
688
715
|
preflights,
|
|
716
|
+
sourceDocument,
|
|
689
717
|
}
|
|
690
718
|
report.findings = findingList(document, challenges, preflights, entries)
|
|
691
719
|
return report
|