- seeds/ontology.yaml: 59 entity types (5 abstract, is-a hierarchy), 46 relationship types with cardinality, 6 lifecycles with terminal states and named precondition checks - seeds/inventory.yaml: 110 entities / 142 relationships translated from legacy inventory.yaml (fleet, services, ingress, storage, governance, archaeology); thin spots marked for backfill - seeds/policy.yaml: 4 risk classes, 27 approval rules (hierarchy-aware, per-entity overrides), autonomy kill-switch off (cold start) - api/openapi.yaml: full v1 REST contract (40 paths), RFC 9457 errors, cursor pagination, idempotency, ETag/If-Match, scopes; redocly-clean - docs/adr/0001-0010: initial architecture decision records - scripts/validate-seeds.py: Phase 0 gate — hierarchy, lifecycles, endpoints, cardinality, policy cross-refs (0 errors) - plan: layer CHECK gains 'meta' (root type), cardinality gains 'many-to-one' Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
22 lines
941 B
Markdown
22 lines
941 B
Markdown
# ADR 0004 — Contract-first OpenAPI API
|
|
|
|
Status: accepted (2026-07-07) · Plan: rev 3, R3-2/R3-3
|
|
|
|
## Context
|
|
Future UIs, a CLI client, and an MCP surface must stay in sync with the
|
|
API. Code-first (Gin + generated docs) drifts.
|
|
|
|
## Decision
|
|
api/openapi.yaml (OpenAPI 3.1) is the source of truth. Server stubs via
|
|
oapi-codegen (strict server, chi router); clients generated for Go (CLI)
|
|
and TypeScript (future UI). Conventions: RFC 9457 problem+json errors,
|
|
{items, next_cursor} envelopes, cursor pagination, Idempotency-Key on
|
|
unsafe POSTs, ETag/If-Match optimistic concurrency, scopes
|
|
(operator/viewer/agent) annotated per operation. CI fails on spec/handler
|
|
drift. MCP tools wrap the same service layer.
|
|
|
|
## Consequences
|
|
- UI development needs only the running API (spec served at /openapi.yaml).
|
|
- Handler changes require spec changes first — deliberate friction.
|
|
- Breaking changes ship as /api/v2 side by side; v1 is additive-only.
|