COOLJAPAN
← All posts

OxiStore 0.3.0 — Breaking the OxiSQL Cycle, Envelope Transactions, and a PKCS#11 Bridge

OxiStore 0.3.0 is a minor release that structurally severs the oxistore ⇄ oxisql circular dependency, adds EnvelopeTxn/EnvelopeSnapshot for encrypted stores, ships a PKCS#11 HSM-backed KeyProvider, and fixes S3/Azure key percent-encoding bugs. Part of the NoFFI sovereign Rust stack — zero *-sys crates on default features.

release oxistore pure-rust cooljapan noffi storage key-value encryption pkcs11

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 oxistoreoxisql 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:

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

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

↑ Back to all posts