Skip to content

5.10.1 Introduction

releases is the system responsible for the installed clients: what a version contains (builds, manifests, chunks), who receives it (channels, releases, recipient Organizations, tester groups), the trust chain clients verify, and the installations with their updates. It belongs to the Distribution domain of the platform. Every interface it offers follows Choosing an Interface.

Proposal for review

The contracts of this system are a proposal, not confirmed design: endpoints, events and calls were written from the refined requirements, the data model and the flows, and wait for review. What needs a decision is collected in Open Decisions.

5.10.1.1 Host Names

Environment Host
Prod releases.moonitoring.com
Stage stage-releases.moonitoring.com, behind IAP

Release files are served by Cloud CDN with short signed URLs in both environments (decided 2026-11-11 for stage, as in prod), so the update check always carries a chunk_base_url and a download link always redirects to the CDN. Only the API hosts above are behind IAP in stage; the files are protected by the signed URLs that releases mints (Network).

The names follow the host name rule; on a developer's computer each service answers on a local port (Running Locally). Each domain below is a path on these hosts, followed by its version: https://releases.moonitoring.com/<domain>/v1.

5.10.1.2 Domains

Each domain of releases is one API, with its own contract and its own version.

  • 5.10.2.1 Builds

    What a version contains: the catalog of projects, applications, platforms and depots, and the builds with their manifests and chunks, uploaded by CI through signed URLs and deduplicated by content. /builds/v1

  • 5.10.2.2 Channels

    Who receives a version: channels and their access rule, releases of a build on a channel with their approval, pauses and rollbacks, recipient Organizations and tester groups. /channels/v1

  • 5.10.2.3 Signing

    The trust chain clients verify: the public keys of the TUF roles, whose private halves live in Cloud KMS, and the signed metadata documents with their signatures. /signing/v1

  • 5.10.2.4 Installations

    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. /installations/v1

  • 5.10.2.5 Downloads

    The links to the installer of every application, open to anyone: a universal latest link that detects the platform, a latest link per platform, and a link per version and platform. /downloads/v1

5.10.1.3 How It Is Used

CI build

  1. CI passes Identity-Aware Proxy on the Console's host with the Google ID token of its Google service account, with no key, and calls the Builds domain through https://<env>-console.moonitoring.com/api/releases, where console-server adds the staff token of the staff service account linked to it (Uploading a Version from the Console). That account's role holds releases.builds.upload and releases.releases.read only, so CI reads the catalog and its builds but never stages them. It asks which content-addressed chunks the Builds domain already holds.
  2. CI uploads missing chunks and signed manifests through signed URLs.
  3. CI finalizes the build, which is then available for a release.

Release approval

  1. A releaser stages a build on a channel.
  2. A second person approves it, satisfying the two-person release boundary.
  3. Releases signs the TUF metadata with keys in Cloud KMS and activates the release for that channel.

Installed client update

  1. An installed client enrols with the identity of its audience and receives an installation token. For an application of the Organization audience, such as the farm sync client, the installer enrols with the token of the person who signed in to it.
  2. It fetches the TUF documents and checks for an update; Releases evaluates the channel rule again using current memberships and entitlements.
  3. If the client is eligible, it downloads manifests and chunks through signed URLs and verifies the trust chain locally.
  4. A caller that is not eligible receives the same non-enumerating response as if the private release did not exist.
flowchart LR ci{{CI service account}} -->|REST uploads| releases[Releases API] client{{Installed client}} -->|REST enrolment and updates| releases console{{Console}} -->|REST staging and approval| releases releases -->|membership and entitlement checks| platform[Access / Farm] releases -->|release events| farm[Farm]
  • Called by: Console (REST); Farm sync client and installed clients (REST); Organization Dashboard (REST); Public readers (REST); access (gRPC CatalogService); farm (gRPC CatalogService, gRPC InstallationsService); moochat (gRPC CatalogService).
  • Calls: access (gRPC OrganizationsService); farm (gRPC EntitlementsService).
  • Publishes events consumed by: farm (4 event types).
  • Consumes events of: access (2 entries), farm (3 entries).
  • Reads no other system's database: everything above goes through a contract on this page or an event.

5.10.1.4 Synchronous Calls Between Systems

InstallationsService (verify) in Installations. It calls EntitlementsService.Check for the features a channel requires.

5.10.1.5 Events

Events are facts in the past tense, published through the outbox and delivered at least once on the topic releases.events.v1; the envelope and the guarantees are in common/v1/events.yaml. Events marked outside reach the Pub/Sub subscriptions an Organization registers in Webhooks, pushed to its HTTPS endpoint or pulled by its own service account.

