FOLIO Application Versioning Proposal
FOLIO Application Versioning Proposal
Use vMAJOR.minor.patch as a release-cadence version, similar to Keycloak and macOS, instead of reserving artificial version slots such as +100 for applications or +10 for modules. This keeps the version readable, predictable, and aligned with how FOLIO actually validates applications today.
vM.m.p
MAJOR - Flower release or another large feature/release train.
This does not imply breaking module interface changes.
minor - CSP release.
patch - Security fixes and urgent fixes for the current CSP.Executive Summary
FOLIO is not a monolith. Application and module versions currently work mostly as artifact and release identifiers. They do not carry strong compatibility meaning by themselves.
The real compatibility checks are elsewhere:
Area | What is actually validated |
|---|
Area | What is actually validated |
|---|---|
Module interface integrity | Required interfaces must be satisfied by compatible provided interfaces. |
Application dependencies | Dependency versions must satisfy SemVer ranges. |
Descriptor syntax | Application and module versions must look like SemVer. |
Upgrade flow | Requested application version must be higher than the currently entitled version. |
Therefore, the version number should communicate the release train, not pretend to encode compatibility rules that are already handled by interface versions and dependency ranges.
Why Not Slot-Based +100 / +10 Versioning
The slot-based approach makes version numbers carry operational bookkeeping:
Application: 3.0.100 -> 3.0.101 -> 3.0.200
Module: 3.0.10 -> 3.0.11 -> 3.0.20This creates several problems:
Problem | Impact |
|---|
Problem | Impact |
|---|---|
Artificial gaps | Numbers become harder to read and explain. |
Different scales for apps and modules | Developers must remember two policies. |
False precision |
|
Future constraints | Slots must be reserved, explained, and protected. |
More policy than value | Compatibility is still validated by interfaces and dependency ranges. |
A release-cadence model is simpler:
3.0.0 - Flower release / large feature train
3.1.0 - CSP 1
3.1.1 - urgent or security fix for CSP 1
3.2.0 - CSP 2
3.2.1 - urgent or security fix for CSP 2Industry Precedent
Keycloak deliberately changed its versioning approach for continuous delivery. A major version can represent a feature release and does not necessarily mean a breaking change.
macOS also uses major versions to represent release generations. The version communicates the release line first, not API compatibility.
FOLIO can use the same idea: version numbers identify the release generation and patch level, while compatibility remains governed by module interfaces and dependency ranges.
Proposed Version Meaning
Version part | Meaning in FOLIO |
|---|
Version part | Meaning in FOLIO |
|---|---|
| Flower release or another large coordinated feature/release train. |
| CSP release within that major line. |
| Security fix or urgent fix for the current CSP. |
Example:
v3.0.0 - Trillium / major release train
v3.1.0 - Trillium CSP 1
v3.1.1 - Security fix for Trillium CSP 1
v3.2.0 - Trillium CSP 2
v4.0.0 - Next Flower release or another large release trainPros
Pro | Why it matters |
|---|
Pro | Why it matters |
|---|---|
Easier to understand | Versions are short and map directly to release cadence. |
Matches current validation | Compatibility remains in interfaces and dependency ranges. |
Avoids artificial slots | No need to reserve |
Same model for apps and modules | One versioning rule can be explained across layers. |
Compatible with SemVer tooling | Still uses |
Better communication | A version tells people which release train and patch level they are looking at. |
Similar to Keycloak and macOS | Proven pattern for release-generation versioning. |
Opportunity for automated patch-releases | In future it provides possibility to implemented automated flows for each of the CSPs to identify outdated or security-vulnerable dependencies and update them as a patch release |
Con
Con | Mitigation |
|---|
Con | Mitigation |
|---|---|
This is a small shift away from traditional SemVer because | Document the rule clearly: interface versions define compatibility; application and module versions define release cadence. |
Key Principle
Application and module versions should not be overloaded with compatibility meaning.
Compatibility should remain validated by:
Module requires/provides interfaces
Application dependency SemVer rangesThe application or module version should answer:
Which FOLIO release train is this?
Which CSP is this?
Is this an urgent or security patch for that CSP?Current Validation Reality
The current code in mgr-applications and mgr-tenant-entitlements supports this split of responsibilities:
Validation behavior | Current implementation meaning |
|---|
Validation behavior | Current implementation meaning |
|---|---|
Application/module versions | Validated for SemVer-like syntax and used for identity, ordering, and upgrade comparison. |
Application dependencies | Validated by name and SemVer range satisfaction. |
Module interfaces | Required interfaces must be compatible with provided interfaces. |
Tenant upgrade | Requested application version must be greater than the installed version. |
Important distinction
Application and module versions do not currently prove API compatibility by themselves. The real compatibility boundary is the module interface contract plus the application dependency range.
Diagram: Responsibility Split
@startuml
title FOLIO Versioning Responsibilities
left to right direction
rectangle "Application Version\nvM.m.p\nRelease train marker" as AppVersion
rectangle "Module Version\nvM.m.p\nArtifact marker" as ModuleVersion
rectangle "Interface Version\nmajor.minor\nCompatibility contract" as InterfaceVersion
rectangle "Application Dependency\nname + SemVer range" as DependencyRange
rectangle "mgr-applications" as AM {
rectangle "Descriptor syntax checks" as Syntax
rectangle "Dependency range validation" as DepValidation
rectangle "Interface integrity validation" as InterfaceValidation
}
rectangle "mgr-tenant-entitlements" as MTE {
rectangle "Entitlement / upgrade flow" as Flow
rectangle "Installed vs requested app check" as UpgradeCheck
}
AppVersion --> Syntax : must be valid SemVer syntax
ModuleVersion --> Syntax : must be valid SemVer syntax
DependencyRange --> DepValidation : must satisfy SemVer range
InterfaceVersion --> InterfaceValidation : requires must match provides
AppVersion --> UpgradeCheck : must increase on upgrade
InterfaceValidation --> Flow : compatible module set
DepValidation --> Flow : compatible application set
note bottom of AppVersion
Does not define API compatibility by itself.
end note
note bottom of InterfaceVersion
This is the real compatibility contract.
end note
@endumlDiagram: Proposed Release Flow
@startuml
title Proposed FOLIO Application Version Flow
skinparam shadowing false
state "Flower / large feature train\nv3.0.0" as Major
state "CSP 1\nv3.1.0" as Minor1
state "Urgent or security fix\nv3.1.1" as Patch1
state "Another urgent fix\nv3.1.2" as Patch2
state "CSP 2\nv3.2.0" as Minor2
state "Next Flower / large feature train\nv4.0.0" as NextMajor
Major --> Minor1
Minor1 --> Patch1
Patch1 --> Patch2
Patch2 --> Minor2
Minor2 --> NextMajor
note right of Major
MAJOR follows release train,
not necessarily breaking API change.
end note
note right of Minor1
minor identifies the CSP line.
end note
note right of Patch1
patch is for security or urgent fixes
within the current CSP.
end note
@endumlDiagram: Validation Flow
@startuml
title Application Validation Flow
actor "Application Descriptor" as Descriptor
participant "mgr-applications" as AM
participant "DependenciesValidator" as DV
participant "Interface Integrity Check" as IV
participant "mgr-tenant-entitlements" as MTE
Descriptor -> AM : register / validate descriptor
AM -> AM : validate descriptor syntax\nid, version format, module descriptor shape
AM -> DV : validate application dependencies
DV -> DV : dependency name exists?
DV -> DV : dependency version satisfies SemVer range?
AM -> IV : validate module interfaces
IV -> IV : collect required interfaces
IV -> IV : collect provided interfaces
IV -> IV : required interface compatible with provided interface?
MTE -> AM : load application descriptors
MTE -> AM : validate descriptor set
MTE -> MTE : verify requested upgrade version is higher
MTE -> MTE : build entitlement / upgrade flow
note over AM, MTE
Application/module version numbers are used for identity,
ordering, and dependency range matching.
They do not replace interface compatibility validation.
end note
@endumlDiagram: Slot-Based vs Release-Cadence Versioning
@startuml
title Versioning Approach Comparison
left to right direction
rectangle "Slot-Based Versioning\n\nApps: 3.0.100 -> 3.0.101 -> 3.0.200\nModules: 3.0.10 -> 3.0.11 -> 3.0.20" as Slot
rectangle "Release-Cadence Versioning\n\n3.0.0 -> 3.1.0 -> 3.1.1 -> 3.2.0" as Cadence
rectangle "Requires reserved gaps\nDifferent rules by layer\nPolicy is not validated as compatibility" as SlotIssues
rectangle "Readable release line\nSingle rule for apps/modules\nCompatibility remains in interfaces/ranges" as CadenceBenefits
Slot --> SlotIssues
Cadence --> CadenceBenefits
@endumlSummary
The recommended approach is to keep SemVer-shaped versions but define their meaning around the FOLIO release cadence.
This gives us simple, readable versions while preserving the validation model FOLIO already uses:
Versions communicate release lineage.
Interfaces and dependency ranges validate compatibility.