wavefront

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: Apache-2.0, MIT

README

wavefront

A small, infrastructure-agnostic edge proxy that maps a versioned external contract onto a single evolving internal HTTP/JSON backend. Clients frozen at different points in contract-time keep working while the backend migrates freely.

pinned clients --versioned protobuf--> wavefront --current JSON/REST--> backend
                                           |
                                           +- descriptor bundle (proto + version map)
                                           +- per-version request/response transform
                                           +- auth-transparent (forwards the bearer)

Why

A pinned client is nearsighted in time: it sees an API only as it was the day it shipped — app-store update lag, partners on last year's contract, a surface on an old build. Without mediation, every internal change is hostage to the oldest client in the wild, and teams accrete /v1 /v2 /v3 sprawl inside every service.

By Fermat's principle, a signal crossing differing media takes the path of least time and its wavefront reshapes to still arrive coherent. wavefront is the version-mediation scheme, extracted: one declarative edge where external contract variance is absorbed so the internal API stays singular.

Core concepts (1-minute version)

  • Bundle — the descriptor input: a proto FileDescriptorSet, the current internal OpenAPI doc, and a declarative version map. Generated by the consumer, committed, loaded read-only.
  • Contract version — the external contract a client speaks; the selector that picks a transform profile.
  • Transform — declarative request/response mapping for a version (field add / rename / optionalize / default / coerce; route remap).
  • Adapter — a codec pair. protobuf ↔ OpenAPI/JSON is the reference adapter, not the identity.
  • Selector — the key the version map is keyed on: version, codec, client-profile, tenant, or migration cohort. Same engine, different key.

For depth, see docs/concepts.md.

What it is — and isn't

It IS:

  • A descriptor-driven edge contract-mapping engine.
  • A version anti-corruption layer over a single internal backend.
  • Auth-transparent: it forwards the bearer; the backend validates.
  • Codec-agnostic via adapters (protobuf↔JSON shipped first).

