apicontract

package
v1.0.173 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package apicontract is the durable enforcement core of the Culvert OpenAPI program. It is deliberately decoupled from package main: it operates on a plain []Route slice (supplied by the caller) plus two on-disk artifacts — the OpenAPI contract and the route-classification manifest — so its logic is unit-testable in isolation with fixtures and reused by the live-router gate in package main.

The three enforcement surfaces:

LoadSpec      — parse + validate the OpenAPI document (Gate 1).
StyleLint     — organizational lint rules over the contract (Gate 2).
CheckCoverage — bijective route⇄manifest⇄spec coverage (Gate 3).
CheckExemptions — no expired route exemption survives (Gate 3, time axis).

Everything is offline and Go-native (getkin/kin-openapi); no network, no Node, no external binary — it runs inside `go test`.

Index

Constants

View Source
const MaxExemptionHorizonDays = 270

MaxExemptionHorizonDays caps how far in the future an exemption may be set, so a route cannot dodge documentation indefinitely by pinning a far-future date.

Variables

This section is empty.

Functions

func BundleJSON

func BundleJSON(specPath string) ([]byte, error)

BundleJSON converts the YAML contract to canonical, deterministic JSON.

Determinism is load-bearing (Gate 8): the YAML is decoded into a generic map and re-encoded with encoding/json, which sorts object keys lexicographically, so the same input always yields byte-identical output regardless of authoring order. No external tool, no network — pure Go, air-gap safe.

func CheckCoverage

func CheckCoverage(routes []Route, spec *Spec, c *Classification) []string

CheckCoverage enforces the bijection route ⇄ manifest and the coverage manifest ⇄ spec. It returns a sorted list of human-readable violations (empty == pass).

  1. every live route+method has exactly one manifest row (no unclassified route)
  2. every manifest row maps to a live route+method (no stale row)
  3. every documented row appears as a spec operation
  4. every spec operation maps to a documented row (no phantom operation)
  5. row/exemption/documented consistency

The time axis (expired exemptions) is CheckExemptions.

func CheckExemptions

func CheckExemptions(c *Classification, now time.Time) []string

CheckExemptions fails when any exemption has expired OR is set beyond the maximum horizon relative to `now` (Gate 3, time axis). Expiry is YYYY-MM-DD and the route stays valid THROUGH the expiry date (the +24h makes the date inclusive); it fails the day after.

func Ext

func Ext(op *openapi3.Operation, key string) string

Ext reads a string vendor-extension value from an operation.

func RenderDocsHTML

func RenderDocsHTML(specPath string, allowedVis ...string) ([]byte, error)

RenderDocsHTML renders the offline, self-contained HTML documentation for the contract at specPath. When allowedVis is non-empty, only operations whose x-culvert-visibility is in that set are included (the public build filter).

func RenderInventory added in v1.0.142

func RenderInventory(manifestPath string) ([]byte, error)

RenderInventory produces the deterministic API-inventory markdown from the classification manifest. Totals and per-domain counts are computed from the manifest rows; nothing is hand-entered.

func StyleLint

func StyleLint(spec *Spec) []string

StyleLint enforces the organizational API style rules over the contract (Gate 2). Returns a sorted list of violations (empty == pass).

Types

type ClassRow

type ClassRow struct {
	Route         string     `yaml:"route"`
	Method        string     `yaml:"method"`
	Handler       string     `yaml:"handler"`
	Domain        string     `yaml:"domain"`
	Visibility    string     `yaml:"visibility"`
	MinRole       string     `yaml:"min_role"`
	Mutating      bool       `yaml:"mutating"`
	AuditExpected bool       `yaml:"audit_expected"`
	DangerLevel   string     `yaml:"danger_level"`
	Documented    bool       `yaml:"documented"`
	OpenAPIPath   string     `yaml:"openapi_path"` // optional; defaults to Route
	Exemption     *Exemption `yaml:"exemption"`
}

ClassRow is one classification manifest entry.

func (ClassRow) SpecPath

func (r ClassRow) SpecPath() string

SpecPath is the exported path this row matches against the contract.

type Classification

type Classification struct {
	Version                 int        `yaml:"version"`
	BaselineExemptionExpiry string     `yaml:"baseline_exemption_expiry"`
	Rows                    []ClassRow `yaml:"routes"`
}

Classification is the parsed route-classification manifest.

func LoadClassification

func LoadClassification(path string) (*Classification, error)

LoadClassification parses the manifest (goccy/go-yaml resolves the YAML anchor used for the shared baseline expiry).

type Exemption

type Exemption struct {
	Owner         string `yaml:"owner"`
	Reason        string `yaml:"reason"`
	SecurityClass string `yaml:"security_class"`
	Expires       string `yaml:"expires"`
}

Exemption records why a route is not (yet) in the contract.

type Operation

type Operation struct {
	Path   string
	Method string
	Op     *openapi3.Operation
}

Operation is one spec operation (path × method).

type Route

type Route struct {
	Path    string
	Method  string // "GET" | "POST" | ... | "*" (MethodAny)
	Handler string
	Domain  string
	Public  bool
	MinRole string
	Muta    bool
	Audit   bool
}

Route is a single registered admin-API route+method, as known to the live router. package main adapts its uiRoutes table into this shape.

type Spec

type Spec struct {
	Doc  *openapi3.T
	Ops  []Operation
	Path string
}

Spec wraps a validated OpenAPI document.

func LoadSpec

func LoadSpec(path string) (*Spec, error)

LoadSpec loads and validates the OpenAPI document (Gate 1: syntax, $ref resolution, schema correctness, duplicate operationId, security-scheme refs).

func (*Spec) FindOp

func (s *Spec) FindOp(method, path string) *openapi3.Operation

FindOp returns the operation for a concrete method+path, or nil.

func (*Spec) OpForRow

func (s *Spec) OpForRow(r ClassRow) *openapi3.Operation

OpForRow returns the operation documenting this manifest row, or nil.

func (*Spec) ValidateJSONRequest

func (s *Spec) ValidateJSONRequest(method, path string, body []byte) error

ValidateJSONRequest validates a request body against the operation's application/json request schema (Gate 4).

func (*Spec) ValidateJSONResponse

func (s *Spec) ValidateJSONResponse(method, path string, status int, body []byte) error

ValidateJSONResponse validates a real handler's JSON response body against the operation's response schema for `status` (Gate 5). A missing operation or status is a hard error — the contract must describe what the handler returns.

Jump to

Keyboard shortcuts

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