Releases: SemVer per component, signed artifacts, SBOM, provenance¶
Context and Problem Statement¶
The monorepo contains server, apps, SDKs (Python, TypeScript) and adapters. They change at different paces and have different users: instance operators, app publishers, developers of integrations. Instance operators must be able to check the origin and content of every artifact. How do we version, tag, sign and document?
Decision Drivers¶
- independent releases without artificial version jumps
- tags must be unique per component and resolvable for tools
- verifiable origin without long-lived signing keys
- SBOM for license and vulnerability checks by the instance operator
- release notes that say whether an upgrade needs manual work
Considered Options¶
- SemVer per component with
VERSIONandCHANGELOG.mdper component, tags<component>/vX.Y.Z; cosign keyless, SBOM (Syft), build provenance (actions/attest) - One shared version for the whole monorepo (lockstep)
- Signature with a long-lived key (GPG or cosign key pair)
- No signature, only checksums
Decision Outcome¶
Chosen option: "SemVer per component; cosign keyless, SBOM, provenance", because components are published independently and the origin can be verified without key management.
- Tags
<component>/vX.Y.Z(server/vX.Y.Z,client/vX.Y.Z,sdk-python/vX.Y.Zand so on), the installation bundlevX.Y.Z; names and prefixes fromtools/ci/components.py(18-release.md 2). Go's tag rule for modules in subdirectories (https://go.dev/ref/mod, retrieved 2026-10-10) does not apply to the server module, because as a main module it is never loaded (PLAN P-05). - Channels stable and beta; apps promote the same build, server and packages a pre-release from the same commit (18-release.md 5).
- Every artifact: SBOM (SPDX and CycloneDX), cosign signature (keyless; as long as the repository
is private, a key pair without a transparency log according to ADR 0062), checksums;
attestation via
actions/attestas soon as the repository is public (in Free, Pro and Team available only for public repositories; https://github.com/actions/attest-build-provenance, retrieved 2026-10-10). - No
latesttag; installations pin versions.
Consequences¶
- Good, because an SDK bug does not force a server release and vice versa.
- Good, because instance operators verify the origin with
cosign verifyandgh attestation verify. - Bad, because several changelogs and tags have to be maintained (a tool generates drafts).
- Bad, because no attestation is created until the repository is published.
- Neutral, because the Go module path of the server stays the same on a major jump, as long as the module is never loaded as a dependency (PLAN P-05).
Confirmation¶
- Gate check:
VERSIONequals the tag; the changelog section is present. - The release chain aborts if signature, SBOM or checksums are missing.
- Portability test: before
install.shit pulls the server images itself, like every installation by the tag of the pinned server version, and checks the signature of each of their digests; after the installation it checks that the containers use exactly these images, and names the digests in the result (16-operations.md, section 11.1; D-W-96, D-W-99).
Pros and Cons of the Options¶
SemVer per component¶
- Good, because versions say something about the respective component.
- Bad, because the compatibility between components needs its own rules (protocol version, minimum app version).
Shared version¶
- Good, because there is one number for everything.
- Bad, because every change to one component publishes all others again.
- Bad, because SemVer statements (breaking yes or no) would be wrong for most components.
Long-lived signing key¶
- Good, because it is independent of CI and public infrastructure.
- Bad, because the key must be protected, rotated and revoked on loss.
Only checksums¶
- Good, because it is simple.
- Bad, because a checksum shows only transmission errors, not the origin.
More Information¶
- Procedure: docs/operations/release.md.
- Tool for changelog drafts: git-cliff behind
make release-prep(ADR 0060). - Signatures in the private phase: ADR 0062.