Publishes (contract: events/v1/asyncapi.yaml):

Event Published when Consumers Outside
build.revoked.v1 A build was revoked; it can no longer be released or rolled back to. none yet no
release.activated.v1 A release became active on a channel: clients in its rollout receive the build at their next check. farm yes
release.paused.v1 A release stopped being offered. none yet yes
release.rolled_back.v1 A channel was rolled back to an older build. farm yes
installation.enrolled.v1 A client enrolled on a channel. farm no
installation.updated.v1 An installation reported an update, successful or not; its current build may have changed. farm no

Consumes:

Event From Why
organization.*.v1, membership.*.v1, organization_role.updated.v1 access Evaluates the channel rule with live memberships at every update check.
entitlement.*.v1 farm Evaluates required features at every update check.
staff_membership.changed.v1, staff_role.updated.v1 access Authorizes the staff audience.
sync_client.enrolled.v1, sync_client.retired.v1 farm Links installations of the sync client application to their farm.
erasure_request.executed.v1 farm Anonymizes installations and events of the farm's Organization.

5.10.1.6 Installer and Client Library

The installer and the client side of updates live in moonitoring-system-releases, written once for every installed client (decided 2026-11-10): the farm sync client today, MooChat on the desktop later.

  • releases-client, a library: enrolment of an installation, the update check, the verification of the channel's TUF chain from a pinned root, the manifest of format 1 and its chunks, staging a new version and rolling back a version that fails to start. Each installed client links it, pinned by commit, and adds only its own work.
  • releases-installer, an app, and the single installer file of every application (decided 2026-11-11): releases makes one per build and platform, with the application, the build and the roots of the application's listed channels inside it, and the download links give it to anyone. When it runs it signs the person in, enrols on a channel they may receive and installs the build only while that channel's current targets name it; otherwise it offers the latest. Its windows are those of the locked prototype (welcome, options, installing, done, update, error, uninstall), parameterized by the application it installs, per user and without elevation, built on releases-client and on the design system. Executables are not code-signed for now, in prod too (decided 2026-11-10); what reaches a PC is still verified by the channel's TUF chain.
  • One base installer per application and platform serves every environment and every channel (decided 2026-11-13 with infra). The CI builds releases-installer once per application and platform with nothing of an environment or a channel inside, and publishes it by digest; a Cloud Deploy hook, approved like a release, copies that same file to installers/base/<application slug>/<os>-<arch> in the content bucket of each environment, so stage and prod make their installer files from the same bytes. Everything that differs per environment and per build comes from the parameters releases writes into each installer file:

    • the application, the build, the platform, the default channel and the root of every listed channel;
    • the environment: its name, its hosts (access, the Account app, releases, the release files host, and farm for an application that carries adapters, the farm sync client), and what stands in front of them: nothing in prod, or IAP with the installer's desktop OAuth client of that environment (installer-desktop-stage, Signing in through IAP).

    The parameters carry no secret: the desktop client's secret ships inside the app and protects nothing, as for every native app. They are read behind one interface of the installer: on Windows they are appended to the executable; macOS will read them from a separate file, because bytes appended to a signed app break its signature, and its format and signing are decided here before the port starts. - In stage the installer passes IAP with the client its parameters name: before its first call of a system it signs the person in to Google in the browser, ahead of their MooNitoring sign-in, keeps the Google tokens in memory only, sends the ID token in Proxy-Authorization on every call of access, farm and releases, and revokes the Google refresh token when it closes, as it revokes the person's. The release files host gets no Google token. A silent install has nobody to sign in, so in stage it stops and says so. - The installer signs the person in through the browser, as the sync client does (decided 2026-11-10), as its own registered native app moonitoring-installer (Signing In from a Native App). The person signs in once: 1. With the person's token, switched to the Organization they choose, the installer enrols the installation (POST /installations/v1/installations, which checks the channel's rule for that person), downloads, verifies and installs the build. 2. When the person chooses a farm where they hold farm.sync_clients.manage, it registers the farm's sync client, issues its enrolment code (POST /organizations/{organization_id}/sync-clients, POST /sync-clients/{client_id}/enrolment-codes of Sync) and writes the hand-over bundle with that code, encrypted with DPAPI for the Windows user, as the bridge of the legacy move does. 3. It then revokes the person's refresh token and keeps no token of theirs. At its first start the client finds the bundle, redeems the code with a key it makes itself and is connected; the person is asked to sign in again only to change an integration.

    A person who installs without choosing a farm gets the client unconnected, and the client signs them in itself when they connect it. - An installed client keeps its own windows, including how it shows an available update; the installer and the library decide nothing a client should own.