pantheca

A family of small, composable storage substrates.

Four layers published pantheca.org

The pantheca substrate family is a set of small, composable storage layers named in the Greek -theca register (θήκη: case, repository). Each layer answers one question; layers compose into a stack. The family is designed so a consumer picks the lowest layer that supplies what it needs and ignores the rest.

Two substrate layers are published at v1.0 RC (apotheca at RC3, syntheca at RC1); the metadata layer is published at v0.2, and the first domain layer above it at v0.1.

apotheca — named write-once store

apotheca is a named write-once store. The caller chooses the name; bytes go in under that name, come out under that name, and are never overwritten. A second, disjoint pinax namespace alongside it holds compare-and-swap (name, bytes) pairs for state pointers and history heads.

One cella, multi-backend composition (local FS, S3-compatible, scp/sftp, CDN-fronted), one-way sync, with a flexible local store decoupled from how remote backends organise the same names. Bucket-agnostic; consumers decide naming policy. The reference Rust implementation is on crates.io as apotheca (binary apo).

syntheca — content-addressable storage

syntheca is content-addressable storage, implemented as a thin layer above apotheca. Names are derived from the bytes by a fixed hash (BLAKE3); collision is treated as benign dedup. The underlying cella's pinax namespace is surfaced verbatim as a transparent pass-through, so consumers holding a single Cella handle can store both content-addressed bytes and mutable head pointers without juggling two cellae.

Reference Rust implementation on crates.io as syntheca (binary syn).

metatheca — paths, facts, and history

metatheca is a path-and-fact layer over one syntheca cella: stable entry identities, human-meaningful paths, append-only structured facts, and a single-pointer head model for state and history. It transforms a content-addressable cella into a navigable, historied vault. The reference Rust implementation is on crates.io as metatheca.

metatheca also reserves an ext/ subtree for derived-view extensions, each in its own cella and fully reindexable from the vault: logopsis (lexical search, BM25), semopsis (semantic search, IVF-flat), taxopsis (typed predicate retrieval — exact equality, prefix, and range filters over fact-derived field values), dendropsis (structural decomposition, tree diff and move detection), and zetetes (hybrid-query coordinator over the two search extensions).

audiotheca — a music library on the stack

audiotheca is the first domain layer over the family: a content-addressed music library on a metatheca vault, keeping audio (immutable originals), metadata (mutable facts), and artwork (immutable blobs) strictly apart. Editing a tag never touches a byte of audio; lower-bitrate copies are derived on demand, never durably stored. Reference Rust implementation on crates.io as audiotheca.

What the layering buys you

apotheca handles the bucket plumbing — the part every storage consumer needs and would otherwise reimplement: backend abstraction, atomicity, integrity (mandatory SHA-256), the enumerate-exclusion discipline that makes scp/sftp and CDN-fronted backends viable as first-class citizens, encryption-as-wrapper, write fan-out across remotes. syntheca then adds content-addressing as a small specialisation on top: hash the bytes, name = hash, treat collision as dedup. metatheca lifts the resulting blob store into meaning — identity, paths, structured metadata, history — and audiotheca shows the shape of a domain layer built on that: domain facts in the vault, domain blobs in the cella, nothing invented below.

Cross-cella dedup falls out of the layering automatically: any project that points two cellae at the same backend gets dedup with no special protocol. Consumers can compose private and shared backends per cella without coordinating across the codebase.

More to come

Additional layers and extensions are in development and will be published here as they mature. The family is open by design — the substrate primitives are general enough that other layers and other consumers can compose against them without coordinating.