A storage layer that everything else depends on cannot itself depend on something built on top of it.
Today we’re releasing OxiStore 0.3.0 — a minor version jump (0.2.1 → 0.3.0, since 0.2.1 itself was never published to crates.io) that closes out a structural debt: oxistore-cache no longer depends on oxisql-core. The oxistore ⇄ oxisql circular dependency that has been quietly tolerated since the sql cache feature was added is gone, for good, from the published crates.io graph.
No RocksDB. No LevelDB. No LMDB. No FFI. No -sys crates. cargo build --workspace --no-default-features still produces a working KV store in a fresh rust:slim container with no C toolchain in sight — that guarantee doesn’t change across a version bump, only strengthens.
Why this is a minor release, not a patch
The last version actually published to crates.io was oxistore-cache 0.2.0, and it still exposed the sql feature — SqlQueryCache, SqlPlanCache, CachedQueryRunner — pulling oxisql-core straight into oxistore-cache. That’s backwards: oxisql is supposed to sit on top of oxistore, not feed back into it. Every time oxisql-core cut a release, it risked round-tripping straight back into oxistore-cache’s own dependency tree.
0.3.0 ends that:
oxistore-cache’ssqlfeature andsrc/sql_cache.rs(698 lines) are removed outright. That’s a breaking removal against the last published API — hence semver-minor, not patch.- The equivalent functionality now lives in a new
oxisql-cachecrate inside theoxisqlrepo, which depends onoxistore-cache— not the reverse. The dependency arrow now points one direction, permanently. - A new
publish = falseworkspace member,oxistore-interop-tests, now hosts every cross-workspaceoxisqlintegration test that used to live scattered acrossoxistore-kv-redb,oxistore-kv-sled,oxistore-kv-fjall,oxistore-blob, andoxistore-encrypt. No publishableoxistorecrate depends on anyoxisql-*crate anymore — the coupling only exists in a dev-only, unpublished test harness.
What else shipped
Envelope encryption gets transactions and snapshots. EncryptedKvEnvelope<S> — the envelope-encryption decorator — now implements KvTxn and KvSnapshot via the new EnvelopeTxn / EnvelopeSnapshot types: raw-key AAD, read-your-writes semantics, delegated commit/rollback, and point-in-time snapshots. This brings envelope encryption to parity with the cell-level EncryptedKv decorator, which already had this coverage.
A PKCS#11 bridge for HSM-backed keys. Pkcs11KeyProvider is a new KeyProvider implementation behind the opt-in oxicrypto-pkcs11 feature, pulling oxicrypto-adapter-pkcs11 from crates.io — not a path dependency, so no upward coupling is reintroduced. It’s extractable-keys-only (the module doc is upfront about the honest limitation on non-extractable HSM keys), and because the feature is off by default, the default build stays 100% Pure Rust: cryptoki/cryptoki-sys load PKCS#11 modules dynamically via libloading, with no link-time C toolchain requirement even when the feature is on.
TTL consistency, finished. Across all three KV backends (redb, sled, fjall), a TTL-less write through batch_write, a committed transaction put, or compare_and_swap now correctly clears any stale TTL sidecar entry left by an earlier put_with_ttl/expire call — previously only the plain put() path did this. delete/batch_delete clear sidecar entries too, so ttl() can’t report an expiry for a key that no longer exists. oxistore-kv-fjall also caught up on read-path TTL: range/prefix_scan/count/iter/keys now honor expiry, and FjallTxn/FjallSnap gained a captured_at_millis field for a point-in-time-consistent view.
Real bugs in the cloud blob backends, fixed. oxistore-blob-s3 and oxistore-blob-azure now percent-encode object/blob keys per path segment instead of interpolating them raw into the URL — a key containing a space, #, ?, or non-ASCII character no longer produces a malformed request or (for Azure) silently targets the wrong blob. S3’s SigV4 signing settings were also corrected: single-encoding mode (matching the now-single-encoded path), disabled URI normalization (so legitimate // or /./ sequences in keys survive), and x-amz-content-sha256 is now actually sent for header-based signing, which real AWS S3 requires and which MinIO/mock servers had been silently tolerating its absence on.
Fuzzing, for real. Four new cargo-fuzz targets over the untrusted-bytes parsers — envelope_decrypt and cell_decrypt in oxistore-encrypt, s3_error_xml in oxistore-blob-s3, azure_list_response_xml in oxistore-blob-azure — each with a checked-in seeds/ corpus of well-formed inputs. All four ran clean across roughly 3M executions under ASan + libFuzzer before this release.
Runnable examples everywhere. All 12 member crates that previously had none now ship an examples/ directory — only the oxistore facade crate had examples before 0.3.0.
Getting Started
cargo add oxistore
[dependencies]
oxistore = "0.3"
use oxistore::{open, KvStore};
let store = open("/tmp/my-store").expect("open failed");
store.put(b"hello", b"world").expect("put failed");
let val = store.get(b"hello").expect("get failed");
assert_eq!(val.as_deref(), Some(b"world".as_ref()));
Default features get you the redb B-tree backend — single-file, ACID, zero native dependencies. 949 tests passing (4 skipped) across 13 publishable crates.
Tips
- Upgrading from
oxistore-cache0.2.0 with thesqlfeature enabled? That feature is gone. Pull in the newoxisql-cachecrate from theoxisqlrepo instead — same functionality, correct dependency direction. - Encrypting a store you also transact against?
EncryptedKvEnvelope<S>now supportsbegin_txn/snapshotdirectly — no need to drop down to the unencrypted backend for transactional semantics. - Bringing your own HSM? Enable
oxicrypto-pkcs11and construct aPkcs11KeyProvider— but check the module docs first if your keys are marked non-extractable; that path isn’t covered yet. - Storing keys with special characters in S3 or Azure? Just upgrade — the percent-encoding fix in 0.3.0 handles spaces,
#,?, and non-ASCII bytes in object/blob keys correctly now, no workaround needed on your end. - Want to see the new interop test harness? Check
oxistore-interop-tests(publish = false) if you’re contributing — it’s now the single place cross-workspaceoxisqlintegration tests live, socargo test --workspacestill exercises the full contract without polluting the published crates’ dependency graphs.
This is the foundation
OxiStore is part of NoFFI — the COOLJAPAN initiative to replace every C/C++/Fortran/-sys FFI dependency in the Rust world with a clean, memory-safe, 100% Pure Rust implementation. It depends on oxicrypto (encryption-at-rest, now with the PKCS#11 bridge), oxiarc (compression + Parquet codec), oxitls (cloud blob TLS, never ring), and oxihttp (cloud HTTP client). In turn it underpins oxisql (SQL atop KV + columnar — now the correct direction), oxirs (RDF triplestore), oxionnx (model cache), oximedia (asset blob storage), oxigeo (geospatial state backend), and oxify (session and object storage).
Repository: https://github.com/cool-japan/oxistore
Star the repo ⭐ if you want a storage layer that stays a layer — never quietly depending on the things built on top of it.
Pure Rust storage — sovereign, safe, acyclic, and FFI-free.
— KitaSan at COOLJAPAN OÜ August 7, 2026