Expand description
flint-lean: the checkout/publish syncer core (plan of record: docs/plans/flint-lean-plan.md v2).
Lean is a SEPARATE front end from the hub: no NFS, no daemon in the
data path. An agent pod gets a full local checkout on an emptyDir
(real ext4/APFS POSIX), and a syncer publishes snapshots to the
bucket through a barrier. Durability is RPO-shaped (the flush floor);
coherence is snapshot-level (the subtree manifest CAS is the atomic
commit point). This module reuses tier::store (ObjectStore,
GenerationStamps, conditional puts, the epoch cell) as a library and
deliberately does NOT reuse the hub’s flush/arbitration machinery —
the plan pins that: the hub’s 412 arbitration is LOCAL-WINS-overwrite
(tier/flush.rs), which is exactly wrong under HITL second writers.
The protocol here is the shipped shape lean/PROTOCOL.md writes out,
from its model lean/formal/LeanP1.tla (the shape since the
simplification of 2026-09-25: P1, P2, M1). PROTOCOL.md has every rule
with the invariant it holds up and the model world that fails without
it; the load-bearing ones, in brief:
- Every write lands at a fresh immutable handle
(
files/<path>@<flush>), and the pointer CAS is the only commit — a writer’s and the gateway’s alike. Nothing overwrites a handle. - The gateway commits each UI verb itself (P2): a save PUTs a fresh
handle, then ONE pointer CAS that lands only over the version the UI
read (else 412); a rename or a delete is one CAS. It never takes the
writers’ lease. The request cell (
inbox,.flint/lean/inbox) carries only the two verb requests, “please publish” and “please pull” — no entries, no removals, no window. - The barrier: consume (the cheap path: the scan trigger) → scan → upload → claim the lease → verify the uploads (R4a) → install, a three-way merge onto the CURRENT document with the baseline as the merge base (mine wins modify/modify; R7 records theirs; a delete over theirs applies, theirs kept, M3) → collect → finish (the baseline follows what landed).
- What a commit stops citing is retired, not deleted: logged at the CAS and reaped only once G old (M1), so a reader that loaded less than G ago can still fetch it. The orphan sweep runs only under the lease (R4b) and spares a save in flight (G3).
- Takeover rotation: a successor rewrites the document before serving, so a deposed holder’s pointer CAS 412s; the worker-facing verbs are epoch-validated per request.
- Restart matrix: marker present ⇒ never re-materialize (a re-checkout would resurrect unpublished deletes); reload the persisted baseline, rescan, self-recognize the lease via the persisted incarnation id (emptyDir-scoped — a replacement pod gets a fresh identity and takes the takeover path).
- Deletion basis: a path is delete-eligible only if absent in two consecutive scans AND present in our own baseline (the rename-vs-walk guard).
Re-exports§
pub use gauges::status_report;pub use gauges::Gauges;pub use gauges::StatusReport;
Modules§
- barrier
- The publish barrier (plan §2.1, seven steps) — the machine
lean/formal/LeanSubtree.tlachecks. Order is load-bearing: consume → scan → intent/window → uploads → manifest CAS (merge) → GC deletes LAST → baseline rewrite. - checkout
- Checkout + the restart matrix (plan §2.1).
- chunk
- Content-defined chunking of the manifest’s key stream
(
docs/plans/flint-lean-chunked-manifest-design.md§3). - chunkcache
- A local copy of manifest chunks, kept by content address (latency plan
2026-10-23, lever A:
docs/plans/flint-lean-latency-plan-2026-10-23.md). - conformance
- Does this store actually enforce the conditions lean writes under?
- control
- The
.flint/control namespace (boundary-verbs plan §2.0, D0/D11): the agent’s side of the file protocol. - docview
- A manifest document seen chunk by chunk (latency plan 2026-10-23, lever G, §12).
- gauges
.flint-sync/gauges.json— the Phase-3 observability minimum (§2.6; review ledger OF-6).- inbox
- The request cell: ONE CAS document per workspace carrying the two verb requests a party outside the pod can make (plan §2.5) — “please publish” and “please pull”.
- lease
- The subtree lease, held for ONE BARRIER’s commit section (design
2026-09-13,
docs/plans/flint-lean-writer-lease-and-gated-assessment.md§4), with a FIFO ticket so W writers wait at most W barriers. - manifest
- The lean subtree manifest: one JSON document, CAS-written, the atomic commit point every reader trusts (checkout, sync, DR).
- metrics
/metrics(D15, §8 Q5) — Prometheus exposition rendered from the SAME structgauges.jsonis written from.- news
- The news poll (latency plan 2026-10-23, lever B).
- reader
- Read access (per-user access design §4.4): the floor tick of a syncer that follows the workspace and never writes to the bucket.
- scan
- The barrier’s scan-diff (plan §2.1 step 2).
- sentinel
- The boundary verbs:
.flint/publishand.flint/sync(plan §2.1, §2.2 — D1, D2, D3, D3.1, D12). - state
- Durable emptyDir bookkeeping (plan §2.1 “restart matrix”).
- sync
- The sync verb (v1, HITL — decided §9 Q4), plus the scoped form the
.flint/syncsentinel invokes (boundary-verbs plan §2.2, D4). Harness- or sentinel-invoked, never background. - trace
- The protocol event trace (
FLINT_SYNC_EVENT_TRACE=1, orspec.eventTraceon a deployed workspace). - tracked
- Collections that remember which keys changed since they were loaded,
so the baseline persists what a save changed rather than the whole
document (lever D,
docs/plans/flint-lean-latency-plan-2026-10-23.md). - uds
- The UDS door (§2.5, Phase 5) —
.flint-sync/ctl.sock. - untracked
- Finding 10: an upload whose commit never came.
- verbs
- The one-shot verbs, and which of them holds the publish fence for its whole run.
Structs§
- Lean
Config - Syncer
- Everything a syncer operation needs: store + config + durable state.
Enums§
- Access
- What this syncer may do to the bucket (per-user access design §4.4).
- Lean
Error - Sentinel
Mode - Sentinel posture knob (D0.4).
auto= verbs on unless the pre-existing-.flint/pre-flight trips;forceaccepts consumption of pre-existing sentinel-named files.
Constants§
- CHUNK_
CACHE_ DIR - The chunk cache’s directory inside the state dir (
chunkcache). - CHUNK_
FETCH_ PARALLELISM - Chunk GETs a manifest load keeps in flight (
LeanConfig:: chunk_fetch_parallelism). A chunk is about 1 MiB, so this many is 16 MiB in flight; the bodies are all held until the document is assembled anyway, as they were when they were fetched one at a time. - CONTROL_
DIR - The workspace-local control namespace (boundary-verbs plan D0): the
agent’s side of the file protocol. Reserved exactly as the gateway
reserves
.flint/on the HTTP side (flint-lean-gateway’spath_ok) — the scan skips it,classifynever makes it delete-eligible, and checkout never materializes afiles/.flint/...citation into it. - EXIT_
REFUSED - Process exit code for
LeanError::Refused(sysexitsEX_CONFIG). Mirrored asSYNCER_EXIT_REFUSEDin the CSI node plugin, which does not depend on this crate; drill leg S22 is where the two are checked against each other. - LEAN_
DIR - Reserved control namespace inside the subtree prefix. Never scanned, never part of a checkout, never GC’d by the barrier.
- MAX_
FLUSH_ LEN - The longest flush id a handle carries: the gateway’s
ui-<secs>-<uuid>with au64of seconds (a barrier’s is a bare uuid; an ingress copy’s,ingress-<etag>, adopts an object whose bare key already fit). - MAX_
KEY_ BYTES - The longest key the stores lean runs on take: 1,024 bytes of UTF-8 on
S3 (
KeyTooLongError) and on GCS. - SENTINEL_
PROTOCOL - Protocol version advertised in
.flint/capabilities.json. - STATE_
DIR - The syncer’s durable bookkeeping directory inside the workspace (emptyDir-scoped: survives container restarts, dies with the pod).
- SYNCER_
VERSION - This binary’s version, echoed to the agent (
capabilities.json) and to the operator (the lease cell’s echo, §2.6). Both mixed-version holes — agent↔syncer and operator↔syncer — are detected by comparing what is RUNNING against what was asked for, and neither comparison exists without a version on the running side. - WHOLE_
PUT_ MAX - Default whole-object publish ceiling; larger files go through the
multipart compose path (
tier/flush.rsuses the same 64 MiB split).
Functions§
- now_
unix - Seconds since the epoch, saturating at 0 on a clock before it.
- ui_
flush - The gateway’s flush id for a UI write’s handle:
ui-<added_unix>-<uuid>. The time is the order a consume reads off two UI handles of one path (design 2026-09-19, R7’s “later”): a citation that moved to a LATER gateway write supersedes an entry, one that moved to an earlier one leaves it live. One gateway’s clock orders its own writes exactly; two replicas’ clocks are the residual, and a tie or an inversion between them costs a surfaced conflict, never a silent drop. - ui_
flush_ added - The
added_unixa UI flush id carries;Nonefor any other flush.