PLATINUM DOCS

JuiceFS public-client parity

JuiceFS public-client parity

JuiceFS is an independently gated Shared Volume driver. Discover it from GET /v1/auth/me at features.juicefsVolumesEnabled; do not infer it from sharedVolumesEnabled. When the global gate is off, the public OpenAPI document omits the JuiceFS-only operation/reconciliation namespaces and does not advertise driver: juicefs.

Durable lifecycle contract

Create a JuiceFS volume with type: "shared", driver: "juicefs", a byte quota (size_gb), and the required logical inode quota (inode_quota). The public volume projection reports logical bytes/inodes, reconciliation drift, last reconciliation time, generation, and the write-lock state.

JuiceFS lifecycle mutations require Idempotency-Key; a missing key is a 400 with code: "idempotency_key_required". The caller creates and durably persists one key before transport I/O, reuses it only to recover that same request after a lost response, and never reuses it for a changed operation. The public SDKs, CLI, and MCP never generate a process-local fallback because it would be lost across a restart or disconnected tool invocation.

The lifecycle endpoints return durable asynchronous operations where relevant. Read one at GET /v1/volume-operations/{id}?wait_ms=0..5000; terminal states are succeeded, failed, and cancelled. Client-side wait helpers are bounded and only poll — they never submit the mutation again.

SurfaceJuiceFS operations
TypeScript SDKvolumes.create, resize, attach, detach, delete, usage.reconcile, snapshots.create/restore/delete, operations.get/wait
Python SDKSync and AsyncPlatinum mirrors: volumes.create, resize, attach, detach, delete, reconcile_usage, snapshot methods, get_operation/wait_operation
CLIpt volume create --driver juicefs --inode-quota ... [--idempotency-key ...] [--wait]; usage reconcile; operations get/wait; snapshots and checkpoints aliases, including restore-fork wait
MCPvolume_create, lifecycle/attach tools, checkpoint/restore tools, volume_usage_reconcile, and volume_operation_get/wait

Checkpoint creation requires the driver’s writer-safety conditions. Restoring a JuiceFS checkpoint is fork-only: it returns an asynchronous operation and a target_volume_id; it never overwrites the source volume.

Direct files and Git

The volume file API is object-FUSE only. MCP preflights the volume driver and refuses direct-file tools unless it is explicitly object_fuse; JuiceFS uses its POSIX mount workflow instead. This avoids translating POSIX paths into object operations.

Git workspaces are a second, independently discovered JuiceFS capability: features.juicefsGitWorkspacesEnabled. When disabled, Git paths and models are omitted from OpenAPI. When enabled, the SDKs mirror projects, workspaces, status/diff/log/branches, checkpoints, restore, delete, merge, and POST /v1/git-projects/{projectId}/usage/reconcile. CLI commands are under pt volume git; MCP mirrors them as volume_git_* tools. Every Git mutation uses the same idempotency-key rule as volume lifecycle mutations.

The four Git read endpoints return content only on 200. A bounded host-read timeout or failure is a retryable 503, not a 202 receipt: there is no public command identifier or polling token. TypeScript and Python raise their normal typed 5xx error; CLI and MCP surface the same error. Callers may retry the same read endpoint with their own bounded policy. Public clients never accept or return a repository path, remote URL, gitdir, credential, or storage coordinate.

Advisory locks do not cross the guest boundary

Measured on two hosts, 2026-09-02.

flock and fcntl coordinate correctly between hosts when taken directly on the JuiceFS mount: one host holds the lock and the other blocks until it is released (flock -w 3 exits 1). Run the same test from inside two sandboxes on those same two hosts and both acquire the lock immediately.

host level   allen-metal holds -> jang blocked        exit=1   correct
guest level  sandbox A holds   -> sandbox B acquires  exit=0   unprotected

The holder's grip was evidenced, not assumed: it writes a flag file from inside the critical section, and that flag is present when the peer succeeds.

So the gap is not JuiceFS. The virtio-fs export does not carry guest lock operations through to the backing filesystem, and each sandbox gets its own virtiofsd, so their lock state is unrelated. Two sandboxes that both take an advisory lock on the same file will both believe they hold it.

Consequence for callers. Do not rely on advisory locks for mutual exclusion between sandboxes. Coordinate through something that is genuinely shared — atomic rename(2), which is proven to work across hosts, or exclusive O_EXCL creation — or serialise the work outside the sandboxes. This is the same class of caveat as uncoordinated overlapping writes to one byte range, which are not merged; the difference is that locking looks like it works.

A checkpoint whose quiesce returns retryable never finishes

Measured on two hosts, 2026-09-02, with writers live on both.

POST /v1/volumes/:id/snapshots dispatched volume.juicefs_checkpoint_quiesce to the first host holding an RW attachment. The host completed it with status: retryable (juicefs_completion_receipt_uncertain), which apps/api/src/api/hosts.ts:2572 records with a finishedAt — terminal for the command. Nothing re-drives it: exactly one attempt was made, and fifteen minutes later the operation was still pending, manual_required: false.

host_commands   volume.juicefs_checkpoint_quiesce  attempts=1  status=retryable
operation       kind=checkpoint                    state=pending  manual_required=false

So an uncertain quiesce leaves the checkpoint hung with no terminal state and no operator signal — it is neither failed, nor uncertain, nor manual_required, and the remaining RW attachments are never quiesced.

It does fail safe: the volume stays fully readable and writable throughout on every attachment, writers are unaffected, and no fence is raised. The cost is a checkpoint that silently never happens.

Until a retry driver exists (or retryable escalates to manual_required after a bounded number of attempts), treat checkpoint completion as something to poll and alert on rather than assume.

A held attachment replay leaves the guest writing to its own disk

Measured on two hosts, 2026-09-02. This is the most serious behaviour found.

Restarting platinum-host-agent on a host carrying a live RW attachment:

agent   JuiceFS attachment replay held for sandbox sbx_...:
        JuiceFS desired attachment device cleanup is uncertain
host    virtiofsd count 1 — only the other volume's export was restarted
CP      volume_attachments: state=attached, detached_at=NULL   (unchanged)
guest   df -T /mnt/shared  ->  /dev/root

The agent's refusal is correct: it will not re-establish an export whose device cleanup it cannot prove. The damage is what happens around that refusal.

Inside the guest the virtio-fs mount simply disappears, and /mnt/shared reverts to being an ordinary directory on the sandbox's own root disk. Writes keep succeeding. They are no longer on the shared volume, no longer visible to any other sandbox, and are lost when the sandbox is discarded. The file written before the restart is still intact in the host-side export directory and still visible to peers on the other host — only this guest has silently diverged.

Reproduction, end to end:

before  A writes durable.bin, md5 cf0dfc6e…   B sees the same md5
restart both host agents
after   A: md5sum /mnt/shared/durable.bin -> No such file or directory
        B: md5sum /mnt/shared/durable.bin -> cf0dfc6e…   (unchanged)
        A: writes post.txt -> succeeds
        B: cat /mnt/shared/post.txt -> No such file or directory

Two independent gaps:

  1. The control plane is never told. The attachment stays attached with a null detached_at, so nothing reports degraded, nothing re-drives the replay, and a scheduler still treats the host as carrying that attachment.
  2. The guest keeps a writable path at the same location. A mountpoint whose backing export is gone should fail closed — the directory should not remain writable local storage under the volume's name.

Until both are addressed, treat a host-agent restart on a host with live JuiceFS attachments as requiring an explicit re-attach, and do not assume a successful write to a mount path means the data reached the volume.