Rust implementation of the Pimdir standard: the store and the sync engine
This library is composed of 3 layers, the two upper ones feature-gated:
- Low-level I/O-free core: no_std-compatible schema, encodings, per-kind summaries and the five sync verbs as coroutines, usable anywhere (always built)
- Mid-level std client: the three profiles the standard names, reader, producer and owner, as handles running the statements against SQLite and the blob files, the owner running the verbs against a connector you provide (requires the
clientfeature, enabled by default) - High-level CLI: the
pimdirbinary, the operator tool over a store (requires theclifeature)
- One store for mail, contacts and calendars: a portable SQLite database plus a content-addressed blob directory, readable by any conformant pimdir implementation.
- Offline-first sync: five verbs, open, upgrade, mutate, sync and rekey, reconciling the store against IMAP, JMAP, CardDAV or CalDAV through a three-way merge, a push confirmed before local state moves.
- Several sources per item: one shared item and a base per source, so a change one server folded in reaches the others on their next sync with no cross-merge.
- Typed summaries: what a reader lists from without the body, one table per kind with the people an item names, derived the same way by every writer and checked against the format's vectors.
- Deduplicated bodies: each body is stored once by content hash, so a message filed in two mailboxes costs one copy and a body already held is linked without a download.
- Retention: an item every source dropped is kept, hidden and restorable until an explicit purge.
- Action queue: processes that do not own the store append actions the owner applies exactly once.
- Change feed: every row carries a stamp, so an index or a window folds what moved since it last looked.
- Three roles, three handles: one owner that writes, any number of producers that enqueue, any number of readers that take no lock.
- Operator CLI: inspect a store while a sync runs, read the trash, restore or purge, prune the queue, check consistency, collect what nothing references, dump the store.
- Conformance suite: the specification's sync and summary vectors run against the real store in the test suite.
Tip
io-pimdir is written in Rust and uses cargo features to gate each layer. The default feature set is declared in Cargo.toml or on docs.rs.
io-pimdir is the reference implementation of the pimdir standard: the owner store STORAGE.md specifies, with its reader and producer profiles, and the engine SYNC.md describes. This release implements pimdir draft-01: the canonical schema and statements of that text are vendored under spec/ byte for byte and generated into the crate at build time, the summaries follow Annex A, and the engine reproduces the sync vectors. The reference index of SEARCH.md is not implemented yet and will come in a later release.
A client that only lists a store, or only queues an action, needs the reader or the producer handle and nothing of the engine; the standard's GUIDE.md Β§1 says what each profile owes, and this crate's handles meet it.
Install the pimdir binary from crates.io with cargo:
cargo install io-pimdir --locked --features cliTo use io-pimdir as a library, add it to your Cargo.toml: the cli feature is not part of the defaults, so a library consumer never compiles the binary or its terminal dependencies.
The pimdir binary is to a store what sqlite3 is to a database: an operator tool, not an end-user client. Reads open the store read-only, so inspecting a store mid-sync is always safe. A few real-world invocations:
pimdir -s ~/mail store info
pimdir -s ~/mail collection list
pimdir -s ~/mail item list INBOX --retained
pimdir -s ~/mail item restore 42
pimdir -s ~/mail item purge --older-than 90d
pimdir -s ~/mail queue list --parked
pimdir -s ~/mail checkRun pimdir --help for the full command tree and flags, add --json to any command for machine-readable output, and pimdir json-schema describes that output. The CLI contract lives in cairn/spec/cli.md. The whole library API is documented on docs.rs.
The tests demonstrate real usage: ./tests runs every verb against a store, and tests/vectors_sync.rs is a complete connector over the specification's vectors.
This project is licensed under either of:
- Chat on Matrix
- News on Mastodon or RSS
- Mail at [email protected]
Special thanks to the NLnet foundation and the European Commission that have been financially supporting the project for years:
- 2022 β 2023: NGI Assure
- 2023 β 2024: NGI Zero Entrust
- 2024 β 2026: NGI Zero Core
- 2026 β 2027: NGI Zero Commons Fund
This program is part of Pimalaya, free software funded entirely by grants and donations. If you find it useful, consider sponsoring its development:
