Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
sdk-generator-smoke / sdk-smoke (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
48 lines
3.3 KiB
Markdown
48 lines
3.3 KiB
Markdown
# API Versioning
|
|
|
|
Last updated: 2025-11-25 (Docs Tasks Md.V)
|
|
|
|
## Principles
|
|
- **Semantic versioning**: OpenAPI artifacts follow `MAJOR.MINOR.PATCH` where breaking changes bump MAJOR, additive changes bump MINOR, fixes/docs bump PATCH.
|
|
- **Long-lived compatibility**: At least N-1 major versions remain runnable for 12 months; minor versions remain compatible for 6 months after release unless a security fix requires earlier removal.
|
|
- **Explicit deprecations**: Every breaking removal/change is preceded by a deprecation window with headers and changelog entries.
|
|
- **Deterministic specs**: Generated `out/api/*.yaml` are reproducible from a pinned manifest and committed checksums.
|
|
|
|
## How versions are expressed
|
|
- **Base URL**: `/api/v{major}/...` (e.g., `/api/v1/policy`). Major only; minor/patch controlled via headers.
|
|
- **Headers**:
|
|
- `X-Stella-Api-Version: <major.minor.patch>` → client-requested minor/patch; server chooses the highest compatible available ≤ requested. If omitted, server serves the latest compatible minor/patch for that major.
|
|
- `Deprecation: true` + `Sunset: <rfc7231-date>` returned when an endpoint or field is scheduled for removal.
|
|
- `X-Stella-Api-Deprecated-Fields: field1,field2` lists soon-to-be-removed members for the response.
|
|
- **Error codes**:
|
|
- `error.code = API_VERSION_UNSUPPORTED` when requested major is not served.
|
|
- `error.code = API_VERSION_TOO_OLD` when requested minor/patch is below the minimum supported for the major.
|
|
|
|
## Compatibility rules
|
|
- Additive changes (new fields/enums/paths) are allowed within the same major; fields default to `null`/empty and must not change meaning.
|
|
- Breaking changes require a new major: field removals/renames, required field additions, behavior changes that alter contracts.
|
|
- Enum extensions: existing values remain; new values must be tolerated by clients.
|
|
- Pagination/order: sort keys and determinism must be preserved across versions.
|
|
|
|
## Release & lifecycle
|
|
1) Draft OpenAPI in `src/Api/StellaOps.Api.OpenApi` and update `out/api/stella.yaml`.
|
|
2) Run `pnpm api:lint` + `pnpm api:compat --baseline stella-baseline.yaml` to ensure no unintended breaks.
|
|
3) Publish changelog entry under `out/api/changelog/<yyyyMMdd>-<version>.md` with checksums/signature.
|
|
4) Announce deprecations via release notes; include `Deprecation`/`Sunset` headers in affected endpoints for at least 60 days before removal.
|
|
5) Sunset execution: remove endpoints/fields only after the sunset date and after the major bump ships.
|
|
|
|
## Client guidance
|
|
- Always send `X-Stella-Api-Version` to lock to a tested minor/patch; pin SDK versions accordingly.
|
|
- Handle `Deprecation`/`Sunset` headers by warning users and planning upgrades.
|
|
- Prefer server-provided pagination tokens; avoid relying on incidental field order.
|
|
|
|
## Testing
|
|
- Contract tests must cover the lowest and highest supported minor/patch for each major.
|
|
- Deterministic fixtures for each version live under `tests/fixtures/api/versioning/`; CI runs `pnpm api:compat` against these fixtures.
|
|
- Compatibility diff (`pnpm api:compat old.yaml new.yaml`) now flags:
|
|
- Added/removed operations and responses
|
|
- Parameter additions/removals/requiredness flips
|
|
- Request body additions/removals/requiredness and content-type changes
|
|
- Response content-type additions/removals
|
|
Use `--fail-on-breaking` in CI to block removals/requiredness increases.
|