Workspaces
A workspace is a named draft of the store design (ADR 0027 §3). The builder's own draft is the workspace main; every agent and developer workspace is a separate row beside it: same bundle format, same validation, different identity. Design work by agents happens only in their own workspace: an Ajan token is bound to exactly one, and a write to main is refused with 403 agent_workspace_only.
The draft model
workspaces.list: every workspace with its kind, status, draft rev and sandbox state.workspaces.create: creates one; for kindagentit also mints the bound Ajan token (returned once). At mostworkspacesPerStoreper store; idle workspaces archive afterworkspaceIdleArchiveDaysdays.- Every draft route takes
?workspace=(defaultmain):design.draft.get,design.draft.put,design.draft.delete,design.draftFromTemplate.
Draft writes are whole-draft compare-and-swap: PUT carries expectedRev, and a mismatch is HTTP 409 with the current state in the body: {rev, hash, updatedAt, updatedBy}. On 409, re-read the draft, redo your edit on top of the new body, and PUT again with the new rev. The server never merges: there is no three-way merge endpoint, no "force" flag, and a lost race is always resolved client-side. Through the CLI the same contract surfaces as push exiting 4 on conflict.
Workspace writes carry the workspace agent policy: they execute directly for every token kind (no proposal is recorded) because a workspace draft changes nothing live. The proposal boundary sits at publish, not at draft edits.
Stable preview URL
design.previewUrl.get with ?workspace=ws_… returns a signed link that follows the workspace's current draft: push again and the same URL shows the new state (a lightweight poll reloads the open tab). With ?hash= instead, the link freezes one snapshot. Hand the workspace link to the owner once; it stays valid as you iterate. CLI: preview, or dev to watch, push on change and print it.
Builder always wins
The acceptance rule is literal: *builder open + agent edit + builder save = no data loss.* It holds structurally on the agent path: your workspace and the builder's main are different rows, so you can never overwrite an owner's unsaved work, and the owner's edits never appear in your draft mid-flight. Developer tokens writing main share the builder's CAS: on a 409 the builder rebases its own unsaved edits onto the new rev client-side; your job on a 409 is the same: rebase your edit, never expect the server to reconcile.
Adopt is owner-side ("Taslağa al")
Getting workspace work into the builder's draft is the owner's click, not your call: workspaces.adopt (POST /v1/workspaces/{ws}/adopt) copies the workspace body into main under expectedMainRev CAS: a copy, never a merge; the builder's unsaved state guards itself with the rev check. The owner does this from the panel after looking at your preview. From there, publishing to the live store is a separate owner decision (design.publish: owner policy; an agent's publish intent travels as a proposal design item, which re-checks the workspace hash and the live sequence before running).
Deleting your draft (design.draft.delete) also takes expectedRev: the same CAS discipline applies to discarding as to writing.
Hosted sandboxes (P1.5, platform-managed since ZA1)
A hosted workspace is an isolated container Mozaik prepares: the store opened as a project tree under /workspace/store, the pinned mozaik CLI of the exact platform build, AGENTS.md and .mcp.json: nothing to install, nothing to version-match. Since ZA1 (ADR 0028) hosted sandboxes are provisioned by the platform for the store's Zeki Asistan: workspaces.create refuses hosted: true; the routes below still drive any hosted workspace a token is bound to. No agent process runs inside; you drive it remotely:
workspaces.exec: run one command (cwd defaults to/workspace/store; timeout up toexecTimeoutMaxMsms, defaultexecTimeoutDefaultMs; stdout/stderr capped atexecOutputMaxBytesbytes). The pinned CLI is on PATH:mozaik status,mozaik push,mozaik propose.workspaces.files.list/workspaces.files.read/workspaces.files.write: file access confined to/workspace(≤workspaceFileMaxBytesbytes per file; base64 for binary).workspaces.backup: snapshot/workspace/storeto storage (backupTtlDays-day TTL). Backups also run automatically (debouncedbackupDebounceSecs after activity) and restore on the next cold start.workspaces.activity.list: the append-only feed of everything that ran (op, summary, exit code, duration). The store owner sees the same feed in the panel.workspaces.preview: the workspace's stable draft preview URL (never wakes the container).
Lifecycle. The container sleeps after sandboxSleepAfterSec s idle and its filesystem is wiped on sleep: the platform is the source of truth; on the next call the sandbox restores your scratch backup and re-opens the store project. At most hostedAwakePerStore sandboxes per store run at once, with a awakeBudgetPerDaySec-second daily awake budget (HTTP 429 beyond either). Idle workspaces archive after workspaceIdleArchiveDays days.
Credentials. The container never stores a token: each call injects a propose-only, workspace-bound, 24-hour token as environment. Everything you run inside obeys the same rules as outside: mutations become proposals; publishing stays with the owner.
Internet access is *Kısıtlı* by default (the sandbox reaches only the Mozaik API and docs); *Açık* (unrestricted; separately priced in the future) becomes an assistant setting at ZA2. In both modes HTTP(S) egress transits Cloudflare's interception proxy: blocked hosts answer HTTP 520, TLS is re-signed by a platform CA the sandbox already trusts (NODE_EXTRA_CA_CERTS/SSL_CERT_FILE/CURL_CA_BUNDLE/GIT_SSL_CAINFO are pre-set: leave them in place), and non-HTTP protocols (ssh, raw TCP) are unavailable.
Staying current. Exec responses carry imageStale: true when the sandbox's image is older than the platform (the panel shows "Güncel değil"); the owner's Yenile rebuilds it on the current image: your files come back from the backup. An image below the platform's supported CLI floor is refused outright with HTTP 412 workspace_stale until refreshed.
CLI shorthands: mozaik workspace exec -- <cmd>, mozaik workspace logs, mozaik workspace preview.