The axes
Every admitted release carries a compatibility block:runtimeVersions is a record, not something you pin
It captures the Framework version your release was reviewed against, for
provenance. It does not gate anything, and you should not reason about it.
It cannot: the Framework version moves with every Voyant release, and you have
no way to tell which of those releases touched anything your app depends on.
Treating it as a compatibility axis would mean every Voyant release
invalidating every app admitted before it — which is precisely why it does not.
Why the app API is a date
Your backend calls/v1/app/* over HTTPS and installs no Voyant packages, so a
package version range would describe nothing you actually have. A date does.
The runtime serves several dated versions at once, so a new one appearing never
breaks you; you move when you choose to.
Send the version you built against:
Why the extension protocol is a major
Your manifest declares a range against the admin UI extension API ("^1", "1.x", or an exact "1.2.3"), which the admin evaluates when it
renders your frame. The compatibility axis is coarser — just the major —
because that is what a breaking protocol change moves.
Where compatibility is checked
At Marketplace admission. Your release is reviewed against a pinnedsourceRepository and sourceRevision, and the compatibility block is recorded
with it. An operator installing your app gets a release already known to work
against the contracts their runtime serves.
Nothing is resolved at install time and nothing is negotiated at render time.
If an axis you declared is no longer served, the release stops being offered —
it does not fail halfway through an install, and it never blocks the operator’s
own upgrade.