5.10.2.4 Installations
The Installations domain of releases. Installed clients: enrolment, the update check that evaluates the channel rule again every time, the download of manifests and chunks through signed URLs, the events of every download and update, and the installation token. Staff read installations and events; clients act on their own. It is one API, with its own contract and its own version.
5.10.2.4.1 Versions¶
| Version | Status | Prod URL | Contract |
|---|---|---|---|
v1 |
Proposed | https://releases.moonitoring.com/installations/v1 |
installations/v1/openapi.yaml |
The resources follow the data model. Adds enrolment, the update check and the tester verification; the installation token of req 118.12 is the bearer of a client's calls.
5.10.2.4.2 Operations¶
Every operation names who calls it and the capability it checks (x-moonitoring-audience, x-moonitoring-capability in the contract); every capability is in the catalog of the data model (req 1002, 1006). Lists are paged by cursor, writes that create something carry an Idempotency-Key, errors are Problem Details.
| Operation | Request | Who | Capability |
|---|---|---|---|
| Enrol an installation | POST /installations |
Installed clients | none |
| List installations | GET /installations |
Staff | releases.installations.read |
| Count an application's installations | GET /installations/summary |
Staff | releases.installations.read |
| Check for an update | POST /installations/{installation_id}/update-check |
Installed clients | none |
| Rotate the installation token | POST /installations/{installation_id}/rotate-token |
Installed clients | none |
| Report an update | POST /installations/{installation_id}/update-events |
Installed clients | none |
| List an installation's events | GET /installations/{installation_id}/update-events |
Staff | releases.installations.read |
| Report a download from the download page | POST /update-events |
Organization users, staff or clients | none: any member of the Organization |
| List update events | GET /update-events |
Staff | releases.installations.read |
| Read an installation | GET /installations/{installation_id} |
Organization users, staff or clients | none: any member of the Organization or releases.installations.read |
| Start a tester verification | POST /tester-verifications |
Anyone | none |
| Confirm a tester verification | POST /tester-verifications/{verification_id}/confirm |
Anyone | none |
5.10.2.4.3 gRPC¶
farm verifies the installation a sync client reports, so that a client cannot claim an installation of another Organization.
| Service | RPC | Callers |
|---|---|---|
InstallationsService |
VerifyInstallation |
farm |
The contract is installations.proto, package moonitoring.releases.installations.v1:
// Proposed contract, version 1. Status: proposal for review, not confirmed design.
//
// Callers: farm (when a sync client reports the installation it runs as, to check that the installation
// exists, belongs to the sync client application and to the same Organization; req 67.2, 118).
// Deadline: 2 s.
// The callers listed are authentication only (decided 2026-11-11): each RPC below names who may call it and what
// it sees, and refuses anyone else with PERMISSION_DENIED.
// x-moonitoring-callers: farm
// x-moonitoring-requirements: 67.2, 118
syntax = "proto3";
package moonitoring.releases.installations.v1;
import "google/protobuf/timestamp.proto";
service InstallationsService {
// Whether an installation exists and what it is.
// Callers: farm only. Sees: the answer for the installation it asks about; it cannot list installations.
rpc VerifyInstallation(VerifyInstallationRequest) returns (VerifyInstallationResponse);
}
message VerifyInstallationRequest {
string installation_id = 1;
}
message VerifyInstallationResponse {
bool exists = 1;
string application_id = 2;
string application_slug = 3;
string channel_id = 4;
string organization_id = 5;
string current_build_id = 6;
string version_label = 7;
google.protobuf.Timestamp last_seen_at = 8;
}
5.10.2.4.4 Contract v1¶
Proposed version
v1 is a proposal for review: its endpoints, errors and capabilities were designed from the requirements and the flows and are not confirmed. It leaves proposal with its first release; from then on it changes only as described in Every API Is Versioned.
5.10.2.4.5 Rules Confirmed with the Implementation¶
Decided on 2026-11-05, from the choices made while building releases:
- Installation tokens are
mri_<random>on theAuthorizationheader, told apart from tokens ofaccessby the prefix (theinstallationTokenscheme of the contract); only their SHA-256 is stored. - A wrong token and an unknown installation both answer 401, so installation ids cannot be probed.
- Chunks are addressed by the hash of their uncompressed content:
chunks/<hash>, andchunks/<key>/<hash>for an encrypted depot, since the same content encrypted with two keys is two objects.chunk_base_urlis signed for the prefixchunks/, so one signed base covers both: the client appends<hash>, or<key>/<hash>with the key the manifest names, its query kept. - Enrolment without
current_buildtakes the channel's current build, and is a 409 when the channel offers none. - An update check without
current_buildmeans nothing is installed (decided 2026-11-10): it answers the build the channel's current TUF targets name, the active release, whatever the rollout bucket, as an update that is not mandatory, with full manifests and no patch; with no active release,update_availableis false. The client no longer sends the nil UUID. A fresh install never gets a superseded build (corrected 2026-11-10): such a build is not in the current targets, soreleases-clientcould not verify it. The rollout percentage applies only to updates of an installed build. - An installation that never confirms a start is retired after 30 days (decided 2026-11-10): the sweeper of
releasessetsretired_aton an installation with nostarted_at30 days after it enrolled, since a fresh install that failed leaves an enrolled installation nobody can delete. Its token is then refused with 401, like an unknown installation, and the row is kept; installing again enrols a new one. - The installer enrols with the person's token (decided 2026-11-10): for an application of the Organization audience, the token of the person who signed in to the installer through the browser (Installer and Client Library).
mandatory(belowmin_build_number) does not bypass the rollout, and a rollback is offered as an update.- Tester proofs: a six-digit code valid 15 minutes, five wrong codes, five verifications per address per hour (429); the proof
mtp_<random>lasts 12 hours. The code goes only to an active tester, and the answer is the same for any address. - Download events of private software need a caller of the application's audience or a tester proof, recorded as the tester; an anonymous call is a 401.