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, public) publishes the build identity:
buildId— the deployed git sha (every API response also carries it asx-mozaik-build).apiVersion— the date of the last breaking wire change (x-mozaik-api-versionon responses).commandsHash,routesHash,sectionsHash,manifestSchemaHashand the combinedregistryHash— 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 differentregistryHash, 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.
X-Mozaik-Client and 426
The CLI and Dev MCP send X-Mozaik-Client: mozaik-cli/<version> 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:
initializeanswers JSON-RPC error -32001client_too_oldwithnpm 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) 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: platformbuildId/apiVersion/registryHash, the draft rev/hash it synced from, live seq, file hashes.statuscompares it against the server and reports drift.package.json/.mcp.json— an exact@mozaik/cliversion, 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 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.