Files
clawstor/claw-store/Cargo.toml
T
Omar Sobh c678c08c76
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
Phase 6a: read-only FUSE mount over the blob store
First slice of Phase 6. Ships a minimal, feature-gated `claw-fuse`
binary that mounts the local blob store read-only as a POSIX
filesystem:

  <mount>/blobs/<blob-id-hex>   ← file, content = assembled blob
  <mount>/blobs/                ← dir, ls shows all blob-ids
  <mount>/                      ← dir, contains `blobs`

Lets an operator `tar -tvzf`, `md5sum`, or grep at a cached
tarball without wiring a client. Debug + audit tool for now;
warm-tier git-worktrees + write path come in later slices.

Feature-gated so my macOS dev box doesn't need macFUSE headers
to build the rest of the tree:
* Cargo.toml declares `[[bin]] name = "claw-fuse"` with
  `required-features = ["fuse"]`.
* Feature `fuse` pulls in `fuser = "0.15"`, target-restricted
  to `cfg(target_os = "linux")` — dep resolution never
  considers fuser on other platforms.
* `cargo build` (default) leaves claw-fuse out entirely.
  `cargo build --features fuse --bin claw-fuse` on Linux builds it.

Design notes baked into the impl:
* Inode allocation is lazy — first `lookup` for a hex assigns an
  inode. Avoids pre-indexing the full blob store at mount time
  which would be O(blobs) fs walk before FUSE is even ready.
* getattr / read validate that the manifest exists on every
  call — no stale-inode reads if a blob is GC'd out from under
  us mid-mount. Extra read cost is negligible against the
  per-request FUSE overhead.
* size = manifest.total_size (bytes reported without touching
  chunk files) so `ls -l` is cheap.
* runtime = current-thread tokio, block_on per callback. fuser
  is sync; a full tokio worker pool would just add scheduling
  overhead when callbacks are already serialized by the kernel.

No new tests here — Filesystem impls are integration-heavy and
the underlying BlobStore methods are already covered. The
`fuse` feature build itself will be smoke-tested on tank.

381 tests pass unchanged (feature-gated bin doesn't affect the
existing test surface).
2026-07-14 12:13:59 -07:00

103 lines
4.3 KiB
TOML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[package]
name = "claw-store"
version = "0.3.0"
edition = "2021"
[[bin]]
name = "claw-store"
path = "src/main.rs"
# Phase 5b: fingerprint-keyed cargo build cache CLI. Wraps `cargo build`
# with a peer-cache lookup: hit → download+restore, miss → build+capture+upload.
# Uses the same identity/config surface as claw-store daemon.
[[bin]]
name = "claw-cargo"
path = "src/claw_cargo.rs"
# Phase 6 (2026-07-14): read-only FUSE mount that exposes the blob
# store as a filesystem. Gated behind the `fuse` cargo feature +
# Linux-only in dep resolution so my macOS dev box doesn't need
# macFUSE headers installed to build the other bins.
#
# Build with: cargo build --features fuse --bin claw-fuse
[[bin]]
name = "claw-fuse"
path = "src/claw_fuse.rs"
required-features = ["fuse"]
[features]
default = []
# Phase 6: enables the claw-fuse binary + pulls in the fuser dep.
fuse = ["dep:fuser"]
[target.'cfg(target_os = "linux")'.dependencies]
# v0.15 — Rust FUSE bindings. Only pulled on Linux + only when
# the `fuse` feature is on; keeps macOS + non-fuse builds clean.
fuser = { version = "0.15", optional = true }
[dependencies]
clap = { version = "4", features = ["derive", "env"] }
serde = { version = "1", features = ["derive"] }
toml = "0.8"
tokio = { version = "1", features = ["full"] }
sysinfo = "0.30"
anyhow = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
chrono = { version = "0.4", features = ["serde"] }
axum = { version = "0.7", features = ["macros"] }
tower-http = { version = "0.5", features = ["cors", "fs"] }
tokio-stream = "0.1"
serde_json = "1"
# v0.2.0 — flock(2) wrapper for atomic+locked manifest writes
# (manifest.rs). Already a transitive dep; declaring it directly
# makes the call site obvious.
libc = "0.2"
# v0.2.0 — sibling-tempfile + rename for atomic manifest persistence.
# Was previously dev-dep only; promoted to main.
tempfile = "3"
# v0.11.1 — cluster membership via scuttlebutt gossip + phi-accrual failure
# detection. Wraps in cluster/gossip.rs. UDP transport, keyed KV state per
# node, seed_nodes bootstrap from [[cluster.peers]] config.
chitchat = "0.11"
# v0.11 — QUIC transport for peer RPC (Phase 1c). UDP-based; runs on a
# separate port from chitchat gossip. TLS 1.3 by default; we wire mTLS
# against a fleet root CA in cluster/transport.rs.
quinn = { version = "0.11", default-features = false, features = ["runtime-tokio", "rustls-ring"] }
# v0.23 — TLS 1.3 provider driving quinn's crypto. Pinned to the ring
# provider so a single CryptoProvider is installed process-wide.
rustls = { version = "0.23", default-features = false, features = ["ring"] }
# v0.13 — X.509 cert generation for the fleet CA + per-node leaf certs.
# Used both by production bootstrap (writes PEM to /etc/claw-store/tls/)
# and by tests (in-memory ephemeral CA).
rcgen = { version = "0.13", features = ["pem", "x509-parser"] }
# v2 — parse PEM files into DER for rustls consumption. Used in
# NodeIdentity::from_pem_files (Phase 1d) so persistent identity round-trips
# through the file system on daemon restart.
rustls-pemfile = "2"
# v1 — content-addressed hashing for the Phase 2 blob store. BLAKE3 is
# used both for whole-blob addressing (BlobId) and for per-chunk
# addressing (dedup). Fast enough that a full-blob rehash on read
# verification stays cheap.
blake3 = "1"
# v0.4 — tar archive writer/reader for the Phase 5 build-artifact
# capture flow (cargo target/deps → tar → BlobPutStream). Preserves
# file metadata (mtimes, perms) which cargo relies on for its own
# incremental-rebuild fingerprint checks.
tar = "0.4"
# v0.13 — zstd wrapping around the tar stream. Level 3 is the default;
# gets 5-10× compression on cargo .rlib without noticeable CPU cost.
zstd = "0.13"
# v0.12 — HTTP client for the Phase 7f Gitea live-refs adapter.
# `rustls-tls` reuses the same rustls stack already pulled in by
# quinn — no additional TLS impls in the binary. `json` unlocks
# serde parsing of the /branches + /tags responses without a
# hand-rolled decoder. `default-features=false` drops native-tls
# and the openssl dep chain we don't need.
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] }
[dev-dependencies]
tempfile = "3"
tower = { version = "0.5", features = ["util"] }
http-body-util = "0.1"