Versioning & Deprecation Policy
This document is the authoritative reference for all versioning and deprecation contracts in Platform-Kernel. It covers:
- REST API version strategy (
/v1/,/v2/). - Module and SDK Semver rules.
- Deprecation lifecycle with RFC 9457 sunset errors.
- Protobuf schema backward-compatibility enforcement (
buf breaking). - Primitive Freeze definition and checklist.
REST API Versioning
Strategy: URL Path
All REST API endpoints are versioned via the URL path:
https://api.septemcore.com/api/v1/<resource>
https://api.septemcore.com/api/v2/<resource>
- URL path versioning is mandatory (CONVENTIONS.md §6).
- Header-based versioning (
Accept-Version,API-Version) is prohibited. - Query-parameter versioning (
?version=2) is prohibited. - A version bump from
v1tov2happens only when a breaking change cannot be avoided.
What Counts as a Breaking Change
| Change | Breaking? |
|---|---|
| Add a new optional response field | No |
| Add a new optional request field | No |
| Add a new endpoint | No |
| Remove an existing field from a response | Yes |
| Rename an existing field | Yes |
| Change a field type | Yes |
| Add a required request field | Yes |
| Change a 200 to a 4xx | Yes |
| Remove an endpoint | Yes |
Non-breaking changes may be deployed to v1 at any time without notice.
Breaking changes require the full deprecation lifecycle described below.
Deprecation Lifecycle
When a breaking change is unavoidable, the old version follows a structured two-phase process (CONVENTIONS.md §6.1):
Phase 1 — Deprecation Notice
- The new version (
/api/v2/) is launched. - Every response from the old version (
/api/v1/) gains two headers:
Deprecation: true
Sunset: 2026-12-01T00:00:00Z
Sunset carries an ISO 8601 UTC timestamp — the exact date after
which the old version stops responding.
- An Event Bus notification is published to all active tenants:
{
"type": "platform.api.deprecated",
"targetVersion": "v2",
"sunsetDate": "2026-12-01T00:00:00Z",
"affectedEndpoints": ["/api/v1/users", "/api/v1/auth/login"]
}
- The Admin Dashboard shows a list of modules that are still calling deprecated endpoints, so Platform Owners can contact affected module developers.
Phase 2 — Grace Period
- Duration: minimum 6 months from the Deprecation date.
- Both
/api/v1/and/api/v2/respond normally during this period. - The
Deprecation: trueandSunsetheaders are present on every/api/v1/response throughout the grace period.
Phase 3 — Sunset
After the Sunset date, all requests to the old version return:
HTTP/1.1 410 Gone
Content-Type: application/problem+json
{
"type": "https://platform-kernel.io/problems/api-version-sunset",
"title": "API Version Sunset",
"status": 410,
"detail": "The /api/v1/ endpoint was sunset on 2026-12-01. Migrate to /api/v2/.",
"instance": "/api/v1/users"
}
SDK Versioning
SDK packages follow Semantic Versioning 2.0.0
(MAJOR.MINOR.PATCH):
| Segment | Changes when |
|---|---|
MAJOR (e.g., 2.0.0) | Breaking changes: removed exports, renamed hooks, changed types |
MINOR (e.g., 1.3.0) | New features, new hooks, new optional parameters — backward compatible |
PATCH (e.g., 1.2.1) | Bug fixes, performance improvements — no API changes |
SDK Deprecation Window
When a new major SDK version is released, the previous major version is supported for 12 months (CONVENTIONS.md §6 + kernel-spec §672). Deprecated SDK major versions receive security patches only — no new features.
kernelSdkVersion in Module Manifest
Every module manifest declares which SDK major version it targets:
"kernelSdkVersion": "^1.0.0"
The ^ prefix means the module is compatible with any 1.x.y
version. When the platform upgrades to SDK 2.0.0, modules with
"kernelSdkVersion": "^1.0.0" continue to work on the 1.x
compatibility layer until the 12-month support window closes.
Module Versioning
Module versions follow strict Semver X.Y.Z — no pre-release
qualifiers (-beta, -rc) are allowed in production manifests.
Immutable CDN Deployments
Every version of a module is an immutable deployment on the CDN. The Module Registry stores a URL mapping per version:
https://cdn.platform.io/modules/{tenantId}/{moduleId}/{version}/remoteEntry.js
This means:
- Rollback is instant — the Registry switches the
entryURL back to the previous version without republishing any code. - Rollforward — the Registry switches
entryto the new version URL. Users online at the moment of update see a browser toast:"Module {name} updated. Refresh to apply." - Version pinning — each tenant is pinned to a specific version. The Platform Owner or tenant admin manually approves upgrades through the Admin UI.
Update Flow
Protobuf / gRPC Versioning
The seven gRPC services use package-versioned proto paths:
platform.iam.v1
platform.billing.v1
platform.data.v1
platform.events.v1
platform.module_registry.v1
platform.integration_hub.v1
platform.common.v1
Backward Compatibility Enforcement (buf breaking)
Every pull request that modifies a .proto file is blocked by CI
unless it passes buf breaking (Buf CLI with breaking.use: [FILE]):
| Change | Allowed? |
|---|---|
| Add new fields to a message | Yes |
| Add new RPC to a service | Yes |
| Add new message type | Yes |
| Remove a field | No — CI blocks merge |
| Rename a field | No — CI blocks merge |
| Change a field type | No — CI blocks merge |
| Remove an RPC | No — CI blocks merge |
| Remove a message type | No — CI blocks merge |
When a breaking gRPC change is unavoidable, a new package version is
created (platform.iam.v2). Both packages coexist until all callers
migrate.
Event Schema Versioning
Domain events on Kafka topics follow the same non-breaking-by-default rule as gRPC. Event type names encode the version when a breaking change occurs:
auth.user.created ← v1 (stable)
auth.user.created.v2 ← v2 (breaking schema change)
During the deprecation period (minimum 90 days for events,
CONVENTIONS.md §22.3.1), both auth.user.created and
auth.user.created.v2 are published simultaneously. Consumers
migrate at their own pace. After 90 days, the old event type stops
being emitted.
Primitive Freeze
A Primitive (Auth, Data, Events, Notify, Files, Money, Audit) is considered FROZEN once it has passed all items in this checklist (referenced from the Glossary and used throughout the documentation):
| # | Criterion | Verification |
|---|---|---|
| 1 | Unit test coverage ≥ 80% | go test -cover |
| 2 | Integration tests green (Testcontainers) | CI green |
| 3 | Contract tests green (Pact) | CI green |
| 4 | OpenAPI spec published and validated | pnpm build in docs-kernel |
| 5 | All Markdown docs lint-clean | markdownlint-cli2 0 errors |
| 6 | pnpm build 0 broken links | Docusaurus build green |
| 7 | Changelog entry committed | CHANGELOG.md |
| 8 | No TODO/FIXME in production code | grep -rn TODO|FIXME services/ |
| 9 | golangci-lint run 0 errors | CI gate |
| 10 | Security review: Vault secrets, RLS enabled | Manual sign-off |
A frozen primitive must not have its public API changed without a deprecation cycle. Internal refactoring is allowed if all tests remain green.
Versioning Decision Tree
See Also
- API Conventions — URL patterns, CRUD verbs, pagination, error format
- REST API Overview — base URL, auth,
current
v1endpoints - Migration Guides — historical breaking changes and upgrade paths
- Changelog — full release history
- Glossary — Primitive, Freeze, and other term definitions