# C19: OpenAPI for the admin API, and a Terraform provider ## CHANGELOG ### The admin API described, and a Terraform provider - **The admin API in OpenAPI 3.1.** Every endpoint under `/api/v1`, its path and query parameters, and the schema of each request and answer with the meaning of each field, in [docs/admin-api.openapi.json](docs/admin-api.openapi.json) and served by every control plane at `GET /api/v1/openapi.json` (with the token, like the rest). The bearer token, the `X-Llmgw-Actor` header and the error shape are in it. Generated by `go generate ./internal/docgen` from a route table in `internal/control/adminapi/routes.go` and the Go types the handlers use, with the fields' comments as descriptions; a test fails when an endpoint is served and not in the table, another when the committed document is stale. Checked with openapi-spec-validator and openapi-generator-cli's validate. - **[docs/admin-api.md](docs/admin-api.md)**: how to reach the API (loopback, an SSH tunnel, `admin_remote`), the token at `/var/lib/llmgw/admin-token`, what a request must carry — an address in `Host`, `application/json` on every change, even a `DELETE` — and some calls with `curl`. - **`GET /api/v1/models/{name}`**: one model's whole definition as it is in force, with the defaults the catalog filled in. The listing has only its state and its profiles' names. - **A Terraform provider**, in `terraform-provider-llmgw/`, a module of its own so the gateway does not carry its dependencies. `llmgw_model` (a model added at runtime: scaling, class, owner and adapters change in place, the rest replaces it), `llmgw_quota`, `llmgw_guard_attachment`, and the `llmgw_models` and `llmgw_nodes` data sources. Its client is checked against the OpenAPI document, endpoint by endpoint and field by field, so a change to the admin API that breaks it fails its tests; CI runs them. Built and installed by hand for now: see its [README](terraform-provider-llmgw/README.md). ## BACKLOG **Done (branch `features-c2`):** `adminapi.Routes` and `internal/docgen/openapi` generating `docs/admin-api.openapi.json` (3.1, bearer security, every route, query parameters, schemas from the Go types with their comments), served embedded at `GET /api/v1/openapi.json`, kept true by a route-table test and a staleness test; validated with openapi-spec-validator and openapi-generator-cli. `GET /api/v1/models/{name}`. `docs/admin-api.md`. `terraform-provider-llmgw/` (terraform-plugin-framework): `llmgw_model`, `llmgw_quota`, `llmgw_guard_attachment`, data sources `llmgw_models` and `llmgw_nodes`; client tests against a fake admin API and the OpenAPI document; acceptance tests with Terraform and OpenTofu against the fake; one apply, empty plan, in-place change and destroy against a real `llmgw server` run by hand. Left: organizations, teams, projects, people and keys are not in the admin API (they are `llmgw org`/`users`/`keys` against the store), so not in the provider; a model's definition beyond scaling, class, owner and adapters is changed by replacing it (the API has no edit, and `resources` is not used yet); `canary`, `slo`, `scaling.schedule` and `prewarm`, `guard` role and `origin` are not in `llmgw_model`; models cannot be imported; the provider is not published to a registry and has no release build; the acceptance tests are not run in CI (they need Terraform); the document's schemas mark nothing required and give no enums; `catalog.SLO`'s fields have no JSON tags, so they are `TTFTp99` and `TPOTp99` on the wire.