API stability, versioning, deprecation & sunset
This page is the stability contract for everything that programs against the
control plane. It states what is stable, how breaking change is signalled, and
how long a deprecated surface keeps working. The enforcement is in the
codebase, not in prose: the deprecation table, the response headers, the
OpenAPI markers and the window checks below are all driven from a single
in-code declaration (core/api/stability.go), and a sunset scheduled earlier
than the policy allows fails the build.
Covered surfaces and tiers
Section titled “Covered surfaces and tiers”| Surface | Versioned by | Tier today |
|---|---|---|
| REST core contract — the paths in the served OpenAPI document | URL major (/v1/…) | stable |
gRPC mirror — ControlPlane in proto package olivares.api.v1 | proto package major | stable (frozen mirror) |
Live-ingest / connector wire — proto package olivares.sdk.v1 | proto package major + plugin ProtocolVersion | stable (frozen) |
Connector SDK (Go) — modules sdk, sdk/plugin (author surface) | module semver — tags sdk/v*, sdk/plugin/v* from the first public release | stable v1 (Go contract; wire row above) |
Event bus contract (AsyncAPI 3.0) — its event types are also what the eventing platform delivers to external webhook subscriptions; the subscription-management routes are module routes (/v1/m/eventing/, in the beta document below), but each event type carries its own stability tier from the in-code catalog | info.version (1.0.0-preview) | beta (document); per-type tiers for event types |
Module routes — /v1/m/<ns>/…, the product’s modules, in the beta module-route document | URL major (/v1/); reflected from the routes the modules register | beta |
| Terraform provider | its own semver (terraform-provider-v* tags) | stable, MAJOR tracks API v1 |
| Client SDKs (Go / Java / Python / TypeScript) | their own semver; MAJOR tracks the API major from GA | beta (pre-1.0 packages) |
| Anything not listed — SCIM, federation, internals | — | out of contract |
Tiers. A stable surface does not change incompatibly within its major
version; removing or changing it requires the deprecation process below. A
beta surface may still change shape, but gets the same signalling and a
shorter window — the module routes (/v1/m/<ns>/…) are published as a separate
beta document, kept distinct from the stable core
contract so the stable surface stays identifiable. An out-of-contract surface
(SCIM, federation, internals) carries no compatibility promise; its contracts
live in the typed interfaces that ship with the product.
Every operation in both OpenAPI documents carries a machine-readable
x-stability marker — stable in the core contract, beta
in the module-route document — and each document links
this page in info.x-stability-policy.
What counts as a breaking change
Section titled “What counts as a breaking change”For a stable surface, all of these are breaking and gated on the process below:
- removing or renaming a path, method, request field, response field or error
code; - changing a field’s type or meaning, or making an optional request field required;
- tightening authentication/authorization such that a previously valid call fails;
- for gRPC/protobuf: anything
buf breaking(FILE ruleset) rejects.
These are not breaking: adding endpoints, adding optional request parameters, adding response fields, adding new error codes for new failure modes, and adding response headers. Clients must tolerate unknown JSON fields.
Versioning
Section titled “Versioning”- REST is versioned in the URL: the entire stable contract lives under
/v1/. An incompatible change ships under/v2/and/v1/enters deprecation — never an in-place break. - gRPC is versioned by proto package:
olivares.api.v1/olivares.sdk.v1. An incompatible change requires a new package major (…v2); both contracts are guarded bybuf breakingagainstmain(task proto:breaking). - The Terraform provider is released independently
(
terraform-provider-v*tags); its MAJOR tracks the API major it speaks. - Client SDKs embed
API_VERSION(the contract major they were generated from) andSPEC_HASH(the exact OpenAPI snapshot) —APIVersionandSpecHashin Go; from GA their MAJOR tracks the API major. - The connector SDK (the Go contract third-party connectors build
against) is versioned by per-module semver tags (
sdk/vX.Y.Z,sdk/plugin/vX.Y.Z) and gated by the samebuf breakingwall on its wire. Interfaces an author implements never gain methods within a major; new capability arrives as new optional interfaces. The full policy ships with the module (sdk/VERSIONING.md); the authoring lifecycle is in Build and ship a connector.
Deprecation process and signalling
Section titled “Deprecation process and signalling”A deprecation is one declared entry in the in-code table plus a migration guide; everything else follows from it mechanically.
-
Announce. The entry lands with its announcement date and the migration guide URL. From that moment every response of the deprecated route carries the RFC 9745 header and a link to the guide, and the OpenAPI operation gains
deprecated: true,x-deprecated-atandx-migration-guide:Deprecation: @1780272000Link: <https://olivares.ai/docs/how-to/migrate-example/>; rel="deprecation" -
Schedule the sunset. When the retirement date is committed, responses add the RFC 8594 header (and the spec gains
x-sunset-at):Sunset: Thu, 01 Jun 2028 00:00:00 GMTLink: <https://olivares.ai/docs/how-to/migrate-example/>; rel="sunset" -
Remove — at the earliest on the sunset date, normally with the next API major.
Minimum support windows (deprecation announcement → sunset):
| Tier | Minimum window |
|---|---|
| stable | 24 months |
| beta | 12 months |
These windows are enforced by tests against the declaration table: an entry whose sunset violates its tier’s window, or that points at a route that does not exist, does not build.
For gRPC, deprecation is expressed with the protobuf deprecated option
(which surfaces in generated code) plus the same windows; the wire contracts
are otherwise frozen and buf breaking rejects incompatible edits outright.
What clients see
Section titled “What clients see”- Terraform provider — emits a
tflogWARN (method, endpoint, dates, guide) once per unique method and request path per run when a control-plane response carries a deprecation signal (a deprecated parameterized route warns once per resource it touches), and sends a versionedUser-Agentso deprecated-client usage is attributable server-side. - Go SDK — surfaces a
DeprecationNoticeonce per endpoint (default: anslogwarning; override withWithDeprecationHandler). Deprecated operations carry Go// Deprecated:markers, so editors andstaticcheckflag them at development time. - Python SDK — one
DeprecationWarningper endpoint (or youron_deprecationcallback); deprecated operations are marked in docstrings. - TypeScript SDK — one
console.warnper endpoint (or youronDeprecationcallback); deprecated operations carry@deprecatedJSDoc.
Related
Section titled “Related”- REST API reference — the stable contract itself
- Using the client SDKs
- Build and ship a connector — the connector SDK contract and lifecycle
- Manage as code (Terraform)
- Module XIX — own API + manage-as-code
- Event bus (AsyncAPI 3.0)
- Honesty and limits