# Version pinning The platform's rule is "no version mismatches, ever" (ADR 0027 §6) — enforced by construction, not convention: every surface an agent touches reports the same fingerprint, and a client below the floor is refused with instructions, never served stale answers. ## /v1/meta `GET https://api.mozaik-dev.com/v1/meta` ([`meta.get`](/reference/routes/meta.get), public) publishes the build identity: - `buildId` — the deployed git sha (every API response also carries it as `x-mozaik-build`). - `apiVersion` — the date of the last breaking wire change (`x-mozaik-api-version` on responses). - `commandsHash`, `routesHash`, `sectionsHash`, `manifestSchemaHash` and the combined **`registryHash`** — sha256 over the canonical JSON of the same registries this site renders. If your snapshot of the tool list or schemas was taken under a different `registryHash`, re-discover before trusting it. - `minCli` / `latestCli` / `cliPackage` — the CLI floor and current release. - `projectFormat` — the store-as-project tree format the platform can read. One CI pipeline publishes the CLI, deploys the API and builds these docs from the same commit, so `meta.buildId` and the docs agree by construction. CLI: [`meta`](/reference/cli). ## X-Mozaik-Client and 426 The CLI and Dev MCP send `X-Mozaik-Client: mozaik-cli/` on every request. A version below `minCli` is answered **HTTP 426** `client_too_old` with the exact upgrade command; an `X-Mozaik-Project-Format` above the platform's is 426 `project_format_unsupported`. The refusal is uniform across surfaces: - HTTP: status 426, body carries the upgrade line. - CLI: exit code **3**, upgrade command printed. - MCP: `initialize` answers JSON-RPC error **-32001** `client_too_old` with `npm i -g @mozaik/cli@latest`-style instructions. Clients that do not identify as our CLI (third-party MCP clients, curl, the admin panel) are never refused for lacking a version header — the floor guards our own pinned tooling, not the open API. ## The project pin A store project ([`open`](/reference/cli)) pins everything it depends on: - `mozaik.json` — `format` (the tree format) plus store and workspace identity. No secrets, ever. - `.mozaik/base.lock` — last-sync state: platform `buildId`/`apiVersion`/`registryHash`, the draft rev/hash it synced from, live seq, file hashes. [`status`](/reference/cli) compares it against the server and reports drift. - `package.json` / `.mcp.json` — an **exact** `@mozaik/cli` version, so the MCP servers an editor launches match the tree they sit in. Proposals record the `registry_hash` they were recorded under; the review UI shows a "Platform güncellendi" badge when the platform moved after recording. ## Upgrading [`upgrade`](/reference/cli) is the single, explicit move: re-pin the project to the current platform build (package.json, `.mcp.json`, lock) and regenerate what the format needs. Nothing self-updates: there is no background CLI update, no auto `pull --force`, no server-side migration of your tree. When you see a 426, the loop is: `npm i -g @mozaik/cli` → `mozaik upgrade` → continue where you left off.