All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

[0.4.1] - 2026-08-15

Fixed

  • Declare :telemetry as a required runtime dependency so telemetry events and facilitator calls work in downstream installs without optional dependencies
  • Start the OTP :public_key application used by X402.Facilitator.HTTP.secure_pool_opts/0
  • Exercise the library from a minimal downstream Mix project in CI to catch missing runtime dependencies before publishing

[0.4.0] - 2026-08-15

Added

Changed

  • X402.Plug.PaymentGate now verifies before the protected handler and settles only after a successful handler response
  • Facilitator requests now use the v2 {x402Version, paymentPayload, paymentRequirements} wire format
  • "upto" verification uses PaymentRequirements.amount as the authorized maximum; settlement uses it as the actual atomic amount charged
  • Plug route prices and all documentation examples use atomic token units

Fixed

  • Fail closed when facilitator responses omit or mistype isValid, success, transaction, or network
  • Preserve the full request URL, including its query string, in ResourceInfo.url
  • Reject partial or mutated accepted requirements instead of matching only five fields
  • Return HTTP 500 for facilitator transport failures and malformed facilitator responses while retaining HTTP 400 for invalid input and HTTP 402 for payment failure
  • Reject unsupported upfront and escrow flows instead of applying unsafe authorization-flow timing
  • Avoid creating atoms from untrusted string route keys
  • Compile cleanly without optional SIWX crypto dependencies and return :missing_dependency when the default verifier cannot load them

Migration

  • Replace the removed Plug option facilitator_url: with a supervised X402.Facilitator process and pass it via facilitator:.
  • Replace decimal display amounts such as "0.01" with atomic-unit strings such as "10000" for six-decimal USDC.
  • Hook callbacks use context.payload / context.requirements and return {:cont, context}, {:halt, reason}, or {:recover, result} as documented by X402.Hooks.

[0.3.3] - 2026-03-29

Fixed

  • Payment signature format validation and SIWX ETS size cap (#39)
  • Tightened Solana address validation and warn on missing idempotency cache (#36)
  • Enforce https:// scheme on facilitator base_url — prevents plaintext credential leakage (#35)
  • Added 8KB payload size cap to PaymentRequired and PaymentResponse to prevent oversized payloads (#34)
  • TLS peer verification enabled by default and PAYMENT-SIGNATURE header size cap (#32)

Changed

  • Bumped minimum Elixir to ~> 1.19 (#33)
  • Optimized decimal parsing and centralized utility functions (#37)

Added

  • Unit test for HTTP.secure_pool_opts/0 (#38)

[0.3.2] - 2026-03-01

Fixed

  • Safe cache eviction with bounded cleanup to prevent full-table scans under load (#30)
  • Atomic payment claim in PaymentGate plug to prevent double-settlement on concurrent requests (#30)
  • SIWX ETSStorage read consistency — route get through GenServer to prevent revoked session reads (#31)
  • Full-jitter exponential backoff in Facilitator.HTTP to prevent thundering herd on retries (#31)
  • Base.decode64 padding safety in PaymentSignature and PaymentRequired (#31)

[0.3.1] - 2026-02-25

Fixed

  • Fixed unbounded ETS cache growth vulnerability (DoS) — added max_size config with LRU eviction (#17)
  • Fixed expired entries not being deleted during direct ETS reads (#25)
  • Fixed mix format compliance across all files

Added

  • Comprehensive tests for X402.Behaviour.implements?/2 with doctests (#28)
  • Test coverage for facilitator hook exception and throw handling (#24)
  • Optimized ETS cache with direct concurrent reads bypassing GenServer serialization (#25)

[0.3.0] - 2026-02-17

Added

Changed

  • ex_secp256k1 and ex_keccak are now optional dependencies (only needed for SIWX)
  • ETS storage uses :protected access with direct reads bypassing GenServer for better concurrency

Fixed

  • Credo strict compliance: implicit try, redundant with clauses
  • Dialyzer: unreachable pattern matches in PaymentIdentifier and SIWX Verifier

[0.1.0] - 2026-02-14

Added