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>
97 lines
5.1 KiB
Markdown
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.
|