Namespaces and KV
A namespace is a versioned ordered map whose mutations are committed by a three-node OpenRaft group. KV, buckets, and filesystems build on the same revision, history, snapshot, rollback, and durability machinery.
Enable the service
[namespace]
enabled = true
consensus_enabled = trueAll three candidate nodes need namespace consensus enabled, sufficient advertised storage, and available namespace-group capacity. Replica placement considers failure domains and capacity. Namespace aliases are local metadata conveniences; the namespace ID is the durable identity.
Lifecycle and inspection
Namespace commands
namespace create --kind <KIND> [--alias NAME]Create a namespace on exactly three replicas. Use kind kv directly; bucket and filesystem have dedicated create commands.
namespace inspect <NAMESPACE>Show descriptor, current revision, root CID, and head commit CID.
namespace status <NAMESPACE>Show leader, term, log/application indexes, state, and quorum availability.
namespace replicas <NAMESPACE>List the three voter identities and Raft IDs.
namespace history <NAMESPACE>List immutable revisions and their roots/commits.
namespace diff <NAMESPACE> <A> <B>Compare two revisions; changed-key output is bounded.
namespace rollback <NAMESPACE> <REVISION> [--request-id ID]Create a new monotonic revision whose content matches an older revision.
KV reads and writes
pepper kv put <NAMESPACE> <KEY> --cid <CID> [--if-generation N] [--if-cid CID] [--request-id ID]
pepper kv put-file <NAMESPACE> <KEY> <PATH> [PRECONDITIONS]
pepper kv get <NAMESPACE> <KEY> [--revision N | --root CID | --checkpoint CID]
pepper kv delete <NAMESPACE> <KEY> [PRECONDITIONS]
pepper kv scan <NAMESPACE> [--prefix TEXT] [--limit N] [--cursor CURSOR] [--revision N]Normal reads are linearizable. Revision, root, and checkpoint selectors provide historical reads. Scan cursors are bound to the root that created them, so a cursor cannot silently continue against a different snapshot.
--if-generation and --if-cid provide optimistic concurrency. A mismatch is a stable generation-conflict error. --request-id makes an identical retry idempotent; reusing the same ID for a different intent is rejected.
Atomic transactions
{
"version": 1,
"base_revision": 4,
"base_root_cid": "cid://...",
"mutations": [
{"op":"put","key_hex":"616c706861","value_cid":"cid://...","value_kind":"object","metadata":{},"precondition":"absent"},
{"op":"delete","key_hex":"62657461","precondition":{"match":{"generation":2,"cid":"cid://..."}}}
],
"message": "atomic update"
}pepper kv txn apply <NAMESPACE> ./transaction.json [--request-id ID]The whole mutation list commits or conflicts as one revision. The transaction file must declare version 1; the CLI supplies the target namespace and generates missing request metadata.
Snapshots and retention
pepper namespace snapshot create <NAMESPACE> nightly [--revision N] [--request-id ID]
pepper namespace snapshot list <NAMESPACE>
pepper namespace snapshot delete <NAMESPACE> nightly [--request-id ID]Named snapshots retain a revision independently of the moving head. Rollback is also non-destructive: history remains immutable and the rollback appears as a new revision. Publication intents, staging leases, read leases, and synchronized pins prevent referenced DAGs from being collected while a write or retained read is live.
Failure behavior
- A quorum is required for linearizable reads and writes; any healthy ingress node routes work to the current leader.
- Referenced content must reach the required durability before its namespace mutation becomes visible.
- put-file retains its uploaded CID when the metadata mutation conflicts, and reports that CID so it can be reused or unpinned.
- Stable CLI exit categories distinguish conflicts (20), namespace/leader unavailability (21), durability failure (22), authorization (23), and invalid requests/cursors (24).