The last six C-FFI integrations in the OxiRS dependency tree just got quarantined — and every published crate still builds 100% Pure Rust under --all-features.
Today we released OxiRS 0.3.2 — a maintenance-and-purity release for the Rust-native Semantic Web / SPARQL 1.2 / GraphQL platform that extracts every remaining C-FFI integration into opt-in adapter crates, migrates GeoSPARQL’s SQLite backend onto a Pure-Rust engine, and hardens SHACL and the oxirs-wasm query engine.
No JVM. No rusqlite quietly linking C libsqlite3 into a published crate. No zstd-sys riding in transitively through tantivy, parquet, pulsar, or wasmtime. OxiRS stays the Rust-first replacement for Apache Jena + Fuseki — one dataset speaking both SPARQL 1.2 and GraphQL, every crate stand-alone, compiled to a single static binary or WASM module. With 0.3.2, cargo tree -i rusqlite and cargo tree -i zstd-sys both come back empty for every published crate’s --all-features build. The six integrations that still need real C (NVML, CUDA, GEOS, DuckDB, Kafka, Pulsar) haven’t disappeared — they’ve been quarantined into separate, opt-in, publish = false adapter crates that never touch the published Pure-Rust surface.
Why OxiRS 0.3.2 is a game changer
“Pure Rust” claims usually fall apart the moment you actually run cargo tree -i on a project’s optional features. A GPU-monitoring flag drags in nvml-wrapper. A geometry feature links libgeos. A time-series backend needs libduckdb. Once any of those ship inside the same crate that’s published to crates.io, the whole --all-features surface stops being auditable Rust — even for users who never touch the C-dependent feature.
OxiRS 0.3.2 ends that ambiguity for good:
- Six C-FFI integrations extracted, not deleted. NVML GPU monitoring, CUDA buffers/kernels, GEOS geometry relations, the DuckDB↔TSDB bridge, and the Kafka/Pulsar stream backends move into
oxirs-gpu-monitor,oxirs-vec-adapter-cuda,oxirs-geosparql-adapter-geos,oxirs-tsdb-adapter-duckdb,oxirs-stream-adapter-rdkafka, andoxirs-stream-adapter-pulsar— each API-compatible with the in-tree feature it replaces, eachpublish = falseso it never reaches crates.io as part of the main crate’s dependency graph. - GeoSPARQL’s
GeoPackagebackend is now Pure Rust. The SQLite storage layer migrated fromrusqlite(bundled Clibsqlite3) to the new OxiSQL engine (oxisql-core/oxisql-sqlite-compat), plus an explicitGeoPackage::checkpoint()for WAL flush. - The last transitive
zstd-sysis gone. A new internalcrates/zstd-shim, backed byoxiarc-zstdand wired in workspace-wide via[patch.crates-io], replaces the Czstdcrate for every transitive consumer — tantivy, parquet, pulsar, and wasmtime included. - SHACL gets subclass-aware targets. A reflexive+transitive
rdfs:subClassOfclosure meanssh:classand implicit-class targets now validate subclass instances, not just exact-type matches — and SPARQL-based and property-path SHACL targets execute for real against the store instead of returning stub results. oxirs-wasm’s query engine got faster and safer. Triple-pattern and property-path evaluation now runs off SPO/POS/OSP indexes instead of full scans, queries can declarePREFIX/BASEprologues, and a per-store solution budget fails an unselective join fast instead of running it to completion.
All of this lands at 45,034 tests passing with --all-features (44,344 on default features), zero compilation warnings across all 27 crates, and every .rs file still under 2,000 lines.
Technical Deep Dive: what’s new under the hood
1. The quarantine architecture. Each extracted adapter crate reuses the original in-tree types, so callers who need the real GPU/GEOS/DuckDB/Kafka/Pulsar backend add one extra dependency and keep the same API surface — while everyone who doesn’t need it gets a strictly smaller, 100% Pure-Rust dependency tree by default. The old feature flags (oxirs-core’s gpu, oxirs-vec’s cuda/gpu-full, oxirs-geosparql’s geos-backend, oxirs-tsdb’s duckdb, oxirs-stream’s kafka/pulsar) are gone outright — this is the one breaking change in the release.
2. OxiSQL arrives as a first consumer. oxisql-core/oxisql-sqlite-compat is a new Pure-Rust, SQLite-compatible engine, and GeoSPARQL’s GeoPackage backend is its first real-world consumer inside OxiRS — proof the replacement is a drop-in for rusqlite at the API level, not just at the dependency-tree level.
3. Subclass closure via Floyd–Warshall. SHACL’s new advanced_features::subclass_closure computes the reflexive+transitive rdfs:subClassOf relation as a boolean adjacency matrix. Once computed, sh:class targets and implicit-class targets check membership through that closure instead of exact rdf:type equality — a shape written against ex:Animal now correctly reaches individuals typed only as ex:Dog where ex:Dog rdfs:subClassOf ex:Animal.
4. Index-driven WASM queries. oxirs-wasm previously matched triple patterns and property paths by scanning every triple. 0.3.2 drives that evaluation off the store’s subject/predicate/object indexes instead, so a join costs a hash lookup per solution rather than a linear scan — and the new per-store solution budget (setSolutionBudget/clearSolutionBudget) lets a browser or edge deployment cap intermediate result size and fail fast rather than hang on an unselective join.
5. The dependency floor moves up again. SciRS2 0.5.0 → 0.6.0, oxiarc-* 0.3.3 → 0.3.5, oxicrypto/oxitls 0.1.1 → 0.2.0, kube 3.1 → 4.0 (optional k8s feature), and bytes → 1.12.0 closes CVE-2026-25541. lazy_static is gone workspace-wide in favor of once_cell, and num_cpus::get() is gone in favor of std::thread::available_parallelism().
Getting Started
As of 0.3.2, the oxirs CLI binary is intentionally kept off crates.io (publish = false) so it can optionally depend on the quarantine adapter crates above without pulling their C FFI onto a published surface. Build it from source:
git clone https://github.com/cool-japan/oxirs.git
cd oxirs
cargo install --path tools/oxirs
Then put it to work:
# Initialize a new knowledge graph
oxirs init mykg
# Import RDF data (persisted to mykg/data.nq)
oxirs import mykg data.ttl --format turtle
# Query it
oxirs query mykg "SELECT * WHERE { ?s ?p ?o } LIMIT 10"
# Serve it — SPARQL, GraphQL, and a Fuseki-style admin UI
oxirs serve mykg/oxirs.toml --port 3030
The other 25 OxiRS library crates remain normally published — cargo add oxirs-core for the RDF/SPARQL engine on its own. A shape written against a superclass now automatically covers its subclasses, thanks to the new subclass closure:
# shapes.ttl — targets ex:Animal via sh:class
ex:AnimalShape a sh:NodeShape ;
sh:targetClass ex:Animal ;
sh:property [ sh:path ex:name ; sh:minCount 1 ] .
# data.ttl — ex:Rex is only ever typed as ex:Dog, never ex:Animal directly
ex:Dog rdfs:subClassOf ex:Animal .
ex:Rex a ex:Dog .
Before 0.3.2, ex:Rex would silently skip AnimalShape because it isn’t rdf:type ex:Animal exactly. With the new subclass closure, it’s now correctly validated as an ex:Animal.
What’s New in 0.3.2
- Pure-Rust Policy v2 (breaking) — six C-FFI integrations (NVML, CUDA, GEOS, DuckDB, Kafka, Pulsar) extracted into opt-in
publish = falseadapter crates; the old in-tree feature flags are removed. - OxiSQL GeoPackage backend — GeoSPARQL’s SQLite layer migrated from
rusqliteto Pure-Rustoxisql-core/oxisql-sqlite-compat, plus explicit WAL checkpointing. - Pure-Rust
zstdshim —crates/zstd-shim(backed byoxiarc-zstd) removes the last transitivezstd-sysC dependency workspace-wide. - SHACL subclass-aware targets — reflexive+transitive
rdfs:subClassOfclosure; SPARQL-based and property-path SHACL targets now execute for real. oxirs-wasmengine hardening — index-driven pattern/property-path matching,PREFIX/BASEprologues, and a per-store solution budget.- GeoSPARQL geometry fixes — shapefile writer emits polygon holes; compressed-geometry round-tripping preserves holes and multi-part structure; WKT parser accepts optional Z/M coordinates.
oxirs-tdbdistributed transactions — sagas, 2PC, and 3PC participants run real registered callbacks against a WAL-backed transaction instead of simulating success.oxirs-gql/oxirs-chat/oxirs-federate/oxirs-stream— adaptive query batching, an activated ML-driven query planner, a real z-score anomaly detector, NATS message dispatch by type, and an MQTT 5.0 property codec replace prior stub paths.- Dependency refresh — SciRS2 0.6.0, OxiARC 0.3.5, OxiCrypto/OxiTLS 0.2.0; 45,034 tests; every file under 2,000 lines.
Tips
- Check your own
--all-featurestree. After upgrading, runcargo tree -i rusqliteandcargo tree -i zstd-sysagainst your own--all-featuresbuild — both should come back empty. That’s the migration, made checkable in your own project, not just ours. - Need the GPU/GEOS/DuckDB/Kafka/Pulsar backend? Add the matching adapter crate directly (
oxirs-vec-adapter-cuda,oxirs-geosparql-adapter-geos,oxirs-tsdb-adapter-duckdb,oxirs-stream-adapter-rdkafka,oxirs-stream-adapter-pulsar,oxirs-gpu-monitor) — the API is unchanged from the old in-tree feature, only the crate boundary moved. - Update CI that ran
cargo install oxirs. That command no longer resolves — the CLI ispublish = falseas of this release. Build from source withcargo install --path tools/oxirsinstead, or pull a prebuilt binary from GitHub Releases. - Write SHACL shapes against superclasses. With subclass closure in place, a single
sh:targetClasson a superclass now covers every subclass transitively — you no longer need one shape per concrete leaf type. - Tune the WASM solution budget for untrusted queries. If you’re exposing SPARQL to end users in a browser or edge deployment, call
setSolutionBudget()so a pathological join fails fast instead of pinning a tab’s CPU. - Re-check your
Cargo.lockafter thezstdpatch. The workspace-wide[patch.crates-io] zstd = ...shim is transparent to your code, but if you vendor or audit dependencies, expectzstdin your lockfile to resolve to the Pure-Rust shim, not the upstream C-backed crate.
This is the foundation
OxiRS is part of the COOLJAPAN ecosystem of Pure-Rust infrastructure, and 0.3.2 is the release where that principle extends all the way to the last stubborn C dependencies: SQLite and zstd. It rides on SciRS2 (now 0.6.0) for graph analytics and numerics, routes all compression through the OxiARC family (now including the new zstd-shim, pinned to 0.3.5), handles crypto and transport through OxiCrypto/OxiTLS (0.2.0), and now leans on OxiSQL for its first production SQLite-compatible storage backend. Alongside siblings like OxiZ (SMT) and OxiRAG, OxiRS gives you an end-to-end auditable, JVM-free, C-free path from bytes on disk to a reasoned SPARQL answer — with the handful of integrations that still need real C FFI cleanly quarantined behind an opt-in boundary instead of hiding inside a published crate.
Repository: https://github.com/cool-japan/oxirs
Star the repo if you want a knowledge graph whose entire published dependency tree you can read in Rust. The era of “pure” crates that quietly link C in an optional feature is over. Pure Rust Semantic Web is here — fast, safe, and sovereign.
— KitaSan at COOLJAPAN OÜ July 12, 2026