It IS NOT:

  • An auth server. Bring your own token issuer/validator (the backend's).
  • A policy/authz engine. No PII redaction, no business logic.
  • A message broker or database. No persistence, no replay.
  • A reverse proxy / TLS terminator / router. The ingress owns that.
  • A WebSocket/streaming tier. The wss-mux sibling owns WS fanout.

Quick start

Generate the bundle from your OpenAPI — a file, or the live service's /openapi.json (no manual export step) — then run the proxy against it:

go build -o wavefront-bundlegen ./cmd/wavefront-bundlegen

# from a file…
./wavefront-bundlegen --openapi ./openapi.json --out ./bundle
# …or straight from a running service:
./wavefront-bundlegen --openapi https://api.internal/openapi.json --out ./bundle

The bundle is committed in your repo (it is the contract source of truth) and mounted or baked in for wavefront.

From source:

go build -o wavefront ./cmd/wavefront

WAVEFRONT_BUNDLE_PATH=./bundle \
WAVEFRONT_UPSTREAM_BASE_URL=http://localhost:9000 \
./wavefront

Or via the prebuilt multi-arch container:

docker run --rm -p 8080:8080 \
  -e WAVEFRONT_BUNDLE_PATH=/etc/wavefront/bundle \
  -e WAVEFRONT_UPSTREAM_BASE_URL=http://core-api:9000 \
  -v $(pwd)/bundle:/etc/wavefront/bundle:ro \
  ghcr.io/alternet-dev/wavefront:latest

The bundle directory holds descriptors.binpb (proto FileDescriptorSet), openapi.json (current internal surface), and versions.yaml:

version: 1
contracts:
  - contract_version: "2024-11"
    route: /v0/me/session
    transforms:
      - rename: { from: displayName, to: display_name }
      - default: { field: locale, value: en-US }

Configuration

All configuration is environment variables, read once at startup.

Var Default Meaning
WAVEFRONT_BUNDLE_PATH — (required) path to the descriptor bundle dir
WAVEFRONT_UPSTREAM_BASE_URL — (required) the single internal backend base URL
WAVEFRONT_LISTEN_ADDR 0.0.0.0:8080 bind address for HTTP
WAVEFRONT_METRICS_ADDR 0.0.0.0:9090 bind address for /metrics
WAVEFRONT_CONTRACT_VERSION_HEADER X-Api-Contract-Version header carrying the client's contract version
WAVEFRONT_REQUEST_TIMEOUT_MS 15000 upstream request timeout
WAVEFRONT_MAX_BODY_BYTES 1048576 inbound body cap
WAVEFRONT_LOG_LEVEL info structured log level

Operational notes:

  • SIGHUP reloads and re-validates the bundle without dropping in-flight requests. A failed reload keeps the previous bundle serving.
  • Fail-fast. A missing/invalid bundle at boot → refuse to start.
  • GET /metrics exposes Prometheus/OpenMetrics counters keyed by contract version + transform outcome; /health and /ready are the probes.
  • Codec. protobuf is the reference inbound codec; adapters are selected by content negotiation. Auth + tracing headers are forwarded untouched.

The version-map schema and transform vocabulary are detailed in docs/protocol.md; integrating a consumer is covered in docs/embedding.md.

Reading order

  1. docs/concepts.md — first principles + vocabulary
  2. docs/protocol.md — bundle schema + wire contract
  3. docs/embedding.md — how a consumer integrates
  4. docs/architecture.md — implementation shape
  5. docs/operations.md — running it
  6. docs/roadmap.md — what's in each version

LLM agents: start with AGENTS.md.

Status

v0.x — pre-stable, pre-implementation. This repo currently holds only its kickoff documents. Contracts may break between minor versions until v1.0.

License

Dual MIT / Apache-2.0.

Directories

Path Synopsis
cmd
wavefront command
Command wavefront is the edge contract-mediation proxy: it maps a versioned external contract onto a single evolving internal HTTP/JSON backend.
Command wavefront is the edge contract-mediation proxy: it maps a versioned external contract onto a single evolving internal HTTP/JSON backend.
wavefront-bundlegen command
Command wavefront-bundlegen scrapes a consumer's OpenAPI document and emits the read-only wavefront bundle (descriptors.binpb + openapi.json + versions.yaml).
Command wavefront-bundlegen scrapes a consumer's OpenAPI document and emits the read-only wavefront bundle (descriptors.binpb + openapi.json + versions.yaml).
internal
adapter
Package adapter is the codec boundary.
Package adapter is the codec boundary.
bundle
Package bundle loads and validates the read-only descriptor bundle (descriptors.binpb + openapi.json + versions.yaml) at boot, fail-fast.
Package bundle loads and validates the read-only descriptor bundle (descriptors.binpb + openapi.json + versions.yaml) at boot, fail-fast.
bundlegen
Package bundlegen is the OpenAPI → bundle generator.
Package bundlegen is the OpenAPI → bundle generator.
bundletest
Package bundletest is shared test scaffolding: it builds a self-contained FileDescriptorSet and writes a valid on-disk bundle so negotiate/server/e2e can exercise the real bundle.Load path without protoc.
Package bundletest is shared test scaffolding: it builds a self-contained FileDescriptorSet and writes a valid on-disk bundle so negotiate/server/e2e can exercise the real bundle.Load path without protoc.
config
Package config parses the WAVEFRONT_* environment once at startup into an immutable Config.
Package config parses the WAVEFRONT_* environment once at startup into an immutable Config.
negotiate
Package negotiate resolves the contract the client declared.
Package negotiate resolves the contract the client declared.
server
Package server is the proxy core: a data-plane listener that runs the negotiate → decode → one upstream call → encode pipeline, and an ops listener for /metrics, /health, /ready.
Package server is the proxy core: a data-plane listener that runs the negotiate → decode → one upstream call → encode pipeline, and an ops listener for /metrics, /health, /ready.
wireerror
Package wireerror is the v0.1 error contract: the typed, wavefront-originated failures returned to a client as a proper HTTP status + standard headers + the `X-Wavefront-Error` code + a fixed `wavefront.v1.Error` protobuf body.
Package wireerror is the v0.1 error contract: the typed, wavefront-originated failures returned to a client as a proper HTTP status + standard headers + the `X-Wavefront-Error` code + a fixed `wavefront.v1.Error` protobuf body.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL