JuiceFS Development acceptance preflight
JuiceFS Development acceptance preflight
The executable Development artifact is
verify/juicefs-development-e2e.sh.
It defaults to a dry run and accepts exactly https://api-dev.platinum.dev as
a target. Its local --preflight makes no network requests. Its guarded
--execute-development requires two explicit authorization sentinels,
dedicated 0600 organization/admin token files, an existing restorable org
override, exact CP/host identity inputs, and restores captured gates/fixtures
via trap. The second sentinel authorizes one canonical health-gated
Development host-agent workflow dispatch; it is never approximated by a raw
host restart call.
This is deliberate: Shared Volumes remain a gated Development capability, and an acceptance script must not become an accidental control-plane test writer.
First, inspect the no-network default:
verify/juicefs-development-e2e.shThen, with a local 0600 token file and identifiers supplied out of band, run the non-network preflight:
verify/juicefs-development-e2e.sh --preflightThe preflight requires a dedicated org_juicefs_e2e_* organization, exact
40-character Development CP SHA, two different host IDs, each host-agent SHA
and 64-character fingerprint, plus a pt-dev-juicefs-e2e-* bucket and the
formatted JuiceFS filesystem name as PT_JUICEFS_E2E_PREFIX. CE 1.4.1 writes
objects under that filesystem name; it does not honor an arbitrary path suffix
on the bucket URL. The runner matches that supplied physical namespace to the
verified bootstrap filesystem name without returning storage coordinates from
the control plane. Names containing cas or object are rejected so the test
cannot share CAS or object-FUSE storage. It validates that the TypeScript SDK,
Python SDK, CLI, and MCP sources are present, but it never prints or reads the
token beyond local file-type/mode checks.
The guarded run additionally requires a local, regular 0600
PT_JUICEFS_E2E_STORAGE_AUDIT_FILE and the dedicated Scaleway project UUID in
PT_JUICEFS_E2E_SCW_PROJECT_ID. The file is JSON consumed through one
O_NOFOLLOW descriptor by the read-only verifier helper, never sourced or
logged. It may be root-owned for automation or owned by the local operator
running the verifier; another account may not read it. It holds the dedicated
S3/IAM credential and expected project/bucket/filesystem identity plus one CAS
and one object-FUSE sibling probe prefix. Before any flag or organization grant
changes, the helper proves the IAM key's preferred-project bucket listing,
positive listing of the exact JuiceFS filesystem-name prefix, and 403 denial
for both sibling prefixes. Missing credentials or a non-0600 file is a hard
pre-gate failure, not a syntactic substitute for isolation proof.
The guarded Development run establishes these evidence boundaries in order:
- Read the public feature discovery document and prove JuiceFS is independently enabled from object-FUSE. Capture the exact deployed CP SHA and both host agent SHAs/fingerprints before any create operation.
- Create unique fixtures with curl, TypeScript SDK, Python SDK, CLI, and MCP.
Each JuiceFS lifecycle mutation uses one caller-generated
Idempotency-Keyreused only for that logical invocation/retry. The same clients exercise public Git project usage reconciliation once Git v1 is available. The MCP mutation response is parsed for its public durable operation and waited to terminal success; a queue command ID is never treated as completion. - Attach a volume RW from two distinct hosts and RO from a third reader; prove cross-host writes, RO denial, capacity/inode quota failures, quota-lowering behavior, checkpoint fork/restore, nonempty child-subpath isolation, traversal/encoded-separator rejection, and measured restart/failure recovery. It also verifies that guest environments contain no JuiceFS metadata/object credentials and cannot see the host-only system namespace. Checkpoint submission occurs while both RW attachments are active: the operation must quiesce/flush their markers and publish them in the fork. The verifier keeps one sequence-writing process alive in each RW guest, records an acknowledged cutoff immediately before the checkpoint request, and proves the fork contains every immutable entry through each cutoff. It then proves both original writers resume through the same guest mounts. The checkpoint barrier must retain the original two attachment IDs, positive attach epochs, mount paths and modes exactly: fsfreeze plus a host RO bind is a quiesce/resume transition, not detach/reattach. The verifier never POSTs a replacement attachment after a checkpoint, since that could hide a failed barrier behind a new transport identity. The runner checks mountpoints and checksums after restarting both fixtures.
- Trigger the canonical
/v1/admin/hosts/:id/rollworkflow dispatch and wait for its exact correlated GitHub Actions run ID, successful conclusion, and exact requested CP SHA. Only after that run started may a new host-agent registration generation with the caller-supplied agent SHA and existing JuiceFS fingerprint satisfy the roll proof. An ordinary heartbeat, an older successful workflow, a same-SHA process that did not restart, or a workflow run for another host cannot pass this check. It checks both mounted filesystems and checksums after the two rolls. - Require actual Git v1 capability and public workspace/status/diff/checkpoint
and merge routes. Guests may write project files but must not see
.git, a gitDir, or the canonical remote; public checkpoint stages/commits/pushes. The runner creates a second workspace from the first known head, then proves normal merge and a durable expected conflict, then reconciles the project’s separate logical byte/inode usage. A 202 Git read is retried as a bounded pending receipt and a 503 is retried as a bounded unavailable state; neither is content or an operation ID. The publicuncertainoperation state withmanual_required:true(and its bounded resolution) is surfaced immediately as a fenced acceptance failure rather than being hidden by polling. Missing Git v1 fails closed; it is not an optional skip. - Delete all dedicated fixtures and verify operation completion. Git workspaces
are deleted with
retention_days:0, then the runner waits for their actual purge before deleting the canonical project and its volume. Restore every feature gate to its captured initial state even after a failure. Cleanup has its own hard verdict: a successful functional run with any failed cleanup is still an overall failure, with all failed cleanup phases reported together.
The local Docker rig in infra/test/juicefs-rig
proves CE/FUSE behavior but cannot replace this host-enrollment, guest/virtiofs,
or public-client acceptance proof.
Observe-only logical-usage evidence
flags.juicefs_billing_evidence_enabled is a separate, default-off
Development flag. It additionally requires the existing Development-only
JuiceFS volume gate and explicit per-organization juicefsVolumes grant.
When enabled, a verified JuiceFS usage completion writes one replay-safe sample
and an internal outbox item. The sample records live logical bytes/inodes,
ready-checkpoint logical bytes/inodes, declared volume quota, and the separate
usage/quota drift fields. It is keyed by the opaque volume, organization,
source operation, monotonic reconciliation generation, and CP receipt time.
This is evidence only: it does not create a billing_events row, price
usage, mutate credits/wallets, measure sandbox rootfs, or treat object-store
allocation, cache occupancy, or a bucket listing as logical storage. Git
bare-repository dimensions remain unavailable until a separate verified
project-quota/status receipt exists; they are never guessed as zero. The Admin
JuiceFS health projection and Prometheus counters report only aggregate sample
and outbox state. A completed volume-delete receipt marks retained evidence as
cleanup-confirmed; it never deletes or settles it.