Release policy
Scope: the rules every package follows when it ships. The per-repo
checklists (gate commands, registry steps) live in each repo's docs/release.md
(iOS: PUBLISHING.md); this page is the policy they all obey.
Universal rules
- Every package runs its own semver clock — no lockstep with the backend,
each other, or any release train.
0.xwhile pre-stable; client-surface break or a breaking backend-surface change → major; features → minor; fixes → patch. - No remote/publish operation without explicit instruction (platform inviolable): builders stage everything locally; the maintainer performs the publish act.
- Never publish with uncommitted changes to the shipped surface.
- Never release on a keyless gate run — e2e suites self-skip without keys; a skip is not a pass.
- Zero-runtime-dependency contracts (node, android, ios) never gain runtime deps.
Package clocks
| Package | Registry | Clock owner | Version source | Current |
|---|---|---|---|---|
| optolink-node | npm @optomatica/optolink-sdk | own | package.json | 0.1.0 |
| optolink-android | Maven Central com.optomatica:optolink-android | own | build.gradle.kts coordinates (+SDK_VERSION, example versionName mirrors) | 0.1.1 |
| optolink-ios | SPM via the public releases-only mirror Optomatica/optolink-ios-sdk | own | SDKVersion.swift (+README install snippet) | 0.1.0 |
| optolink-flutter | pub.dev optolink_flutter | own | pubspec.yaml | 2.0.1 |
| optolink-backend | no registry — Dokku/Heroku deploys (app.json predeploy runs prisma migrate deploy) | deploy-per-commit | package.json (see below) | 1.0.0 |
| optolink-portal | no registry — static dist/ (Cloudflare Pages previews + dashboard.optoapp.link) | deploy-per-commit | package.json (0.0.0 — unused) | — |
| optolink-docs | public /docs build (build:public, excludes /internal) | CI on push | n/a | — |
The flutter plugin is a thin channel client over the native iOS/Android SDKs — a native-SDK breaking change forces a flutter release even with no Dart change.
Source-checked against optolink-backend @ 29f8589, optolink-node @ d4b5dae, optolink-android @ fb529ef (coordinates
0.1.1), optolink-flutter @ 6ad24b4 (pubspec.yaml2.0.1), optolink-ios @ 9482175 (PUBLISHING.md,0.1.0), 2026-10-07.
The backend compat line — policy
Every SDK README carries "Compatible with OptoLink backend v2.1.0+". The
flagged B-018 problem: the backend has no API versioning — its package.json
and OpenAPI document say 1.0.0 — so nothing machine-readable corresponds to
the line.
Policy (recommended, pending owner sign-off): the v2.1.0 in the compat
line refers to the product release train (the v2.1.0 platform release), not
to any backend artifact version. Concretely:
- The line stays hand-maintained in each SDK README (plus
CHANGELOG.mdand the docs-site changelog page) — no build step derives it, because there is nothing to derive it from. - This page is the register of what the current line means:
v2.1.0+= the platform release carrying the v2 billing/entitlements backend surface. When backend/linksbehavior drifts incompatibly, the SDK owner bumps the line to the next product-train version and records the new meaning here. - Bump timing is the SDK's own release step (step ① in each repo checklist), not a backend-deploy step — a backend drift only obliges the next SDK release to move the line.
If the owner instead wants a machine-readable anchor (e.g. a /health
apiVersion field or aligning backend package.json to the train), amend this
section — until then the hand-maintained line above is the rule of record.
What must sync at publish
A release is not done when the registry has it — all of these move together:
- Changelog: repo
CHANGELOG.md↔ docs-sitesdk/<platform>/changelogpage (update both, or note the pending site update on the page). Gap: flutter has no docs-site changelog page yet — its pub.devCHANGELOG.mdis the record; add the site page when the docs pass lands (B-005). - README: compat line (policy above) + the install-snippet version floor.
- Version mirrors: android's
SDK_VERSIONstamp + exampleversionName; ios'sREADMEinstall snippet + this policy's clock table; the repo checklist'sCurrent:lines. - Docs-site: any SDK page whose contract changed (the
systems/sdk-contracts/*pages carry their own verification lines — refresh them against the released backend surface, not the registry artifact).