x402-surface-check 0.2.36 → 0.2.37

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 CHANGED
@@ -30,6 +30,7 @@ npx --yes x402-surface-check --strict-proof https://api.example.com/openapi.json
30
30
  - No-payment HTTP 402 challenge shape
31
31
  - x402 v1 and v2 price fields, including `accepts[]` and `schemes[]` challenge arrays
32
32
  - MPP `WWW-Authenticate: Payment` and x402 V2 `WWW-Authenticate: X402 requirements=...` challenges
33
+ - x402 challenges nested inside framework error wrappers such as FastAPI-style `{"detail": {...}}`
33
34
  - MPP descriptor-only 402s that advertise discovery headers but do not return a machine-readable payment retry challenge
34
35
  - Atomic-unit `amount` / `maxAmountRequired` fields, plus legacy decimal `amount` + `token` x402 v1 challenges
35
36
  - `asset` or token metadata, `network`, and `payTo`
@@ -648,6 +648,29 @@ function parseX402Authenticate(value) {
648
648
  }
649
649
  }
650
650
 
651
+ function bodyChallengeJson(value) {
652
+ if (!value || typeof value !== 'object') return null
653
+ if (Array.isArray(value.accepts) || Array.isArray(value.schemes)) return value
654
+
655
+ const candidates = [
656
+ value.detail,
657
+ value.error,
658
+ value.payment,
659
+ value.paymentRequired,
660
+ value.payment_required,
661
+ value.challenge,
662
+ value.x402,
663
+ ]
664
+
665
+ for (const candidate of candidates) {
666
+ if (!candidate || typeof candidate !== 'object') continue
667
+ const nested = bodyChallengeJson(candidate)
668
+ if (nested) return nested
669
+ }
670
+
671
+ return null
672
+ }
673
+
651
674
  async function fetchDocument(url) {
652
675
  const response = await fetch(url, {
653
676
  headers: {
@@ -750,7 +773,11 @@ async function probeEndpoint(entry, origin) {
750
773
  const authenticateChallenge = parsePaymentAuthenticate(response.headers.get('www-authenticate'))
751
774
  ?? parseX402Authenticate(response.headers.get('www-authenticate'))
752
775
 
753
- const bodyHasChallenge = Array.isArray(body.json?.accepts) || Array.isArray(body.json?.schemes)
776
+ const bodyChallenge = bodyChallengeJson(body.json)
777
+ const bodyHasChallenge = Boolean(bodyChallenge)
778
+ if (bodyChallenge && body.json !== bodyChallenge) {
779
+ body.json = bodyChallenge
780
+ }
754
781
  if (!bodyHasChallenge) {
755
782
  if (headerChallenge && typeof headerChallenge === 'object') {
756
783
  body.json = headerChallenge
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x402-surface-check",
3
- "version": "0.2.36",
3
+ "version": "0.2.37",
4
4
  "description": "No-payment x402 public-surface checker for manifests, OpenAPI specs, and HTTP 402 challenges.",
5
5
  "type": "module",
6
6
  "bin": {