Appearance
Keryx versioning and compatibility policy
Approved: 26 August 2026
This document is the P3-05 policy packet for Keryx for SafeCall: semantic version rules, monotonic build numbers, annotated source tags, changelog ownership, store release-note derivation, QR schema compatibility and migration, minimum SafeCall compatibility placeholders, downgrade behavior, abandoned-build handling, and launch support window.
It does not claim an automated release pipeline (#111), CI version gates (#112), store console paste (#125), QR v2 implementation in app or SafeCall server code, a numeric {min_safeCall} value (recorded at first release in #114), or the full compatibility/EOL matrix deferred to #130.
Purpose and non-goals
Purpose
- Approve semver and build-number rules for
keryx/pubspec.yaml. - Define annotated
keryx-v*tags in the safecall monorepo. - Assign changelog ownership and map entries to store release-note templates.
- Document QR schema evolution, stored-config migration, and coordinated v2 cutover expectations.
- Record downgrade, abandoned-build, and launch support-window policy.
Non-goals
- Implementing automated bump/tag in CI or release scripts.
- Changing current QR parser code (v2-only; v1 scans are rejected with on-device copy).
- Replacing this policy with CI-owned bumps. Current pre-release candidate is
1.0.0+3(builds 1 and 2 were consumed by the Play internal draft and the first Internal TestFlight IPA). - Replacing SafeCall Nav (
mobile/) versioning —mobile-v*tags remain Nav-only.
Current version baseline
| Field | Value | Source |
|---|---|---|
| Public version | 1.0.0 | keryx/pubspec.yaml (before +) |
| Build number | 3 | keryx/pubspec.yaml (after +) |
| Changelog | First-release notes | keryx/CHANGELOG.md |
| QR in code | safecall.keryx.ntfy.v2 | keryx/lib/models/keryx_config.dart |
| QR protocol target | safecall.keryx.ntfy.v2 | provisioning-protocol.md |
Semantic version rules
Public version uses MAJOR.MINOR.PATCH in pubspec.yaml (the part before +).
| Segment | When to bump | Examples |
|---|---|---|
| PATCH | Compatible bug fixes, small UX polish, dependency patches with no behavior change | 1.0.0 → 1.0.1 |
| MINOR | Backward-compatible features, material UX changes, new optional QR fields that older apps ignore | 1.0.1 → 1.1.0 |
| MAJOR | Breaking QR schema, breaking stored-config shape, minimum SafeCall bump that drops older servers, or product-positioning change requiring re-provisioning | 1.1.0 → 2.0.0 |
Align version intent with release types in Publishing Keryx (first release, routine patch/minor, major, hotfix, security).
Hotfix and security releases still bump at least PATCH (or MINOR/MAJOR when compatibility changes). Never ship a store candidate without incrementing the public version from the last promoted build unless the prior candidate was never uploaded and is discarded before any store record references it.
Build number rules
The integer after + in pubspec.yaml is the monotonic build number shared across iOS and Android for a given store candidate.
| Rule | Policy |
|---|---|
| Monotonicity | Each uploaded or submitted candidate uses a build number strictly greater than any prior upload for the same platform store record |
| Cross-platform | iOS and Android releases from the same public version may share one build number when built from the same tagged commit; single-platform releases still increment |
| Never reuse | Rejected, abandoned, or superseded candidates consume their build number — do not reuse after Play or App Store Connect assignment |
| Pre-upload bumps | Increment before building when the previous candidate reached upload, even if not promoted to production |
Example:
yaml
version: 1.0.1+21.0.1 is the public version; 2 is the build number.
Source tag policy
Keryx store artifacts are attributed to annotated tags in the safecall monorepo:
| Item | Policy |
|---|---|
| Tag format | keryx-vMAJOR.MINOR.PATCH (e.g. keryx-v1.0.0) |
| Tag target | Commit that produced the signed AAB/IPA uploaded or submitted |
| Tag type | Annotated tag with message: public version, build number, operator/date reference |
| Forbidden patterns | Do not use mobile-v* (SafeCall Nav) or undecorated version tags for Keryx |
Tag after verify scripts pass (verify:keryx-aab, verify:keryx-ipa) and before or immediately after store upload. Record tag name, commit SHA, and build number in the controlled evidence archive (#114).
Changelog ownership
| Item | Owner |
|---|---|
| Canonical file | keryx/CHANGELOG.md |
| Policy approver | Thomas Minitsios (P0-05 RACI) |
| Language | English user-facing entries (Czech store fields derived per localization.md) |
Monorepo root CHANGELOG.md | SafeCall server/product scope only — not Keryx store notes |
Workflow:
- Accumulate user-visible changes under
## Unreleasedduring development. - On release cut, move entries to
## X.Y.Z — YYYY-MM-DD(or launch date TBD). - Derive Apple/Google release notes from the released section (see below).
- Archive changelog excerpt + store paste in #114 evidence.
Release-note derivation
Map changelog sections to templates in store-listing-copy.md:
| Placeholder | Source |
|---|---|
{version} | Public semver from pubspec.yaml / tag |
{min_safeCall} | Recorded per release in #114 evidence — TBD at G2 for first public release |
{changes} | Bullet list from changelog (omit internal/tooling-only items) |
Rules:
- First public release: use the fixed welcome/compatibility templates; do not invent
{min_safeCall}until G2 records it. - Routine updates: paste
{changes}from the released changelog section. - Hotfix: one-line summary acceptable when the fix is narrow; still log full detail in
CHANGELOG.md. - Major / QR cutover: include explicit re-provision or minimum SafeCall statement; coordinate with client enablement (#120).
QR schema compatibility
| Schema | Status | Policy |
|---|---|---|
safecall.keryx.ntfy.v1 | Current code | Pre-launch legacy; must not be emitted for production QR after v2 cutover |
safecall.keryx.ntfy.v2 | Approved protocol (#95) | Launch production target; requires subscribe_auth per provisioning-protocol.md |
Closing #113 approves policy only. v2 cutover is a coordinated release gate:
- SafeCall admin UI stops emitting v1 QR.
- Keryx rejects new v1 scans (fail-closed).
- Stored v1 credentials are not silently upgraded — administrators re-scan v2 QR.
- ntfy requires HTTPS + ACL per #119 at cutover.
See provisioning-protocol fail-closed v1 migration rules for field-level detail.
Stored-config migration
On app upgrade when the QR schema is unchanged:
- Preserve topics, friendly labels, server URL, and pause state in
KeryxConfigStore(forward-only JSON shape). - Do not clear history unless the user runs reset or a documented migration requires it.
On v1 → v2 cutover:
- No silent credential upgrade — require re-scan of v2 QR.
- Reject opening or refreshing with stored v1 config after cutover build ships.
- Document migration in release notes and client administrator guidance.
Future schema bumps follow the same rule: breaking stored shape → major version
- explicit re-provision unless a forward-compatible reader is proven in #118 evidence.
Minimum SafeCall and ntfy compatibility
| Field | Launch policy |
|---|---|
{min_safeCall} | Placeholder until first public release evidence (#114); set at G2 go/no-go, not invented in docs |
| ntfy server | HTTPS-only; topic ACL and subscribe tokens per v2 protocol and #119 checklist |
| OS floors | iOS/iPadOS 17+, Android 12 (API 31)+ per P0-04 — stated in store templates |
Each promoted release records {min_safeCall}, QR schema version accepted, and OS/API floors in the #114 controlled archive.
Downgrade behavior
| Scenario | Policy |
|---|---|
| App Store / Play rollback | Stores do not roll users back to older builds; fixes require a new higher build |
| Sideload / manual install of older APK/IPA | Unsupported for production administrators |
| Downgrade after schema migration | May fail to connect or show stale config until re-provisioned with current QR |
| Major version downgrade | No guarantee of forward-compatible stored config |
Administrators on outdated builds remain on best-effort support per support window below; security issues may force minimum-version enforcement in a future #130 matrix.
Abandoned and rejected builds
When a candidate fails verification, review, or go/no-go:
- Archive AAB/IPA checksum, build number, commit SHA, and rejection reason in #114.
- Mark the build abandoned in the release record — do not promote.
- Still consume the build number; increment before the next upload.
- Never promote an untested binary or one that skipped verify scripts.
Support window (launch policy)
Until #130 defines full EOL:
- Supported: current store release + previous patch on the same minor (N and N−1 patch, e.g.
1.0.2and1.0.1when1.0.2is current). - Best-effort: older patch/minor versions still on devices.
- EOL matrix, store removal, forced upgrade: owned by #130 (P6-03).
Evidence handoff
| Remaining work | Owner issue |
|---|---|
| Reproducible bump/build/tag pipeline | #111 — first recorded run 1 September 2026 did not bump or tag. Operator cut is bun keryx (bump, signed AAB+IPA, commit, keryx-v* tag, push). Store upload stays manual. |
| CI quality and version gates | #112 |
Release records, checksums, {min_safeCall} | #114 |
| Store release-note paste | #125 |
| Full compatibility / EOL lifecycle | #130 |
| QR v2 implementation and cutover | Post-#95 delivery; coordinated with #119 |
Launch posture
Closing #113 approves versioning and compatibility rules. It does not claim:
- Automated version increment or tagging.
- QR v2 parsing in shipped binaries.
- A numeric minimum SafeCall version.
- Store release notes pasted or a production promotion.
Review record
- Status: approved as the P3-05 versioning and QR compatibility policy.
- Date: 26 August 2026.
- Approver: Thomas Minitsios under the P0-05 RACI.
- Depends on: P1-02 provisioning protocol (QR v2 contract).
- Evidence sources:
keryx/pubspec.yaml,keryx/lib/models/keryx_config.dart, store-listing-copy.md, keryx-publishing.md.