Skip to main content
Version: 1.1.0

API versioning

The KubeAtlas HTTP API ships under two prefixes that are served by the same handlers:

PrefixStatusNotes
/api/v1alpha1/*Frozen surfacePhase 1 shape; no field will be removed or renamed.
/api/v1/*GAPhase 2 superset; adds graph-analysis enrichment fields on ResourceDetailResponse.

Both prefixes hit the same store query path. The only difference is serialisation — /api/v1/... returns a ResourceDetailResponseV1 that carries blastRadiusCount, isOrphan, and inCycle fields on top of the v1alpha1 shape; /api/v1alpha1/... returns the original three-field bundle.

What "frozen" means

The CI job api-compat-check compares the build's emitted v1alpha1 spec against api/openapi-v1alpha1.json (the v0.1.0 baseline) on every PR. The job fails when any of the following changes:

  • A path is removed.
  • A method is removed from an existing path.
  • A schema is removed.
  • A property is removed from an existing schema.
  • A property's type changes.
  • A previously-required field becomes optional.
  • A previously-optional field becomes required.

Additions are always fine: a new endpoint, a new optional field, a new schema. The intent is that v0.1.0-era curl + jq scripts never break across the v0.x → v1.x → v2.x trajectory of the project.

Adding a new endpoint

The route table in pkg/api/routes.go is the single source of truth. Add the entry under v1alpha1 form (the canonical pattern is /api/v1alpha1/<path>); the server registers each route at the matching /api/v1/<path> automatically. The same handler powers both versions.

After adding the endpoint, regenerate the baseline so the new schema lands in api/openapi-v1alpha1.json:

go run ./tools/api-compat-check/dump > api/openapi-v1alpha1.json

Commit the regenerated file alongside the route addition.

Adding a v1-only field

For fields the v1alpha1 surface should not see (typically graph-analysis enrichments that pre-Phase-2 clients didn't ask for), declare them on a sibling DTO type — see ResourceDetailResponseV1 in pkg/api/handlers.go. The handler branches on apiVersionFor(r) and serializes the version- appropriate type. The OpenAPI spec for v1 picks up the sibling schema automatically through openAPIComponentsFor.

Do NOT add v1-only fields to existing v1alpha1 DTOs. The shared JSON shape between the two versions is part of the "v1alpha1 → v1 is a no-touch upgrade" promise.

Deprecation timeline

The eventual retirement story for v1alpha1:

Releasev1alpha1 status
v1.0.xFully supported, served alongside v1.
v1.1.xDeprecation: true response header on every v1alpha1 response (no functional change).
v2.0.xRemoved. The migration window from Deprecation: true to removal is at least one minor release line.

Practical consequences:

  • Scripts and dashboards that pin /api/v1alpha1/... keep working through every v1.x release.
  • A user upgrading directly from v0.1.0 to v2.0 has at least one minor-line warning window; check the Deprecation header in CI logs and migrate.
  • If your tool can drift to /api/v1/... early, do — the enrichment fields are useful and the schema is a strict superset.

Why two prefixes instead of one with a content-type negotiation

Path-based versioning beats Accept headers in practice for operator tooling: every shell pipeline (curl, jq, kubectl exec, wget) understands paths; not all of them honour content-type negotiation cleanly. The path also makes it trivial to grep for "what version is this script using" — search for the prefix.