ADR-002 Accepted 2026-05-20

OpenAPI 3.1.0 Contract-First

Define the API contract in a machine-readable spec before writing backend code.

Context

madcatalog has a REST API consumed by AI agents, MCP clients, SDK developers, and human engineers. The contract must be machine-readable for programmatic discovery, human-readable for onboarding, and validated automatically so schema drift cannot reach production undetected.

MPP (Machine Payments Protocol) introduces non-standard HTTP headers (WWW-Authenticate: Payment, Authorization: Payment, Payment-Receipt) that need to be modelled explicitly, not inferred from code.

Decision

Define the full API in api/openapi.yml (OpenAPI 3.1.0) before writing any backend Lambda code. Validate the spec on every commit using npx @redocly/cli lint as both a pre-commit hook and a CI quality gate.

The x-payment-info OpenAPI extension (part of the MPP OpenAPI Discovery spec) is used to let MPP clients discover payment terms before triggering a live 402. Redocly preview (task swagger, port :8081) serves an interactive human-browsable API reference locally.

Consequences

Positive
  • Machine-readable contract: agents and MCP clients can discover endpoints and payment terms from the spec
  • Schema violations are caught at commit time, not at runtime
  • Redocly preview gives an instant human-browsable API reference at :8081
  • x-payment-info extension lets MPP clients pre-fund wallets without triggering a live 402
  • Contract above implementation: backend Go code is constrained by the spec, not the other way around
Negative
  • Two acceptable lint warnings cannot be suppressed without incorrect schema changes: info-license-strict (no license URL) and operation-4xx-response on GET /catalog (no 4xx defined, which is correct)
  • YAML verbosity for complex nested schemas (Ad object + optional enrichment fields)
  • Spec and implementation can drift if schema is updated without a matching code change

Alternatives Considered

OptionWhy not chosen
Code-first (generate OpenAPI from Go struct tags)Loses MPP-specific extensions; spec becomes an artifact of implementation rather than a contract above it
No specNo machine-readable contract; agents must reverse-engineer the API; unacceptable for MPP ecosystem participation
Stoplight / Postman collectionsProprietary formats; OpenAPI 3.1.0 is the industry standard and directly supported by the Redocly toolchain already in use