API contract and version governance
The question from the review: Allvue deploys version 1, other systems integrate with its APIs, and cortex later changes the application. Can behaviour change without breaking the API contract? Can cortex be told "maintain /v1/..., no breaking schema or endpoint changes" and be held to it?
The short answer
Yes, as requirement-linked tests that gate every promotion: a contract is written down as a requirement of kind constraint, its tests call the API and assert status, shape and values, every suite runs every fifteen minutes, after every deploy and before a project copy is pushed to another environment, and a red suite refuses the push. What is not built is a schema-level gate: an OpenAPI diff, semantic API versioning, or automatic generation of contract tests from a schema. Partial
What exists
| Mechanism | What it does | Standing |
|---|---|---|
| A contract as a requirement | "Maintain the /v1 contract; do not introduce breaking schema or endpoint changes" is a requirement of kind constraint, cited to the document that asked for it. Constraints are pinned; a review never regenerates them, and the fleet sees them on every card for the project. |
Available |
| Contract tests | Tests of kind http and endpoint linked to that requirement: call the API on a named target, assert on $.status, on paths in the body ($.body.items[0].id), on counts and types. A spec names a target, never a host, so the same test runs on the platform, in the customer archive and in Allvue's environment. |
Available |
| The watchdog | Every project's suite runs every fifteen minutes, once after boot and after every deploy; a transition (green to red, a different failing set) files an alert and posts to Slack. | Available |
| The promotion gate | A project copy moving between environments ends with the test gate; a red suite refuses the push. | Available |
| Change on a branch | Every branch of a project's configuration has its own engine fork. A change is made on a branch, the structure check and the tests run there, and the branch is merged when green. | Available |
| Version history and rollback | Every endpoint save is a version with diff and restore; every export is a commit; the runbook's rollback section is two layers, the previous image tag and per-consumer flags in the project's data. | Available |
| The fleet's own verification | A card is not complete until the tests of the requirements it touched pass; the fleet authors tests for the requirements it made true and runs the whole suite before it hands back. | Available |
What "hold cortex to it" looks like in practice
- Allvue's integration guide for the API is uploaded as a requirement source. The rows it yields include the contract as a constraint.
- The contract's tests are written once, against version 1 as deployed: one
httptest per operation with the response shape asserted. - A change request arrives ("show the new fee column"). The fleet builds it on a branch. Its self-check runs every test of the project; a contract test that turns red is a failed card, visible on the Board with the failing assertion.
- A change that cannot be made without breaking the contract is filed back as a decision for a person: add
/v2, or renegotiate. The fleet does not decide that.
A contract test, as it is stored
{
"key": "api-v1-positions-shape",
"kind": "http",
"requirement": "feat-api-v1-contract",
"spec": {
"target": "service:allvue-dq",
"path": "/api/v1/positions?limit=1",
"expect": [
{ "path": "$.status", "op": "eq", "value": 200 },
{ "path": "$.body.items[0].id", "op": "type", "value": "string" },
{ "path": "$.body.items[0].fee_bps", "op": "type", "value": "number" }
]
}
}
What is not in place, and what we propose
| Gap | Today | Proposal |
|---|---|---|
| A schema-level breaking-change gate | Not built Contracts are enforced by tests a person or the fleet writes. | A test kind contract: the spec names an OpenAPI document (committed with the service) and the runner fails on a breaking diff against the last published version (removed path, removed or retyped field, narrowed enum). The runner already ships with every archive, so the gate travels with the delivery. |
| Semantic API versioning | Not built Versioning is the application's own convention (/v1, /v2). |
Record the API version on the service's declaration row and have the contract test kind refuse a breaking diff unless the major version was bumped. |
| Contract tests generated from a schema | Not built Tests are authored per operation. | Generate the per-operation http tests from the OpenAPI document on the "Write tests" action, so version 1 gets its contract pack in one step. |
| An OpenAPI document for generated services | Partial The platform's own API has an interactive reference; a generated app service documents its API only if a requirement asks. | Make an OpenAPI document part of the Allvue profile (see Security and identity), so every generated API ships with one. |