Files
Andy DixonandClaude 53968f8822 Docs for the Rust version; benchmarks; build.sh fixes
README, CLAUDE.md, man pages, the user guide and its screenshot script
now describe the Rust build and the intentional behaviour changes, which
docs/MIGRATION.md lists. Go and Rust micro-benchmarks for the same
operations, and scripts/bench.sh for end-to-end comparison. build.sh
exports its tree root to the per-target jobs and keeps logs out of the
output directory; riscv64 musl builds use getrandom's raw syscall
backend, since zig's musl getrandom never reaches the kernel there.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-08 11:50:55 +01:00

97 lines
5.1 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code when working with this repository.
## Overview
vault is a post-quantum encrypted file vault: one Rust package (`Cargo.toml`
at the root, toolchain pinned in `rust-toolchain.toml`) that builds a single
`vault` binary. The library (`src/lib.rs`) exists so tests and benchmarks can
reach the same code; `src/main.rs` only calls `cli::main`.
- `src/cli.rs` - commands and Go-`flag`-compatible parsing: `genkey`,
`init`, `add` (file, directory or URL), `migrate`, `mirror`, `absorb`,
`ls`/`list`, `get` (`-r`), `mv`/`cp` (`transfers` resolves names like
mv(1)), `rm` (`-r`, asks unless `-f`), `unlock`/`lock`, hidden `__agent`.
- `src/agent.rs` - the unlock agent: `unlock` re-executes the binary as
`__agent` (passphrase variables stripped, secret over a pipe); it hardens
itself (`platform::memory`) before reading the key, serves it on a Unix
socket in a 0700 per-user dir until a deadline (fixed or `--idle`).
Wire-compatible with the Go agent. Not available on Windows.
- `src/keyfile.rs` - key file: two Argon2id/XChaCha20-Poly1305 slots, decoy
or random bytes in the second, random order, both always tried.
- `src/crypto/` - `frodo.rs` (FrodoKEM-640-SHAKE ported from CIRCL v1.6.4),
`kem.rs` (hybrid suite 0x0001 with RustCrypto ml-kem, `Identity`),
`header.rs` (Fury header format), `fury.rs` (file encryption), `stream.rs`
(STREAM, including random access).
- `src/store/` - on-disk vault: `records/`, `objects/` sharded by ID prefix,
catalogue, add/remove/copy/extract, filler; `types.rs` holds the validated
types (`VaultName`, `Id`, `ObjectSeed`, `Record`) and record JSON.
- `src/pipeline.rs` - the one bounded worker pool and the eight reusable
object buffers; coordinators run on the caller's thread.
- `src/platform/` - all `unsafe` and OS specifics: `fs.rs` (no-clobber
publish, `Dir` confined extraction, epoch times, dir sync), `lock.rs`
(fcntl / LockFileEx / lock file), `memory.rs` (mlock, undumpable),
`term.rs` (prompts).
- `src/net/` - `add URL` and `mirror` with limits; `url.rs` (Go `net/url`
semantics), `html.rs` (tokenizer and link rewriting).
- `src/absorb.rs` - tar (optionally gzipped) from stdin, streamed in.
- `src/secret.rs`, `src/rng.rs`, `src/util.rs`, `src/error.rs` - secret
buffers, randomness (seeded only under `cfg(test)`), Go-compatible
parsing/printing helpers, the error type.
- `oracle/go` - the frozen Go implementation (test-only reference, see
`oracle/README.md`); `oracle/gen-vectors.sh` writes `tests/vectors`.
- `tests/` - CLI and interoperability tests against the real binaries;
`fuzz/` - cargo-fuzz targets; `benches/micro.rs` - micro-benchmarks.
- `docs/` - man pages, `COMPATIBILITY.md`, `MIGRATION.md`, `PLATFORMS.md`,
`BENCHMARKS.md`, and the LaTeX guide (`docs/guide`, `build-pdf.sh` via
Tectonic; `shots.py` re-shoots screenshots from the real binary). Keep
them in step with the CLI.
- `build.sh` - cross-builds every supported target (see `PLATFORMS.md`).
- `packaging/package.sh` builds and inspects dixon-vault packages locally;
`packaging/repo.sh [TAG]` signs and publishes them to repo.dixon.cx.
## Commands
```sh
cargo test --locked # needs go on PATH for interop tests
cargo clippy --locked --all-targets --all-features -- -D warnings
cargo fmt --check
cargo build --release --locked
./build.sh # all buildable targets, into ./dist
TARGETS="linux/amd64" ./build.sh # a subset
cargo deny --locked check # advisories and licences
(cd fuzz && cargo +nightly fuzz run header)
```
End-to-end check:
```sh
export VAULT_PASSPHRASE=test VAULT_KEY=$PWD/k VAULT_DIR=$PWD/s
target/release/vault genkey && target/release/vault init && target/release/vault add README.md docs && target/release/vault list
```
## Invariants
- The on-disk formats are frozen and shared with the Go version; check any
change against `docs/COMPATIBILITY.md` and the oracle vectors.
- Never write a seed or private key unencrypted (the agent gets it by pipe).
- Keep suite IDs, stanza tags, HKDF info strings and the 32-byte file key stable.
- Every ciphertext's and shard directory's mtime is pinned to the epoch;
records stay one fixed size; objects stay at most 4 MiB and bucket-padded.
These hide metadata from the storage host.
- An object's plaintext starts with its own ID, binding it to its record
and its position in the file.
- `get` publishes output only after every object has authenticated, with a
no-replace primitive; never fall back to check-then-rename.
- Decoy deniability: both key slots stay the same size and are both always
tried; `init` always writes filler; foreign records are skipped silently.
- Every command that changes the vault holds the exclusive lock (POSIX
fcntl locks, compatible with Go's).
- Crash-safe order: objects before records, new records before removing old
ones, record removal (synced) before object removal.
- Secrets live in `SecretArray`/`SecretVec`/`LockedBuf`: no Clone, Debug or
serialisation. Production randomness is the OS only.
- `unsafe` only in `src/platform`, each block with a SAFETY comment.
- Diagnostics go to standard error, lower-case, no trailing full stops.