API Versioning

How Stella Ops versions its OpenAPI contracts and SDKs, declares deprecations, and keeps specs deterministic and reproducible. This page is for API consumers planning upgrades and for maintainers evolving the contracts; for the wider contract/SDK programme see SDK & OpenAPI Program, and for shared request conventions see the API Overview.

Last updated: 2026-05-30 (deep doc↔code reconciliation against src/Api/StellaOps.Api.OpenApi)

Implementation status. Parts of this page describe a target design that is not yet wired up in the repository. Where a mechanism is aspirational it is marked (PROPOSED — not implemented) so consumers do not depend on it. The composer (compose.mjs) is real and runs; the lint/compat/changelog scripts referenced from package.json (api:lint, api:examples, api:compat, api:compat:test, api:changelog) currently point at scripts/api-*.mjs files that are not present in the tree, and the driving CI workflows live under .gitea/workflows-archived/. Treat those steps as the intended pipeline rather than a guaranteed-green build until the scripts are restored.

Principles

How versions are expressed

Deprecations

Deprecation is declared per-operation in the per-service OpenAPI files and enforced by Spectral rules (.spectral.yaml at the repo root):

Compatibility rules

Release & lifecycle

  1. Edit the per-service spec under src/Api/StellaOps.Api.OpenApi/<service>/openapi.yaml, then regenerate the aggregate: npm run api:compose (which runs node src/Api/StellaOps.Api.OpenApi/compose.mjs and overwrites src/Api/StellaOps.Api.OpenApi/stella.yaml).
  2. Run lint + compatibility checks (all via npm run, not pnpm):
    • npm run api:lint — Spectral lint of src/Api/StellaOps.Api.OpenApi/**/*.yaml (rules in root .spectral.yaml).
    • npm run api:examples — example coverage check.
    • npm run api:compat — runs node scripts/api-compat-diff.mjs. The CI invocation is positional: node scripts/api-compat-diff.mjs <old.yaml> <new.yaml> --output text [--fail-on-breaking]. CI compares against the previous commit’s stella.yaml and against the baseline at src/Api/StellaOps.Api.OpenApi/baselines/stella-baseline.yaml. (There is no --baseline <file> flag; the baseline is passed as the <old.yaml> positional argument.)
    • npm run api:changelog — regenerates src/Api/StellaOps.Api.OpenApi/CHANGELOG.md (sections: Additive Operations, Breaking Operations).

    Status: the scripts/api-*.mjs helpers are not present in the repository (the whole scripts/ directory is absent); only compose.mjs is committed. Because the api:examples/api:compat/api:compat:test/api:changelog npm aliases could therefore only fail, they were removed from package.json in SPRINT_20260712_005 (DEAD-3); api:lint and api:compose remain and work. Restoring this step means writing the helper scripts and re-adding the npm aliases.

  3. Changelog lives in-tree at src/Api/StellaOps.Api.OpenApi/CHANGELOG.md. (PROPOSED — not implemented): a per-release out/api/changelog/<yyyyMMdd>-<version>.md with embedded checksum/signature is design intent and does not exist; there is no out/api/ directory.
  4. Announce deprecations via release notes and the x-deprecation metadata above; standard Deprecation/Sunset headers should accompany affected endpoints for the configured deprecation window before removal.
  5. SDK freeze: tag the commit api/v{version} (e.g. api/v0.1.0-alpha), compute and commit the SHA256 of stella.yaml (sha256sum stella.yaml > stella.yaml.sha256), and have SDK generators validate it via STELLA_OAS_EXPECTED_SHA256. See the API governance baseline.
  6. Sunset execution: remove endpoints/fields only after the sunset date and after the major bump ships.

Client guidance

Testing