fluid-core/docs/adr/0003-wire-contract-as-boundary.md
tegwick 76912adef8
Some checks failed
ci / build (push) Failing after 1m6s
Generate contract types, pin fixtures to spec, add build and ADRs
Completes FLUID-WP-0002. The record types in internal/contract are
generated from schemas/ by a dependency-free generator; fixtures
transcribed from the spec's worked examples validate against those
schemas and round-trip through the generated types with
DisallowUnknownFields, so a spec change that misses the schemas fails
CI rather than drifting silently.

Adds identifier prefix helpers, Makefile, GitHub Actions, and five ADRs
recording the Go choice, out-of-process attachment, the wire contract as
boundary, the evidence store, and revision identity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014KmVxhJ35tCo7rE7UnLwWu

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1116572@bnt-lap001
Assistant-Session: 8ba9bb93-a72a-4883-b189-2499cce5c400
2026-09-04 02:03:12 +02:00

1.6 KiB

ADR-0003 — The wire contract is the boundary

Status: accepted · Date: 2026-09-04

Context

ADR-0002 puts fluid-core in a separate process from everything it serves. Something has to define how those processes agree.

Decision

The boundary is a set of on-the-wire artifacts, not a Go API:

  1. the revision descriptor (Blueprint §36);
  2. the routing policy (Blueprint §17);
  3. the telemetry envelope;
  4. the control APIs (Blueprint §44).

These live in schemas/ as JSON Schema. Go types in internal/contract are generated from those schemas and are never hand-written.

Rationale

Field names and semantics are the interop surface — the schema specification says so directly in its §1. Generating from the schema means the specification cannot drift from the implementation without failing the build.

It also makes the Go choice reversible where it matters. A future high-throughput gateway in another language, a Python Daimon, a TypeScript adapter: none of them need anything from this repository except the schemas.

Enforcement

  • make check-generated fails CI when internal/contract is stale.
  • conformance/validate_schemas.py validates fixtures transcribed from the spec's own worked examples, so a spec change that the schemas miss fails too.
  • The Go round-trip test decodes those fixtures with DisallowUnknownFields, catching any field the generated types have no home for.

Consequence

Any change that would leak a Go type across this boundary is a design failure, not a convenience. If a consumer needs something, it goes in a schema first.