Architecture
The conformance spine, honest capabilities, and composable decorators.
dumont is a stateless CLI: each invocation routes a URI to a backend and exits. The design rests on three ideas.
The package map
cmd/dumont CLI entrypoint
internal/cli/ cobra commands + cross-remote copy / walk / sync / remove helpers
internal/config/ config.yaml + env:/file:/keychain: credential resolver
pkg/vfs/ FileSystem/File interfaces, Caps, typed errors, paths, io/fs adapter
pkg/uri/ location parser + scheme → backend Router
pkg/conformance/ the behavioral contract every backend must pass
pkg/cache/ transparent metadata + content caching decorator
pkg/emulate/ read-modify-write decorator (random write over object stores)
pkg/archivefs/ shared read-only FS over a flat archive entry list
backend/ mem · local · s3 · bunnystorage · bunnystream · httpfs · zipfs · tarfs1. The conformance suite is the spine
One table-driven battery defines what "correct" means — write/read, stat &
mtime, readdir, mkdir, remove semantics, exclusive create, rename, random
read/write, path safety, context cancellation, and more. mem and local are
the reference implementations; every other backend is measured against the same
invariants. The suite is the executable definition of the filesystem contract.
2. Capabilities are honest
Every backend advertises a Caps struct:
type Caps struct {
RandomRead bool // opened files implement ReaderAtFile
RandomWrite bool // native random write — NOT emulated
Append bool // O_APPEND honored natively
Truncate bool // in-place truncate / O_TRUNC honored
AtomicRename bool // Rename is atomic
Directories bool // real directories vs. synthesized-from-prefix
MTime bool // reports meaningful modification time
CaseSensitive bool // names are case-sensitive
}The conformance suite cross-checks Caps against observed behavior — a backend
can't claim atomic rename or random write it doesn't actually have. An operation
a backend can't perform correctly returns ErrNotSupported; it is never
silently faked in a way that could corrupt data.
Inspect it at runtime:
dumont caps aws3. Behavior is composed, not baked in
Capabilities are added by wrapping a backend in decorators rather than complicating the backend itself:
pkg/cache— a transparent metadata + content cache that cuts repeated listing and stat round-trips. Network remotes get it automatically.pkg/emulate(RMW) — read-modify-write random write, append, and in-place truncate over a whole-object backend. On a writable open it stages the object in a temporary local file, applies the writes, and re-uploads on Close/Sync. Correct but non-atomic andO(filesize), so it's opt-in viaemulate: true. If the wrapped backend already supports native random write, RMW passes writable opens straight through.
Not in scope
- A FUSE mount / daemon — dumont stays a stateless CLI. (The interfaces stay mount-ready for later.)
- Graph/API backends projected as a lossy tree (Gmail, Notion, Slack…). Bunny Stream is the one deliberate, clearly-labelled exception.
- Bidirectional / conflict-resolving sync —
syncis one-way by design.