pub const API_MINOR: u32 = 24;Expand description
The integer MINOR of API_VERSION — see there. Bumped from 0 to 1 when params validation
became strict (#34); to 2 with the set_nickname verb + StatusResult.self_nickname (#37);
to 3 when allow/grant strings became STABLE principals — b64u:/eid:/roster names,
never nicknames (#38); to 4 with the set_app_metadata verb + PresencePeer.meta (#39);
to 5 with PeerReachability.meta — pairing-mode app metadata on the probe pong (#40);
to 6 with PeerInfo.principal — the peer’s eid: device principal on status (#41);
to 7 with PeerReachability.principal — the same on reachability rows (#42); to 8 with the
service_allow_grant/service_allow_revoke per-peer access verbs (#44); to 9 covering the
unregister_service (#50) / peer_services (#52) / Run env+cwd (#51) surface that shipped
in 0.10.1 without a bump, PLUS the set_relays live relay-set verb (#53); to 10 when
service_allow_revoke/peer_remove became IMMEDIATE — no verb shape changed, but their
observable contract did: a revoked principal’s next session is refused even on a connection it
already holds, and its live connections are severed. Previously both waited for the peer to
disconnect on its own, which is unbounded (#54). A consumer can guard on
api_minor >= 10 before telling a user that revocation has taken effect; to 11 when
service_allow_grant/service_allow_revoke gained EPHEMERAL-service support and became strict
about an unknown service name — a name in neither the config nor the ephemeral registry now
answers ERR_NO_SUCH_SERVICE instead of a silent {} (#55, #69); to 12 with the pushed
StreamFrame::Reachability liveness transition frame (#58); to 13 with
PeerReachability::path — direct-vs-relay attribution on every reachability row (#64); to 14
with the run-backend MCPMESH_PEER_EID identity var — the caller’s stable device principal,
unconditionally present, so a run server can scope per caller without keying on a nickname
(#60); to 15 with the blob_revoke / blob_unpublish verbs — per-scope withdrawal of a grant
and of a published hash, so un-sharing a file no longer requires unpairing the person (#62); to
16 when the app-blob provider became available in PAIRING mode — the blob verbs previously
errored on any daemon without an org root key, though their scope gate never needed one (#61);
to 17 when the service answer began coming from the LIVE registry rather than config + overlay,
so a grant the accept path would refuse is no longer advertised. Three surfaces share that
resolver and all changed together: status‘s services[].allow, peer_services’ name list,
and the mcpmesh/ping/1 probe’s services. No wire shape changed, only the source of truth —
exactly the class of change a downstream cannot see in a type diff (#100); to 18 with blob_republish, so a fetched blob can
be re-served and every recipient becomes a source (#83); to 19 with durable blob revocation — an
unpublish now survives a later republish via a per-scope withdrawal set, and
ERR_BLOB_WITHDRAWN distinguishes “deliberately withdrawn” from “never had it” (#107); to 20
with blob_list filters + paging AND a DEFAULT limit of 256 scopes (the clamp is 4096) — a
daemon with more scopes than that previously answered with
everything, and past the 16 MiB frame cap the CLIENT rejected the response as malformed, leaving
the caller an opaque failure with no way to page. The connection survived: the control surface
carries no strike bound. This is a behaviour change for existing callers, detectable via the new
total/truncated (#84b); to 21 when a
PATH change became a reachability transition — StreamFrame::Reachability stopped being an
up/down toggle and same-verdict frames became possible (#92); to 22 with a SECOND producer for
that frame: a live per-session watcher that pushes when a session’s selected path changes,
rather than waiting for a probe, at a cadence probes never had (#92); to 23 when
PeerReachability::rtt_ms stopped including the path-settle window — a relayed peer could
previously never report under 600ms, so “relayed AND fast” was unreachable by construction
(#123); to 24 when reachable stopped sharing a deadline with path classification — a relayed
peer whose pong arrived after ~2.4s was reported OFFLINE while it was answering (#128).
Not every semantic change gets a minor, and that is the gap to watch (#122). A minor marks a change to this surface. A change to behaviour BEHIND the surface — same fields, same shapes, different meaning — may not bump it, and is invisible to a type diff. 17 and 24 above happen to be that class and did bump; do not infer from them that every such change will. When bumping several minors at once, read this block end to end AND the release notes, not the diff.
That class is bigger than it looks: 10, 17, 21, 22, 23 and 24 all shipped with no change to any type in this file — they moved meaning, not shape. Six of the twenty-four. A downstream that diffs types across a multi-minor bump sees nothing for any of them.