Skip to content

Releases: fardinvahdat/x402trace

v0.3.4

Choose a tag to compare

@github-actions github-actions released this 30 May 13:57
509b62d

[0.3.4] — 2026-05-30

v0.3.4 cycle complete: four committed items shipped across L + K + G + I. bazaar-check grows from 5 checks to 8: host-pollution (L, #101), payment-payload echo gap rule pair with new upstream_stuck.cause discriminator (K, #102), facilitator-fitness per-rail probe with declared-identity-first attribution (G, #103), and the first top-level new verdict since v0.3.2 — service_unreachable with multi-probe consensus + per-cause windows + the first stateful event discriminant in x402trace (I, #104 + determinism fix #105). ADRs 005 / 006 / 007 / 008 record the architectural decisions. JSON API X402-44 contract preserved across all four additions — every shape change is strictly additive. Cohort: 4 named external contributors credited (@hypeprinter007-stack / Ferj 🙏, @RipperMercs 🙏, @TKCollective 🙏, @AsaiShota 🙏) plus 5 additional named voices behind the design refinements (@Cryptor, @TomSmart_ai, @Cinderwright, @evanatpizzarobot, @poteshniy).

Added (I — X402-52)

  • reachability check (X402-52, per ADR-006). 8th and final v0.3.4 diagnose-rule. Probes the service URL at the network layer (DNS / TCP / TLS / HTTP) with bounded timeout + bounded retry. Classifies failures into a 5-state axis: dns_failure | tcp_refused | tls_error | timeout | persistent_5xx. Voices: divigent probe (2026-05-23 DNS-fail real example) + @TomSmart_ai (mapper.db cohort + 2026-05-28 traceroute anti-evidence + per-cause-window endorsement 2026-05-29). @AsaiShota's test-echo-cdp as false-positive sentinel pattern (carried from K).
  • NEW top-level verdict service_unreachable — first new top-level discriminator since v0.3.2's upstream_stuck. Exit 3 (same bucket as upstream_issue / upstream_stuck — exit-code contract per ADR-004 Pillar 2 preserved). Pre-empts all other verdict paths via the precedence rule service_unreachable > upstream_stuck.cause (K) > upstream_issue > facilitator_fitness facet (G) > host_pollution facet (L) > looks_correct — a DNS-failing service doesn't reach the surfaces those diagnose. Documented in src/bazaar/diagnose-rules.md.
  • bazaar.probe_attempt JSONL event discriminant (src/decoder/schema.md) — first stateful event added by bazaar-check. Records every reachability probe (success or fail) to enable cross-invocation multi-probe consensus.
  • First stateful verdict in x402traceservice_unreachable requires N consecutive matching probes within the per-cause window. Probe history is read from the JSONL log supplied via --probe-history-log <file>, current probe appended back. Preserves local-first stateless property: no external state directory; probe history lives in the same JSONL log operators already manage.
  • Per-cause consensus windows table (locked 2026-05-29 with @TomSmart_ai endorsement). DNS 5min / TCP 15min / TLS 30min / timeout 15min / persistent_5xx out-of-band. Operators scale uniformly via --unreachable-interval-multiplier <n>. Per-cause individual flags deferred to v0.4+.
  • persistent_5xx is intentionally out-of-band — server-malfunction signal, NOT unreachability. Classified via in-probe bounded retry (3 attempts × 500ms); rolls up to existing upstream_issue, NOT service_unreachable. Per ADR-006 explicit design.
  • 3 new CLI flags on bazaar-check:
    • --probe-history-log <path> — JSONL log for cross-invocation probe history. Without it, single-probe-only mode (top-level service_unreachable never fires).
    • --unreachable-consensus-count <n> — consecutive matching probes required for top-level promotion (default 3).
    • --unreachable-interval-multiplier <n> — uniform scalar over the per-cause windows table (default 1).
  • Clock abstraction (src/bazaar/clock.ts) — injectable for deterministic probe-history timestamps + window computations in tests. Production uses realClock; tests use createMockClock().
  • Anti-pattern documented: "don't key verdicts on third-party single-snapshot status fields" — per @TomSmart_ai's 2026-05-28 traceroute analysis (13/15 mapper.db-labeled-unreachable endpoints were HTTP-reachable on re-probe; status field is stale by design). x402trace always uses its own multi-probe consensus.

Changed (I — X402-52)

  • bazaar-check JSON output: results[] now contains 8 entries (was 7 after G). New 8th entry "reachability". No existing field renamed, removed, or reordered — X402-44 contract preserved.
  • BazaarVerdict discriminated union now includes the service_unreachable variant alongside looks_correct | implementation_issue | upstream_issue | upstream_stuck. New required fields on the service_unreachable variant: unreachableCause, consensusThreshold, probeCount. Strictly additive — existing variants unchanged.
  • verdict.ts UPSTREAM_CHECKS set extended to include "reachability" — info-status from I rolls to upstream signal when consensus not met. Verdict synthesizer checks reachability consensus FIRST and pre-empts the entire downstream verdict chain when fired.
  • src/bazaar/json-api.md documents the new check + facet + verdict shape + the precedence rule.
  • src/bazaar/diagnose-rules.md replaces the "pending implementation" placeholder with the full reachability spec.
  • src/decoder/schema.md documents the new bazaar.probe_attempt event discriminant.

Internal (I — X402-52)

  • src/bazaar/reachability.ts — new check module. Public surface: checkReachability, classifyFetchError. Single-probe + history-read + consensus-compute + facet emission + optional log append in one orchestration.
  • src/bazaar/probe-history.ts — new module. Public surface: readProbeHistory, consensusReached, nextAttemptSeq, PER_CAUSE_INTERVAL_MS. Pure functions; no I/O beyond readFileSync on the JSONL log.
  • src/bazaar/clock.ts — new module. Clock interface, realClock, createMockClock.
  • src/bazaar/types.tsReachabilityState, UnreachableCause, ReachabilityFacet, ProbeAttemptRecord types added.
  • Test count: G cycle shipped 598 → 646 passed + 4 skipped (650 total) in this I cycle. +48 from 37 new reachability/probe-history/clock unit tests + 11 integration assertions.
  • Publish-surface cap raised 540 KB → 600 KB + file count 110 → 120 in scripts/check-publish-surface.mjs. I added ~52 KB across 3 new source modules + their .d.ts companions in dist/.

JSON API (I — X402-52)

  • Additive: new 8th check "reachability" appended to results[] (was 7 in G cycle). New optional reachability.detail.{state, unreachable_cause, probe_count, consensus_threshold, consensus_met, consensus_window_ms, diagnostic} shape. New service_unreachable variant on BazaarVerdict discriminated union with required fields unreachableCause, consensusThreshold, probeCount. No existing field renamed, removed, reordered, or retyped. X402-44 contract preserved (additive change, minor-version-eligible per ADR-004 Pillar 2). Snapshot fixture regenerated.

Added (G — X402-51)

  • facilitator-fitness check (X402-51, per ADR-005). New diagnose-rule that probes the merchant's declared extensions.bazaar.facilitator against a built-in registry (CDP, PayAI, x402.org/facilitator) and emits a per-rail fitness facet. Closes the v0.3.2 gap: indexing.indexer_state: not_applicable_non_cdp correctly avoided misattribution but offered no positive signal for non-CDP services. G fills the silence with a per-rail health probe. Voices: @Cryptor (CDP-only-by-design correction) + @TomSmart_ai (mapper-integration consumer) + @Cinderwright 3rd-touch (#1065 PayAI alternative). Canonical multi-rail fixture from Ferj/@hypeprinter007-stack's anchor-x402 (3 rails: Base USDC CDP + Solana USDC CDP + JPY Coin Polygon).
  • src/bazaar/facilitator-registry.json — built-in registry of 3 facilitators (CDP, PayAI, x402.org/facilitator) with declared URLs, name aliases, probe endpoints. Per ADR-005 § Risks #1: registry is data, not code; new facilitators land as PRs adding entries. Operator override via --facilitator-registry <path> deferred to v0.4+.
  • New facilitator_fitness facet on facilitator-fitness check — per-rail array ({ rail, network, facilitator, identity_source, fitness, diagnostic? }) + summary counts. Strictly additive per X402-44. Verdict synthesizer treats info-status facilitator-fitness as upstream signal — any unreachable rail rolls up to upstream_issue (exit 3); degraded rails surface in facet without flipping the verdict.
  • Identity-source attribution — declared / inferred-from-tx / unknown. v0.3.4 MVP supports declared only (read from manifest.extensions.bazaar.facilitator); tx-from inference reserved as a v0.4+ slot. Per ADR-005: declared-identity-first is load-bearing for gasless rails (SKALE+PayAI per TKCollective's fixture offer) where buyer-side tx from is the gasless relayer, not the facilitator.
  • Bounded retry + backoff on /verify probe — 3 attempts at 500ms / 1s / 2s per the @mkmkkkkk #1065 pattern. 4xx responses read as ok (facilitator is responsive; probe-payload rejection is expected). Cached per facilitator URL for the duration of a single bazaar-check run.
  • anchor-x402-facilitator-fitness-ok-multi-rail.json new fixture — Ferj/@hypeprinter007-stack's 3-rail capture adapted to G acceptance. Tests per-rail emission + summary aggregation across Base/Solana/Polygon when CDP is declared and the facilitator probe returns 2xx.

Changed (G — X402-51)

  • bazaar-check JSON output: results[] now contains 7 entries (was 6 after L). New 7t...
Read more

v0.3.3

Choose a tag to compare

@github-actions github-actions released this 27 May 09:54
32b5545

[0.3.3] — 2026-05-27

Fast-follow on v0.3.2. Documentation polish, a body-discovery remediation copy fix from a first-time contributor, a hybrid D.3+D.5 captured-response fixture from @TKCollective, paid-audits + funding-rail surface additions on README, and ADR-007 recording v0.3.4 K (payment-payload echo gap rule pair) ahead of implementation. No code-level behaviour changes to verdict outputs; the bazaar-check JSON API contract (X402-44) is preserved verbatim. Cohort: three external contributors credited (@TateLyman across two PRs + @TKCollective fixture).

Added

  • AgentOracle captured-response fixture (hybrid D.3 + D.5) (#87, thanks @TKCollective 🙏). New tests/fixtures/bazaar/captured-responses/agentoracle-upstream-stuck-body-discovery.json — operator-contributed live capture from agentoracle.co/research showing the canonical 2026-05-09 → 2026-05-11 stuck-listing pattern: extensions.bazaar validates clean (BodyDiscoveryExtension variant, D.5 path), CDP discovery returns empty resources (D.3 indexer-state processing), composite verdict upstream_stuck. Captured under the #2207 cluster as TKCollective's bucket-2/3 reference case. Fourth fixture under the v0.3.2 captured-responses harness (alongside the three hand-rolled D.x captures from X402-47); first operator-contributed live capture from the named v0.3.2 cohort. Picked up automatically by tests/integration/bazaar-check-captured-responses.test.ts — no harness changes.
  • ADR-007 drafted in DECISIONS.md — v0.3.4 K (payment-payload echo gap diagnose rules + detail.upstream_stuck_cause discriminator). Records the design ahead of X402-50 implementation per ADR convention (same pattern as ADR-003 → X402-31 v0.3.0 and ADR-004 → X402-41 v0.3.2). ADR-005 (G facilitator-fitness, X402-51) + ADR-006 (I service_unreachable, X402-52) slots reserved for v0.3.4 implementation cycle. Two-voice promotion: @RipperMercs (TensorFeed canonical writeup, 1→29 indexed in <1hr) + @TKCollective (44-line patch, 16+d stuck → 22min indexed). @AsaiShota's contrast case (payload-correct, still stuck) baked into AC as false-positive sentinel.
  • Giveth project rail in .github/FUNDING.yml + README "Donate" section (#93). Giveth project page at https://giveth.io/project/x402trace joins the direct-wallet Basescan link as the second supported donation rail. Multichain support (Base, Ethereum, Optimism, Polygon) with optional GIVbacks rewards for donors. Donations through either rail land in the same wallet. Drips Network registration remains deferred per [[iran-residency-payment-rails]] constraints (platform-side ETH fee gate); FUNDING.json claim file from v0.3.2 stays in place for whenever the fee is payable.

Fixed

  • bazaar-check body-discovery remediation copy alignment (#80, thanks @TateLyman 🙏 — first-time contributor). Remediation message in the body-discovery sub-check refactor referenced the legacy MCP-discovery field names; aligned the copy to the variant-aware shape introduced in v0.3.2 D.5 (X402-43). Surgical copy fix only — no verdict-logic change, no JSON API impact. Audit-pass-first-time pattern for an external contribution.

Documentation

  • Bazaar contributor handbook in CONTRIBUTING.md (#86, thanks @TateLyman 🙏 — second contribution within 27h of accepting his handbook offer). New section covering captured-response fixture conventions (tests/fixtures/bazaar/captured-responses/ schema, self-describing JSON shape, automatic harness pickup), discovery-variant triage (BodyDiscoveryExtension vs McpDiscoveryExtension shape detection), and the no-payment-required testing discipline (fixture replay over live HTTP, deterministic verdicts in CI). Onboards the body-discovery + captured-response work shipped through v0.3.2 D.3/D.4/D.5/X402-47 for future external contributors.
  • Paid audits section in README.md (#89). Maintainer-side review offering for teams shipping x402-paid services at scale — bazaar-readiness gap audits, multi-rail integration checks, supply-chain hygiene review. Hourly + flat-rate options; payment via direct wallet or x402 itself. Companion surface to the funding rails (Basescan + Giveth + FUNDING.json) — donations support open-source maintenance; paid audits are commercial work.

Internal

  • Publish-surface cap raised 420 KB → 440 KB in scripts/check-publish-surface.mjs. Necessary for v0.3.3 to pass CI (CI-measured tarball at 430,475 bytes exceeds the 430,080-byte cap by 395 bytes — locally 429,993 bytes due to a ~482-byte pnpm-pack discrepancy between macOS and the GitHub Actions Linux runner). Same step size as v0.3.2's 400 → 420 cycle. Gives ~20 KB headroom for v0.3.4's K/G/I diagnose-rule additions and their new detail.* facets (upstream_stuck_cause, facilitator_fitness, reachability).
  • .gitignore for graphify-output/ artifacts (#90). Session-local knowledge-graph outputs from the /graphify workflow shouldn't ship in the repo or pack into the npm tarball. Clean separation from the published dist/ surface.
  • Canonicalize donate wallet to 0xe922Cc1D44C69bDEc8581Cc9Fd28bab8f59478CC (#91). Updated all in-repo references (README, FUNDING.yml, FUNDING.json) to the single canonical maintainer EOA. Same address resolves on Base + Ethereum mainnet.
  • FUNDING.json claim file for Drips Network (#92). Drips protocol expects a FUNDING.json at repo root with claim-signature fields; file is ready for the Drips registration whenever the platform-side ETH fee is payable. Defers the actual on-chain registration but lands the spec-correct claim shape.

Changed

  • src/cli/index.ts VERSION constant bumped 0.3.2 → 0.3.3.
  • CLAUDE.md Status line updated to reflect v0.3.2 SHIPPED to npm + external adoption evidence (@0xdespot, @poteshniy, @RipperMercs, @TKCollective public npx x402trace@0.3.2 runs in the #2207 closure loop) + v0.3.4 scope pointer (X402-50/51/52 filed 2026-05-27) + deagentic.ai forward-direction reference.

Notes

  • Test count: v0.3.2 shipped 511 passed + 4 skipped (515 total) → v0.3.3 runs 514 passed + 4 skipped (518 total), +3 tests from the captured-responses harness iterating over the new agentoracle fixture (top-level verdict assertion + per-check sub-verdict assertions). No new test files; the harness picks up the fixture automatically.
  • Tarball size: v0.3.2's 102 files / 416,867 bytes (~407 KB) unpacked → v0.3.3: 102 files / 430,475 bytes (~420 KB) unpacked in CI / 429,993 bytes locally on macOS (+13–14 KB from the new captured-response fixture + CHANGELOG entry + DECISIONS.md ADR-007 + README/FUNDING additions). pnpm-pack output is reproducibly ~482 bytes larger in the GitHub Actions Linux runner than on macOS (line-ending or pack-order details — not in scope to fix). The CI measurement is the source of truth. Publish-surface cap raised in this release: MAX_UNPACKED_BYTES in scripts/check-publish-surface.mjs bumped 420 KB → 440 KB — same step size as v0.3.2's 400 → 420 raise. v0.3.4's three diagnose-rule additions (K + G + I) and their new detail.* facets (upstream_stuck_cause, facilitator_fitness, reachability) get ~20 KB of headroom. Revisit again in v0.3.4 alongside the deferred legacy detail.status field cleanup on indexing per ADR-004's follow-up.
  • Runtime dependencies count unchanged from v0.3.2 (4: commander, dotenv, viem, x402). No supply-chain expansion. Zero devDep imports from dist/.
  • JSON API stability preserved. No additive or breaking changes to bazaar-check --log json envelope, facets, or verdict discriminator. Snapshot test passes against v0.3.2's frozen exemplar at tests/fixtures/bazaar/json-api-snapshot.json without regeneration. TomSmart_ai's mapper-integration + @poteshniy's agenttrust.uk/v1/reputation API (the named JSON API consumers per X402-44) require no changes.
  • No breaking changes. v0.3.2 → v0.3.3 is strictly additive (one new captured-response fixture + ADR-007 + docs + funding rail). v0.3.0/0.3.1/0.3.2 callers see identical behaviour.
  • External adoption signals captured during the v0.3.2 → v0.3.3 window: @0xdespot ran npx -y x402trace@0.3.2 bazaar-check against hyperD 2026-05-23 (D.4 --endpoint mode, returned upstream_stuck verdict on the variant-aware body-discovery path — exactly the AC for X402-42 + X402-43). @poteshniy (AgentTrust) shipped agenttrust.uk/v1/reputation 2026-05-26 — a free public compliance API that consumes the x402trace v0.3.2 JSON shape directly, validating the X402-44 stability commitment externally. @TomSmart_ai's mapper-mcp parser audit on 2026-05-27 (anchored to a maintainer reference to src/decoder/parse.ts:113-125) re-classified 401 previously-failed v2 endpoints as valid, a measurable ecosystem-cleanup outcome attributable to the v0.3.2 + Discord exchange chain. Five operators in the #2207 closure loop: RipperMercs / TKCollective / AsaiShota / 0xdespot / poteshniy.
  • v0.3.4 scope locked 2026-05-27: three diagnose-rule additions filed during this fast-follow window — X402-50 K (payment-payload echo gap, ADR-007 in this relea...
Read more

v0.3.2

Choose a tag to compare

@github-actions github-actions released this 22 May 23:31
1f2fc7f

[0.3.2] — 2026-05-23

The metadata-propagation release. v0.3.0 + v0.3.1 answered "is my Bazaar / agentic.market integration shaped correctly?"; v0.3.2 sharpens the upstream-attribution side of the same question — "if my manifest looks right, why isn't my listing rendering?" — with four new verdict pathways, a per-route probe mode, variant-aware extension validation, a published JSON API contract, and end-to-end fixture infrastructure. Seven Jira tickets (X402-41X402-47) ran through the strict 6-stage audit gate; all merged to main 2026-05-21 → 2026-05-23. ADR-004 codifies the three pillars (verdict semantics + JSON API stability + facilitator-aware attribution). No breaking changes to v0.3.0/0.3.1 surface — --log json additions are strictly additive per the new versioning rule.

Added

  • End-to-end fixture consumption for D.x verdict-synthesis paths (X402-47). New tests/fixtures/bazaar/captured-responses/ directory with three hand-rolled, self-describing fixtures — each capturing the well-known + challenge + discovery responses needed to exercise one v0.3.2 D.x failure mode through runBazaarCheck end-to-end without live HTTP. Initial set: d2-missing-propagation.json (manifest correct, indexer surfaces blank resource → metadata_propagation: missingupstream_issue; the @zev / TheRoosters / GM pattern), d3-processing-stuck.json (facilitator settled but CDP discovery returns 0 resources → indexer_state: processingupstream_stuck; Max's polyodds.bet pattern, canonical #2207), d5-body-discovery.json (extensions.bazaar uses BodyDiscoveryExtension shape — was false-positive implementation_issue pre-v0.3.2, now passes cleanly with looks_correct; AsaiShota's test-echo-cdp + 0xdespot's hyperD pattern). Self-describing JSON schema ({scenario, input, mocks, expected}); new integration test tests/integration/bazaar-check-captured-responses.test.ts iterates over every fixture, builds a mock fetcher dispatching by URL pattern, runs the full pipeline, asserts verdict + per-check detail facets match via dotted-path extraction. Adding a new fixture is one JSON file — the harness picks it up automatically. Scope cut vs original ticket: the original X402-47 AC called for consuming 6 named contributor fixtures (TomSmart cdp-mature, AsaiShota test-echo-cdp, evanatpizzarobot tensorfeed, 0xdespot hyperd, hypeprinter007 anchor-x402 multi-rail). Only TomSmart's first fixture is in the repo today; the other 5 are pre-committed but not delivered. This PR ships the fixture-consumption infrastructure with synthetic captures so the v0.3.2 audit gate has D.x coverage NOW; real contributor fixtures wire in as they arrive (TomSmart Sunday drop next).
  • D.3 indexer-state probe + upstream_stuck composite verdict (X402-46, ADR-004 Pillar 1 + Pillar 3). The existing indexing check now emits a detail.indexer_state facet with four values: indexed (≥1 resource in CDP discovery), processing (404 or empty resources — Max's polyodds.bet case + the canonical #2207 indexer-state-stuck cluster), unknown (HTTP error / non-JSON / network failure), and not_applicable_non_cdp (operator declared a non-CDP facilitator in their well-known manifest; CDP discovery is not the canonical indexer for this service per ADR-004 Pillar 3). When indexer_state: processing fires the verdict synthesizer returns a new composite verdict upstream_stuck — distinct from generic upstream_issue because the root cause is known (facilitator settled, indexer queue stalled). upstream_stuck rolls up to exit code 3 (preserves CI contract per ADR-004); verdict prose + JSON facets carry the granularity. New shared src/bazaar/facilitator-detect.ts helper — manifest-claim-based detection (extensions.bazaar.facilitator value), used by both D.2 (propagation) and D.3 (indexing). When facilitator is non-CDP, both D.2 and D.3 short-circuit to not_applicable_non_cdp BEFORE the network probe — fast, no HTTP cost, no false-positive. v0.3.3+ deferred: processing_fresh vs processing_stale distinction (requires settle-timestamp data we don't collect without driving live settles; future work via operator-supplied evidence flag).
  • D.2 metadata propagation diff (X402-45). New 5th check in bazaar-check results: propagation. Queries CDP discovery for the service's payTo and diffs the rendered fields (name, description) against what the operator declared in /.well-known/x402. Surfaces the @zev / TheRoosters / GM pain pattern: manifest is correctly shaped, indexer dropped fields, listing renders blank — your implementation is fine, the gating step is upstream. Emits detail.metadata_propagation with one of four states: ok (all diffed fields match — status pass), partial (some drift — status info + diff array showing per-field mismatches), missing (indexer surfaces none of the manifest's declared fields, matching the canonical #2207 indexer-state cluster — status info), unknown (defensive default when no manifest is available via --endpoint mode, no payTo is extractable, or the discovery query failed — status pass). New module src/bazaar/propagation.ts; pure-function computePropagationStatus() helper exported for downstream re-use. Diff scope intentionally narrow (name, description) — extends when new pain shapes surface. Facilitator-aware semantics layered separately: D.3 (X402-46) will add the explicit not_applicable_non_cdp state per ADR-004 Pillar 3; D.2 stays narrow and returns unknown for non-CDP services rather than asserting attribution it can't yet determine.
  • bazaar-check --log json is now a documented public API contract (X402-44, ADR-004 Pillar 2). Three deliverables landed together: the contract doc at src/bazaar/json-api.md (envelope shape + per-check detail keys + verdict discriminator + stability rules + regeneration workflow), a frozen exemplar at tests/fixtures/bazaar/json-api-snapshot.json, and a snapshot test at tests/integration/bazaar-check-json-api.test.ts (6 tests catch field renames, removals, additions, and reordering against the exemplar). Versioning rule committed: additive changes (new optional fields, new check names, new verdict.kind values, new detail.* keys) ship in MINOR versions with a ### JSON API CHANGELOG entry; shape-breaking changes (renames, removals, type changes, fixed-position reordering) require a MAJOR version + integrator notice. Exit-code contract preserved across all minor versions (D.3's upstream_stuck will roll up to exit code 3, not a new code). README "JSON API" section added under the bazaar-check documentation; CONTRIBUTING.md "JSON API discipline" section added with a PR self-check. TomSmart_ai's mapper-integration is the named consumer this contract is committed to.
  • bazaar-check --endpoint <paid-url> per-route 402 probe mode (X402-42, D.4). For services that publish per-route instead of at root /.well-known/x402 — the #2207 pattern documented by @AsaiShota (test-echo-cdp), @evanatpizzarobot (TensorFeed), and @0xdespot (hyperD.ai). When --endpoint is supplied, the bazaar-check pipeline skips the root well-known probe entirely and fetches the 402 challenge directly from the given paid URL; manifest-shape validations run against the 402 body instead of the root manifest. Self-payment guard + CDP indexing query continue to run unchanged (they consume the challenge body's payTo regardless of how the challenge was obtained). UX: a one-line info note prints when --endpoint is used (ℹ skipping root /.well-known/x402 probe per --endpoint. Note: services that DO publish at root signal extra discoverability hygiene; consider both.); routes to stdout in --log human and stderr in --log json so stdout stays JSON-parseable. New endpoint?: string field on BazaarCheckOptions (programmatic API); new endpoint?: string field on BazaarCheckCommandOptions. URL-validated at command entry; non-URL values exit 1 with a clear error.

Fixed

  • bazaar-check false-positive implementation_issue on body-discovery services (#72X402-43, thanks @AsaiShota 🙏 for the diagnosis with @x402/extensions@2.11.0 package-source citation, and @0xdespot 🙏 for the second-voice corroboration on x402-foundation/x402#2207). v0.3.0/0.3.1's src/bazaar/challenge.ts and src/bazaar/well-known.ts both validated extensions.bazaar assuming the MCP-discovery shape (top-level name + description). Real-world v2 services using the Body-discovery shape (info.input + info.output + schema per declareDiscoveryExtension(...)) failed the envelope check despite being correctly implemented — verdict overrode the substantive indexing-probe signal. New src/bazaar/extensions-bazaar.ts helper detects the variant by shape (body-discovery indicators win; else assume mcp-discovery per ADR-004) and validates the variant-appropriate required-field set. Default-deny third branch for future @x402/extensions variants we don't recognise yet — skips shape validation with an informational pass rather than false-positive. Tests cover ≥4 cases per affected file (challenge.ts + well-known.ts) plus 13 helper unit tests.

Changed

  • **indexing check's detail.status field gai...
Read more

v0.3.1

Choose a tag to compare

@github-actions github-actions released this 20 May 10:43
b053ba5

[0.3.1] — 2026-05-20

Hotfix release covering two bazaar-check bugs surfaced by external contributors within 72 hours of v0.3.0 ship, plus an npm-metadata fix from the v0.3.0 post-publish audit. No breaking changes — strictly additive.

Fixed

  • parseChallengeBody false-fails on canonical x402 v2 challenge bodies (#65#66, thanks @hypeprinter007-stack 🙏 — first external contributor). v0.3.0's src/decoder/parse.ts detected x402Version correctly but enforced v1 field names regardless, so v2-compliant bodies using the renamed amount field (instead of v1's maxAmountRequired) and lacking the v1 per-accept resource field failed with challenge accepts[0].maxAmountRequired missing or wrong type. v2 bodies are now normalized at parse time (amount → maxAmountRequired when only amount is present) and the per-accept resource requirement is dropped under v2 (resource lives top-level in v2). Error messages under v2 include the hint (v2 field name: "amount") so operators don't have to spec-dive. Surfaced against the real v2 service api.anchor-x402.com; e2e-verified to flip bazaar-check exit code from 2 (false-fail) to 0 (looks_correct).
  • bazaar-check hung indefinitely on stalled HTTP probes (#67, thanks @peterxing 🙏). When a checked endpoint accepted the connection but never resolved — or sent headers but then stalled the body — the CLI hung until killed manually, breaking CI / automation use. Now wrapped with a 10s default per-probe timeout via AbortController; configurable with --timeout-ms for CI / smoke runs / known-flaky endpoints. Body-read path keeps the timer active across arrayBuffer / blob / formData / json / text so headers-arrived-but-body-stalls is caught too. Upper bound validated against Node's setTimeout cap (2_147_483_647).

Changed

  • package.json description now reflects the v0.3 headline subcommands (was v0.2-era: "x402 payment debugger for Base. Detects reconciliation failures, pre-flights wallets, explains 402s."). Closes the audit gap discovered post-v0.3.0 publish where the npm-displayed package description didn't mention bazaar-check, validate --diff, or mainnet support. New audit-gate checklist item carried forward to v0.3.2+: "package.json description and README headline list both reflect this version's user-facing features."
  • src/cli/index.ts VERSION constant bumped 0.3.0 → 0.3.1.

Removed

  • Stale --rpc-url example for bazaar-check in the README. bazaar-check is HTTP-only and doesn't need an RPC URL (it uses the CDP discovery API for the indexing query); the example was misleading.

Notes

  • Adoption signal. Two distinct external contributors in 72 hours after v0.3.0 ship (@hypeprinter007-stack and @peterxing); both PRs merged within 12 hours of opening. Strongest "v0.3.0 found its audience" signal so far. Third independent positive signal in the same window: @TomSmart_ai (mapper operator) ran bazaar-check against 19 endpoints from his production catalog, 19/19 returned implementation_issue — first production-scale validation of the verdict taxonomy.
  • Pitch-language update. TomSmart_ai's framing — "catches the listing-readiness gap" vs "speaks x402 at all" (his strict-v2 sweep showed 88% protocol-valid on the same catalog) — is sharper than the prior README copy. Forward to v0.3.2+ surfaces.
  • No breaking changes. v0.3.0 → v0.3.1 is backward-compatible. v1 challenge bodies parse unchanged. Callers that don't pass --timeout-ms get the new 10s default; callers that need the old "wait forever" behaviour can pass --timeout-ms 2147483647 (Node's timer max, the documented upper bound).
  • Test count: 410 in v0.3.0 → 415 in v0.3.1 (+2 from #66 v2 parse coverage, +3 from #67 timeout coverage). All existing tests pass unchanged.

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 19 May 17:53
8dbcdcc

[0.3.0] — 2026-05-17

The v0.3 release. Operator-side debugging cut: x402trace can now answer the question Discord operators are asking each other in real time — "is my Bazaar / agentic.market integration correct, or is the bug upstream of me?" — in a 30-second command-line check. Same shipped binary contract as v0.2.x (no breaking changes to existing subcommands); two new subcommands; five new facilitator-aware diagnose rules; Base mainnet support behind an opt-in --chain flag; cross-facilitator drift detection on validate. Strict 6-stage audit gate ran on every ticket (X402-31..36).

Added

  • x402trace bazaar-check <service-url> (X402-32, headline). Pre-ship Bazaar / agentic.market implementation validator. Four read-only checks compose into a single bottom-line verdict: /.well-known/x402 manifest, 402 challenge structure (extensions.bazaar.{name, description}), self-payment guard (--payer-hint), and CDP indexing query (/v2/x402/discovery/resources). Exit codes: 0 looks_correct, 2 implementation_issue, 3 upstream_issue (the #2207 Bazaar-indexing pattern; named explicitly in the verdict prose). Maps the dominant Discord pain — ≥10 named voices on the #2207 cluster.
  • x402trace validate --diff <facilitators> (X402-35). Cross-facilitator drift detection. Comma-separated aliases (cdp, xpay, payai, x402.org) OR full URLs. Runs the synthesised payload through each facilitator's /verify endpoint in parallel via Promise.all, captures per-facilitator HTTP into a FacilitatorInteraction, and runs the X402-33 facilitator-aware rules per-facilitator. Exit codes: 0 any_accepts, 2 all_reject, 3 all_timeout. Closes TerraDeed's CDP → xpay manual workaround (Discord transcript) and #2184 (PayAI + Python SDK 2.9.0).
  • x402trace versions <service-url> (X402-36, stretch). SDK skew audit. Walks up from cwd for package.json and extracts @x402/* / x402-* / x402 versions; fetches the service URL's 402 for x402Version + Server header hints; matches both against a bundled known-skew dataset (@x402/fetch@2.10.0 extension echo bug, @x402/hono syncFacilitatorOnStart default, pre-v2 Python SDK bazaar emission). Exit 0 no skew / 2 skew detected. Closes Myceliaman14 + Poteshniy's Discord chases.
  • Five new facilitator-aware diagnose rules (X402-33). cdpMinAmountRule, selfPaymentRule, facilitatorThrottlingRule, extensionResponsesMissingRule, gasEstimationFailureRule. Each backed by named Discord/GitHub voices per ADR-003. New FacilitatorInteraction type + DiagnosticContext.facilitator + DiagnosticContext.expectsBazaarExtensions fields. Rules skip cleanly when their context fields are absent.
  • Base mainnet support (X402-34). New --chain <base-sepolia|base> flag on proxy, inspect, validate, bazaar-check, versions. Default stays base-sepolia (no surprise change). --chain base switches to Base mainnet (chain ID 8453) with the canonical mainnet USDC address (0x833589fCD…). Mainnet RPC URL must be supplied via --rpc-url or BASE_RPC_URL env; no default mainnet endpoint is shipped (CLAUDE.md hard rule #2). New BASE_CHAIN_ID env (accepts "base"/"base-sepolia" OR numeric "8453"/"84532", case-insensitive). Mainnet startup banner emits to stdout (human) or stderr (JSON). New ChainKey exported type, BASE_USDC constant, usdcAddressFor() helper.
  • EXIT_UPSTREAM = 3 exit code constant in src/cli/exit-codes.ts. Distinguishes "upstream issue detected" (bazaar-check, validate --diff all-timeout) from "implementation issue" (EXIT_RUNTIME = 2) and "usage error" (EXIT_USAGE = 1).
  • ADR-003 in DECISIONS.md (X402-31). v0.3 feature pick + autonomous-mode strict 6-stage audit gate codification. The gate substitutes for user review during autonomous execution; every PR in v0.3 ran through Pre-work → Implementation → Correctness audit → Edge-case enumeration → Re-audit → Ship.
  • CLAUDE.md hard rule #8 + "Strict audit gate" section. Codifies the gate so future sessions follow it.
  • Cross-platform evidence base. Plan and ADR-003 cite Discord transcript (10+ named voices on Bazaar indexing failures), GitHub issues (#2207 cluster, #1065, #2294), Dev.to article, and agentic.market directory.

Changed

  • CLAUDE.md hard rule #2 updated from "Testnet only until v0.1 ships" to "No committed mainnet RPC URLs" (v0.3 enables mainnet code; CI never uses mainnet).
  • src/cli/index.ts VERSION constant bumped 0.2.3 → 0.3.0 (kept in sync with package.json).

Deferred to v0.3.1+

  • Paid-pass mode (--with-wallet) in bazaar-check — requires signing infrastructure (changes ADR-001 read-only contract) or pre-signed payload pipeline. Static-analysis-only bazaar-check ships now; real-settlement EXTENSION-RESPONSES surfacing is detectable via X402-33's extensionResponsesMissingRule for callers that drive their own facilitator HTTP.
  • SLA-breach observation event (X402-37) — single Discord voice + schema-change risk failed the strict-bar; deferred until a 2nd named operator surfaces independently. Hikari is shipping Recourse as the enforcement product.
  • ERC-6492 Smart Wallet support, reconciliation webhook/auto-retry, extensions.diagnostic decoder (gated on PR #1875), tokenNameMismatchRule, repeatedNonceRule, daemon mode, audit export, multi-chain (non-Base), hosted SaaS — all listed in ADR-003 with documented deferral reasons.

Fixed (X402-38 pre-publish audit, 2026-05-17)

  • validate --diff: AbortController signal was never passed to fetch — the timeout fired controller.abort() but the fetch call didn't receive the signal, so real-world timeouts would not actually cancel the request. Tests passed because the mock fetcher threw AbortError directly. Fix: DiffFetcher type extended with signal?: AbortSignal; signal now plumbed through. Two new regression tests assert the signal is received by the fetcher and reports aborted=true after the timeout window.
  • Pre-existing flake at tests/integration/demo-timeout-reconciliation.test.ts:114 (50ms fixed sleep racing the engine event bus under parallel-test load). Hit CI twice in this session; would have intermittently broken the publish workflow's prepublishOnly step. Fix: replaced fixed sleep with a pollFor helper that retries up to 2s in 25ms steps. 5/5 consecutive runs pass post-fix.

Notes

  • 278 → 410 tests (+132 new across X402-31..36 + audit). The pre-existing flake noted above is now deterministic.
  • Tarball size: 74 files / 222 KB unpacked at v0.2.3 → 96 files / ~337 KB unpacked at v0.3.0. Well under the 400 KB CI guard cap.
  • Runtime dependencies count unchanged from v0.2.3 (4: commander, dotenv, viem, x402). No supply-chain expansion.
  • Audit findings documented but NOT fixed in v0.3.0 (all low severity, none block release):
    1. cdpMinAmountRule applies the same minimum across chains; the $0.001 was Discord-confirmed for Sepolia only. Mainnet minimum may differ. Rule fails-soft (suggests a higher amount); documented inline in src/diagnose/rules.ts.
    2. validate --diff silently overrides --strict. Documented in src/cli/validate-command.ts.
    3. parseFacilitatorList allows duplicate aliases (e.g. --diff cdp,cdp). Harmless but wasteful; documented.
    4. extractX402Versions (the versions subcommand) accepts non-semver values (workspace:*, github:foo/bar). match: "any" known-skew entries can fire false-positives for monorepo users. Edge case; promote to a fix when a real user reports it.

v0.2.3

Choose a tag to compare

@github-actions github-actions released this 13 May 14:28
99473f9

[0.2.3] — 2026-05-13

Supply-chain hardening patch. No functional changes from 0.2.2 — same CLI behaviour, same diagnostic rules, same chain client, same shipped binary (dist/). The bump exists to publish a cleaner install graph and to ship two community files that supply-chain scanners reward.

Changed

  • hono, x402-fetch, x402-hono reclassified from dependencies to devDependencies (X402-26). These three packages are imported only by src/dogfood/, scripts/, and tests/ — paths excluded from tsconfig.build.json and therefore from the published dist/. The shipped tarball is byte-for-byte equivalent to 0.2.2's; the only thing that changes is what npm i x402trace pulls into a consumer's node_modules/. End-user install graph drops the entire WalletConnect / MetaMask SDK / safe-global transitive tree (the source of the 4 high + 10 medium CVE alerts on the Socket report for 0.2.2).
  • src/cli/index.ts VERSION constant bumped 0.2.2 → 0.2.3 (kept in sync with package.json).

Added

  • CODE_OF_CONDUCT.md — Contributor Covenant v2.1 verbatim, contact pointed at the repo's private vulnerability reporting + maintainer email (X402-26).
  • SECURITY.md — vulnerability reporting channels, response targets, scope, and an explicit "what x402trace does/doesn't do" section so reporters know what's in-bounds (X402-26).
  • README supply-chain FAQ — one new Q&A pair pre-empting "my scanner shows transitive alerts on x402trace deps" by naming the runtime tree (commander + dotenv + viem + x402) and pointing wallet-SDK transitives to their actual source (X402-26).
  • CI publish-surface guard (X402-27) — new scripts/check-publish-surface.mjs runs after pnpm build in CI + locally via pnpm check:publish-surface + as part of prepublishOnly. Caps the bundle at 100 files / 400 KB unpacked and forbids any file in dist/ from importing a package listed in devDependencies. Locks in the X402-26 fix so dep classification can't quietly drift back.
  • Dependabot config (X402-28) — weekly grouped npm updates (Mondays; dev-deps + production-patches bundled, semver-majors ignored) plus monthly ungrouped GitHub Actions updates. Gives us a weekly heads-up when an upstream ships a CVE patch instead of waiting for an external scanner.
  • CLAUDE.md hard rule #8 (X402-29) — "The published bundle defines the runtime dependency set." Codifies the X402-26 lesson so future sessions don't recreate the misclassification.

Security

  • Eliminates the wallet-SDK transitive tree (@walletconnect/*, @metamask/sdk, @safe-global/*) from end-user installs of x402trace. The CVE alerts those packages carry are still real — they're just no longer dragged into node_modules/ for a CLI that doesn't use them. Anyone running the dogfood rig or contributing locally still gets them via devDependencies.

Notes

  • The dist/ is byte-for-byte the same shape as 0.2.2: 74 files, ~222 KB unpacked. Verified locally + enforced by the publish-surface CI guard going forward.
  • Socket score recalibration takes a few hours after publish; Snyk a day. Predicted lift: Socket Supply Chain Security 77 → 90+, Snyk Health 27 → 35-45.
  • Five tickets in the v0.2.3 batch: X402-26, X402-27, X402-28, X402-29, X402-30 (this release cut).

v0.2.2

Choose a tag to compare

@github-actions github-actions released this 13 May 09:18
f618249

[0.2.2] — 2026-05-13

Docs-only patch: ships the three animated GIF demos to the npm package page (npmjs.com only re-renders the README on publish). No functional changes from 0.2.1.

Changed

  • README hero is now a live animated GIF — the X402-15 reconciliation demo, generated from the committed asciinema cast via agg. Renders inline on github.com, npmjs.com, and any markdown viewer (256 KB, under X / Twitter's 15 MB cap).
  • validate and explain example sections each now include their own demo GIF (27 KB + 36 KB) above the existing text-output blocks. Text blocks remain for AI-agent quoting and grep-friendly inspection.
  • Three new committed asciinema source casts under examples/cast/ (e2e-timeout-reconciliation.cast, validate-demo.cast, explain-demo.cast) — replayable with asciinema play.

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 13 May 08:52
f6ada6d

[0.2.1] — 2026-05-13

Documentation + discoverability patch. No functional changes from 0.2.0 — same CLI behaviour, same diagnostic rules, same chain client. The bump exists so npm refreshes its search index with the new description + keywords (npm only re-indexes on publish).

Changed

  • package.json description — was "Local CLI for debugging x402 payment flows on Base — catches timeout reconciliation failures"; now "x402 payment debugger for Base. Detects reconciliation failures, pre-flights wallets, explains 402s." Surfaces all three product capabilities in npm search instead of just reconciliation.
  • package.json keywords (9 → 14) — added http-402, base-sepolia, payment-debugging, timeout-reconciliation, eip-3009, facilitator, coinbase-x402, agentic-payments; removed redundant debugging / vague observability / misleading ethereum (Base is an L2).
  • README — added four discoverability blocks for human + AI-agent readers:
    • "When to use x402trace" — 4 problem-statement bullets, each pattern-matching an AI agent's reasoning loop ("wallet debited but server says failed" → proxy --reconcile, etc.)
    • "The four subcommands at a glance" — ASCII lifecycle visual keying validate / proxy / inspect / explain to the BEFORE / DURING / POST / FAILURE phases of a payment
    • Concrete terminal output blocks for validate and explain so devs + AI agents can verify-before-install
    • Comparison table vs xpay / x402scan / x402lint (replaces the previous prose paragraph)
    • 4-question FAQ in the Q&A pattern AI tool-cards quote into recommendation snippets
  • VERSION constant in src/cli/index.ts bumped 0.2.0 → 0.2.1 (kept in sync with package.json).

Notes

  • The live tx hash 0x116ccf73…ba52 is now above the fold in the README so crawlers / GEO snippets have a verifiable on-chain anchor.
  • Release workflow's contents: write permission (fixed for v0.1.0) means this tag-push self-creates the GitHub Release without manual intervention.

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 12 May 17:33
c98d50a

[0.2.0] — 2026-05-12

The v0.2 pre/post-payment debugger. v0.1 owned mid-flight (proxy) + post-settlement (reconcile); v0.2 adds pre-flight (validate) and offline failure diagnosis (explain), sharing a new pure rule engine in src/diagnose/. Closes pain ranks #3 (generic 402 with no error reason) and #4 (wallet-state pre-flight gap) from the X402-6 ranking. 278 tests, same Base Sepolia / exact EVM scope as v0.1 per ADR-002. Apache-2.0.

Added

  • x402trace validate <wallet> <service-url> (X402-21) — read-only pre-flight before signing. Fetches the 402 challenge, queries on-chain USDC balance + EIP-3009 nonce status + wallet kind (EOA vs Smart Wallet via getCode), synthesises a hypothetical PaymentPayload, runs the diagnose engine, renders a plain-English report. Exits 0 for would-succeed, 2 for would-fail, 0 for uncertain (or 2 with --strict).
  • x402trace explain <jsonl-log-file> (X402-21) — read a JSONL log produced by proxy --reconcile, find every exchange where reconcile.result.kind != 'settled_on_chain' plus every decoder.error, run the same rule engine against captured state, print per-failure prose with actionable fixes. CI-friendly: exits 2 if any failures rendered, 0 if log was clean.
  • src/diagnose/ (X402-21) — pure rule engine (no I/O, no Date.now). 10 rules covering network match, scheme match, recipient match, value sufficiency, validBefore / validAfter window, payer USDC balance, EIP-3009 nonce freshness, wallet kind (EOA + Smart Wallet; ERC-6492 deferred to v0.3 per ADR-002), and Base Sepolia USDC asset address. Each rule returns pass / fail / skip; skip means the context lacked the data (e.g. explain doesn't have live wallet state). Top-level status is would-succeed / would-fail / uncertain (the latter when the two critical chain-state rules are skipped).
  • Chain client extensions (X402-21)getUsdcBalance(wallet), isNonceConsumed(authorizer, nonce), detectWalletKind(wallet) read-only methods on ChainClient, plus a narrow USDC_READ_ABI (just balanceOf + authorizationState). Used by validate; reusable by future v0.3 features.
  • v0.2 feature pick (X402-20) — ADR-002 records the decision + 4 rejected alternatives. SPEC.md § 5 flipped from "v0.2 stretch (deferred)" to "v0.2 scope" with a new v0.3 stretch list catching the deferrals. CLAUDE.md current-focus flipped to v0.2.
  • CI release workflow contents: write fix — release.yml's Create GitHub Release step had failed on the v0.1.0 cut with HTTP 403 because the job had contents: read. Promoted to write so v0.2.0+ tag-pushes self-create the GitHub Release without manual intervention.

Tests

  • 278 total (+63 from v0.1.0's 215). New: 36 unit tests for diagnose-rules, 14 for validate-command, 9 for explain-command, +4 for cli-dispatcher covering the new subcommands.

Notes

  • package.json bin layout unchanged from v0.1.0 — x402trace resolves to four subcommands (proxy, inspect, validate, explain).
  • tsconfig.build.json is still the published-bundle config; tarball stays ~62 files / ~156 KB.

v0.1.0 — v0.1 wedge

Choose a tag to compare

@fardinvahdat fardinvahdat released this 12 May 11:16
cb4193d

[0.1.0] — 2026-05-12

The v0.1 wedge: a local proxy + timeout-reconciliation engine that catches the canonical coinbase/x402#1062 symptom — buyer is debited on-chain but the facilitator/server thinks the payment failed. Verified end-to-end on real Base Sepolia + the live x402.org/facilitator (tx 0x116ccf73…ba52). 215 tests, GitHub Actions CI on Node 20 + 22, Apache-2.0.

Added

  • Initial project scaffold (X402-2)
  • CLAUDE.md operating manual for Claude Code sessions
  • TESTING.md defining test requirements per change type
  • SPEC.md, ARCHITECTURE.md, DECISIONS.md skeletons
  • CONTRIBUTING.md, dogfood-notes.md skeletons
  • .env.example configuration template
  • .github/PULL_REQUEST_TEMPLATE.md enforcing test checklist
  • Apache 2.0 license
  • Dogfood rig on Base Sepolia (X402-3): Hono + x402-hono@1.2.0 server (src/dogfood/app.ts, api/[...all].ts for Vercel, scripts/dev-server.ts for local), paying client via x402-fetch@1.2.0 (scripts/dogfood-client.ts), env validation with mainnet-RPC guard (src/dogfood/config.ts), and 20 unit tests covering config validation and 402 challenge generation. Verified end-to-end against the real x402.org/facilitator on Base Sepolia — paid GET returned 200 with on-chain settlement tx 0x8b53a04d…b3428.
  • Public Vercel production deploy (X402-3) on the v1 branch alias at x402trace-dogfood-git-v1-fardinvahdats-projects.vercel.app serving / (static landing) and /api/weather (x402-gated). Second on-chain settlement against the real x402.org/facilitator from this production endpoint: tx 0xc5758bf2…6cbf.
  • Five-failure-mode reproduction harness for X402-4 (scripts/failure-modes.ts, pnpm dogfood:failure-modes <n>). Captures verbatim server/client/facilitator error strings for: wrong chain ID, expired validBefore, insufficient USDC, malformed signature, facilitator unavailable. Full transcripts + diagnoses in dogfood-notes.md § Failure modes.
  • Week-1 pain synthesis (X402-6) in dogfood-notes.md § Top painful moments: 9 ranked pains + 5 wedge candidates (A reconciliation, B inspect+doctor, C bazaar-check, D cross-facilitator, E proxy substrate) — pulls from X402-3 dogfood capture, X402-4 failure modes, X402-5 GitHub catalogue, and the Notion Validation evidence page. CLAUDE.md updated to point future sessions at the table for feature-scope work.
  • v0.1 wedge accepted (X402-7) — ADR-001 in DECISIONS.md: local HTTP proxy substrate + timeout-reconciliation engine on top. Scope tightened for the 5-week timeline: Base Sepolia only, single facilitator profile (x402.org/facilitator), exact EVM scheme only, detect-and-notify (no auto-refund in v0.1). CLAUDE.md status updated from "tentative" to "accepted." Bazaar diagnostics, cross-facilitator drift, inspect/doctor/versions deferred to v0.2+.
  • v0.1 implementation spec (X402-8) filled in at SPEC.md: problem, solution, user flow (x402trace proxy --upstream <url> --reconcile + sample RECONCILED ⚠ settled-but-server-thinks-not output), v0.1 scope/v0.2 stretch lists, 5 success-criteria checkboxes, explicit out-of-scope non-goals, and per-competitor differentiation against xpay / x402scan / x402lint / x402-watch / zauth / PaySentry. Linked from CLAUDE.md.
  • v0.1 architecture (X402-9) finalized in ARCHITECTURE.md: 5-component decomposition (Proxy src/proxy/, Decoder src/decoder/, Chain src/chain/, Reconciliation src/reconciliation/, CLI src/cli/) with one-example data flow traced through every component for happy / rejected / timeout outcomes; TypeScript interface stubs ready to become source code (PaymentRequirements, PaymentPayload, FacilitatorResponse, PaymentExchange, ExchangeOutcome, ChainTransfer, ReconciliationResult); canonical JSONL record format (the file is the API); full configuration precedence table; v0.2 extension points named per feature so no v0.1 component is rewritten for v0.2.
  • Proxy core (X402-10) in src/proxy/: forward HTTP proxy that captures every exchange to a JSONL log + in-process event bus. Five modules — proxy.ts (server + forwarding via fetch), types.ts (ProxyEvent / CapturedRequest / CapturedResponse / ExchangeOutcome discriminated union + isLikelyX402Exchange heuristic), event-bus.ts (subscribe-with-queue-and-drop-counter pub-sub), jsonl-sink.ts (append-only writer), id.ts (per-exchange UUIDs). Hop-by-hop headers stripped per RFC; non-UTF8 bodies base64-encoded; upstream timeout returns 502 + proxy.error event. Deliberately dumb — no x402 parsing here (that's X402-11). 18 new unit tests + a 4-test integration that pipes the dogfood client through the proxy at the X402-3 dogfood rig (mock-facilitator-backed) and asserts both the 402 and the paid 200 are captured to JSONL with the right discriminants. pnpm proxy --upstream <url> runs it; full npx x402trace proxy plumbing arrives in X402-14.
  • x402 message decoder (X402-11) in src/decoder/: pure-function parsers that turn raw ProxyEvents into typed DecodedEvents. Six modules — types.ts (PaymentRequirements, PaymentAuthorization, PaymentPayload, FacilitatorResponse, DecodedEvent discriminated union), parse.ts (parseChallengeBody, parsePaymentHeader, parseSettlementHeader, version detection — uses x402/schemes's exact.evm.decodePayment for the v1 fast path, hand-rolled fallback for v2), redact.ts (signature redaction by default, --log-secrets opt-in), format.ts (formatHuman and formatJson), decoder.ts (createDecoder() stream consumer), index.ts. Includes src/decoder/schema.md documenting the JSONL contract. Handles both v1 (X-PAYMENT / X-PAYMENT-RESPONSE) and v2 (PAYMENT-SIGNATURE / PAYMENT-RESPONSE) header surfaces. 22 new unit tests covering v1 + v2 parsers, redaction, formatting + a 4-test integration that asserts the proxy→decoder→PaymentExchange pipeline produces the right structured events from a paid flow. Stdout sample of the readable output is captured in dogfood-notes.md § "Decoder readable-output sample" per acceptance criterion; pnpm decoder:demo reproduces it.
  • Base RPC client (X402-12) in src/chain/: thin viem wrapper over Base Sepolia. Five modules — types.ts (ChainTransfer + VerifyTransferResult 7-variant discriminated union: confirmed / pending / reverted / not_found / wrong_recipient / wrong_amount / wrong_token), abi.ts (Base Sepolia USDC address 0x036CbD…CF7e + Transfer + EIP-3009 AuthorizationUsed event ABIs), retry.ts (exponential backoff, 3 attempts default per ARCHITECTURE.md), client.ts (createChainClient with verifyTransfer, getTransferByTxHash, subscribeUsdcTransfers AsyncIterable, getBlockNumber), index.ts. Read-only — never holds private keys, never broadcasts. subscribeUsdcTransfers enriches each Transfer event with the matching AuthorizationUsed.nonce from the same tx so the reconciliation engine can match by EIP-3009 nonce. 16 unit tests with mocked transport covering all 7 verify variants + the retry helper + 4 e2e tests against live Base Sepolia (gated by X402_E2E=1; verified against the two real X402-3 settlement txs 0x8b53a04d…b3428 and 0xc5758bf2…6cbf).
  • GitHub Actions CI (X402-18).github/workflows/ci.yml runs pnpm typecheck, pnpm lint, pnpm test, pnpm build on every PR + push to v1 / staging / main. Node 20 + 22 matrix, pnpm-store cached via actions/setup-node@v4, 10-min job timeout, in-progress runs cancelled when a fresher commit lands on the same ref. pnpm test auto-skips tests/e2e/chain-live.test.ts (gated on X402_E2E=1), so the live-Base-Sepolia suite never burns testnet funds in CI. Companion .github/workflows/release.yml is the X402-19 substrate: tag-triggered (v*.*.*), runs the same quality bar, builds, and has the npm-publish step commented out until X402-19 wires the NPM_TOKEN secret. The CI badge in README.md (placeholder since X402-16) lights up on the first run.
  • Unit-test coverage hardening (X402-17) — Week-4 risk-reduction pass on the decoder, reconciliation, and CLI. Per the ticket spec ("chase risk reduction, not coverage targets"), targeted the gaps that break silently: (a) the streaming decoder's dispatch logic (createDecoder().decode()) had zero direct tests — new tests/unit/decoder-decoder.test.ts (11 tests) covers settlement-header parse errors, the outcome.rawPaymentResponseHeader fallback path, and proxy.error passthrough; (b) base64 + unicode edge cases on parsePaymentHeader / parseChallengeBody / parseSettlementHeader mirroring the coinbase/x402#865 surface area — CJK + emoji in description and extra.name round-trip, padding-stripped base64 tolerated, JSON primitives rejected, URL-safe base64 contract documented; (c) reconciliation extractErrorReason paths (non-JSON rawBody, JSON without error, missing rawBody), the unknown proxy outcome branch the X402-15 demo relies on, chain-transfer race conditions (arrival before pending join, duplicate transfers after match); (d) x402trace proxy env-var-vs-flag precedence — extracted resolveProxyConfig(opts, env) as a pure function from proxy-command.ts (small refactor for testability), then pinned the contract from ARCHITECTURE.md § Configuration with 28 unit tests across X402TRACE_UPSTREAM, `X402TRACE_PORT...
Read more