23a68a0710cf58989764b198ce5ad9dc6004d4d9
Adds pkg/vfs.Mount(*zip.App, cloud.Deps) error so the unified Hanzo
Cloud binary can blank-import and register VFS alongside every
other Hanzo subsystem.
VFS has no public HTTP surface today — it's an S3-backed virtual
block filesystem driven through FUSE/CLI/sidecar. Mount() exposes
liveness/readiness probes plus a minimal block-CRUD HTTP API so
co-resident subsystems can talk to VFS without falling back to the
CLI:
- GET /v1/vfs/health — always 200
- GET /v1/vfs/readyz — 200 only when an instance is
attached via vfs.SetInstance
- PUT /v1/vfs/blocks — payload upload
- GET /v1/vfs/blocks/:id — payload download
- DELETE /v1/vfs/blocks/:id — backend delete
- GET /v1/vfs/stats — cache/backend counters
cmd/vfsd is a HIP-0106 thin shim that wires backend + age keys from
env (VFSD_BACKEND, VFSD_AGE_KEY) and listens on cloud.Config.ListenAddr.
The existing cmd/vfs CLI (put/get/stats/mount) is untouched.
init() registers with cloud.Register("vfs", 20, …). schema/vfs.zap
adds the minimal Health + Block ZAP interface; full multi-block
File surface lands in follow-up PRs.
Tests:
- pkg/vfs: TestMount_HealthReadyz + TestMount_PutGetRoundtrip green
- existing TestRoundTrip + TestStats unchanged
vfs
S3-backed virtual block filesystem with PQ encryption — unlimited write storage for stateful services.
Quick start
# Build
make build
# Generate an age key (one-time)
go run filippo.io/age/cmd/age-keygen > /tmp/vfs.key
RECIPIENT=$(grep 'public key' /tmp/vfs.key | cut -d: -f2 | tr -d ' ')
# Put + get a block (file:// backend, dev only)
echo "hello world" > /tmp/in.txt
ID=$(./bin/vfs put /tmp/in.txt --backend file:///tmp/vfs-store --age-recipient "$RECIPIENT" --age-key /tmp/vfs.key)
echo "block: $ID"
./bin/vfs get "$ID" --backend file:///tmp/vfs-store --age-key /tmp/vfs.key
# Same flow against S3
./bin/vfs put /tmp/in.txt \
--backend "s3://my-bucket/vfs-prefix?region=us-east-1" \
--age-recipient "$RECIPIENT" \
--age-key /tmp/vfs.key
What it is
A 4 KiB block-level virtual filesystem that:
- Hashes every block with blake3-256 for content addressability + integrity.
- Encrypts every block with luxfi/age (X25519, optionally hybrid PQ via ML-KEM-768) before it touches the backend.
- Stores blocks as
blocks/<2-hex-shard>/<full-hash>.zap.ageon a pluggable backend (file://,s3://,gcs://(TODO),azureblob://(TODO)). - Caches recently-used blocks in an in-memory LRU (NVMe write-back cache lands in 0.2.0).
- Mounts as a FUSE filesystem (
make build-fuse; mount layer lands in 0.2.0).
Why
Stateful services in K8s usually pre-size a PVC and either over-provision or run out of disk. vfs lets a service write as if it has unlimited local NVMe — the hot tier is a configurable local cache, the cold tier is S3 (or any object store), and the PQ-encrypted blocks let the operator put cold pages in any region without leaking content.
Companion to hanzo/replicate — replicate streams SQLite WAL frames file-level; vfs does block-level for any file system.
See LLM.md for the full architecture, K8s sidecar pattern, encryption design, and roadmap.
License
Apache 2.0
Languages
Go
97.8%
ZAP
1.2%
Makefile
0.6%
Dockerfile
0.4%