- Rust 92.4%
- Python 4.1%
- HTML 1%
- JavaScript 1%
- RenderScript 0.6%
- Other 0.7%
Expose YAML-LD data controls for rules and node expressions Closes #1063 Rules and node-expr now accept --yamlld-input-options for primary IN only. Admit controls before data, rule, shapes, import or expression acquisition and pass the selected bytes through the existing native dataset loader. Both SHACL and SRL rule execution consume the configured primary graph. Check-only runs refuse the flag because no data is consumed. Protect the named options paths as argument documents. Preserve existing shapes, SRL, imports and expression policies, along with coordinates, selectors, bases, governors, reports and output serialization. Production CLI release check, strict release lint for the binary and shapes_tools_cli, both exact native CLI cases, independent combined source review, prose, formatting and normal signed commit hooks passed. Each runtime selected one case with 17 filtered; rules took 0.04 seconds and node expressions 0.02 seconds on one reused release build. No broad target or WASM execution. Hosted qualification is pending; no hosted pass or external approval is claimed. No conflicts or synchronization were needed. Parent #863 remains open for remaining requirements. No optional Stage archive selected; complete local evidence is preserved privately. Defect-Class: none parent_hashes: |
||
|---|---|---|
| .githooks | ||
| .github | ||
| bindings | ||
| corpora/community | ||
| crates | ||
| docs | ||
| examples/projections | ||
| generated | ||
| LICENSES | ||
| queries | ||
| scripts | ||
| vectors | ||
| .deficiencies | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| CITATION.cff | ||
| CLAUDE.md | ||
| cliff.toml | ||
| clippy.toml | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| dependency-ledger.toml | ||
| helpers-ledger.toml | ||
| layers.toml | ||
| LICENSE-APACHE | ||
| license-inventory.toml | ||
| LICENSE-MIT | ||
| LICENSE-MULAN | ||
| LICENSING.md | ||
| Makefile | ||
| PROVENANCE.md | ||
| README.md | ||
| README_zh.md | ||
| rust-toolchain.toml | ||
| SECURITY.md | ||
PurRDF
RDF 1.2, reasoning, retrieval, and graph transport — one Rust engine, shared across languages.
One RDF engine. One behavior. Every language.
PurRDF is a Rust toolkit for building applications around knowledge graphs. It brings RDF 1.2, SPARQL, validation, reasoning, text and vector retrieval, document codecs, and graph transport into one engine. Python, JavaScript / WebAssembly, and C call that engine rather than reimplementing it.
A graph can carry statements about statements, multilingual literals, named graphs, provenance, and linked binary content. PurRDF keeps those distinctions through querying, validation and the carriers that can represent them; a projection that loses information returns a located loss ledger.
One RDF engine. One behavior. Every language. The language surfaces expose
different portions of the toolkit, described below. Every published Rust crate
also builds for wasm32-unknown-unknown.
Try the browser playground · Read the book · Rust API · Migrating to 4.0
What you can build
| Job | PurRDF provides |
|---|---|
| Carry RDF 1.2 through an application | Interned datasets, triple terms, reifiers, annotations, directional literals and named graphs; native text codecs, canonicalization, diff and isomorphism. |
| Query and change a graph | SPARQL 1.1/1.2 query and Update, prepared execution, property paths, host extensions, resource governors and explain receipts. |
| Validate and derive knowledge | SHACL 1.2, ShEx 2.1, deterministic Datalog, RDF/RDFS/OWL-RL/D materialization, OWL-Direct reasoning and RIF-Core. |
| Retrieve across several signals | Exact fixed-point BM25, GeoSPARQL predicates, exact embedding kNN, deterministic HNSW, and reciprocal-rank fusion with per-producer evidence. |
| Make a document queryable | Structural Markdown and ordered JSON codecs with byte-addressed occurrences, explicit profiles and exact reconstruction. |
| Exchange graph data | GTS containers with binary payloads; canonical five-table Parquet; graph, tabular and research-object projections with loss records. |
| Read an immutable snapshot under a budget | Certified segmented storage, authenticated range reads, pinned terms, sparse caches and shared workspace admission through the ordinary dataset/evaluator seams. |
Start with the purrdf facade in Rust. It exposes the RDF
surface at the root and the other engines as modules. Applications supply their
own vocabularies, extension registrations, network transports and embedding
models. Standard RDF vocabulary terms are built in; application namespaces are
explicit configuration.
Query, reason and retrieve together
A Rust host can join graph patterns with text search, spatial relations and embedding neighbours in the same SPARQL evaluator. Register each relation under a predicate IRI supplied by the application:
PREFIX ex: <https://example.org/>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
SELECT ?doc ?score ?distance WHERE {
?doc ex:search ( "harbour dredging" ?score ?rank ?lang ?matched ) .
?doc ex:locatedIn ?feature .
?feature geo:sfWithin ex:PortDistrict .
?doc ex:nearest ( ex:doc-42 5 ?distance )
}
ORDER BY ?rank
This query assumes the host has registered the text, spatial and vector relations and supplied the coordinate-system configuration. An unregistered predicate remains an ordinary RDF pattern.
- Text:
purrdf-textindexes RDF literals, including the annotation layer, with Unicode normalization, case folding and segmentation. BM25 scores use exact fixed-point arithmetic. Ranked search and term-occurrence relations support phrase and proximity composition in SPARQL. The index is resident and built over a frozen dataset. The default preserves lexical spelling; callers can select English stemming. Stop-word dictionaries and a separate query dialect are outside its surface. - Geometry:
purrdf-geoimplements GeoSPARQL 1.1 topological predicates over exact rational WKT/GeoJSON geometry, plus accessors and exactly computable measures and constructors. Coordinate transformation, ellipsoidal geodesics, buffers and overlay set operations are not implemented; registered unsupported functions refuse by name. The host declares the CRS and which coordinate systems use metres. - Vectors: PURREMB carries caller-produced embeddings,
their coordinates and derivation identities. Exact kNN supports cosine,
negative dot and squared Euclidean distance.
purrdf-hnswadds an approximate index with deterministic levels, build scheduling and payload bytes under its default arithmetic. Approximate candidates never certify that no nearer row exists. PurRDF writes and reads embedding artifacts; it does not run a model to generate the vectors. - Fusion:
purrdf-retrievalplans a typed request, compiles it to per-producer SPARQL, executes it and fuses the ranked streams. Exact fixed-point reciprocal-rank fusion carries plan, fusion-law and evidence identities, per-stratum provenance, index-generation attestations and declared search fidelity. Unserved request terms and incomplete producers remain visible in the result. Producers, strata and weights are caller-supplied.
Default distance arithmetic pins the accumulation order across native and WASM
paths. Explicit Reassociated arithmetic permits different last bits in exchange
for different code generation; HNSW artifacts bind that choice to their recorded
build and execution path. Approximation and arithmetic are separate contracts.
See embedding kNN,
HNSW's recall and build evidence,
retrieval composition, and
SIMD and arithmetic contracts.
These ranked producer integrations are Rust APIs, also usable by a Rust host compiled to WASM. The shipped Python and npm packages expose data-shaped property functions and path witnesses; they do not expose the text, spatial or vector producer registrations.
Documents, carriers and storage
Documents can be graphs of themselves.
purrdf-markdown projects a specified Markdown
dialect into headings, paragraphs and other structural units over verbatim byte
spans. purrdf-json records ordered JSON occurrences
and their byte cover. Both require explicit profiles, bind identity to the
profile's law and source bytes, and reconstruct the source byte for byte.
The Markdown dialect is specified by the codec; it is not a CommonMark parser.
Conversions account for loss. Native codecs cover Turtle, TriG, N-Triples, N-Quads, RDF/XML, TriX, HexTuples, JSON-LD and YAML-LD. The JSON-LD context lens compiles reusable offline contexts; it supplies expansion, compaction and derived-prefix modes, with caller-provided context registries and no network loader or framing API. Graph and research-object projections include Neo4j CSV, openCypher, GraphML, CSVW, OBO Graphs, SKOS, DCAT, VoID, RO-Crate, Croissant, DataCite and Frictionless. Supported reversible carriers retain RDF 1.2 through an exact sideband; lossy views report what was lost. See projections and the generated loss matrix.
One canonical columnar projection.
purrdf-columnar supplies the native five-table v1
contract: terms, quads, reifiers, annotations and blobs. Python's
SQLite, DuckDB and Parquet exporters use its canonical IDs and schema, retaining
scoped blanks, quoted terms, directions, empty named graphs and verified blobs.
GTS's append-order inspection IDs remain a separate authority.
Two immutable storage paths. Eager pack snapshots provide a front-coded
dictionary, bitmap indexes and content verification. The new
SegmentedSession reads a certified persistent
representation through a host range provider, authenticates admitted blocks,
and shares a live ledger between sparse caches, pins, evidence and operator
workspace. It preserves global IDs across sealing and reopening; persisted
handles identify the exact snapshot.
Resident datasets retain compact four-byte term IDs, sixteen-byte quad rows
and borrowed term access. Operational reads use typed failures and pinned guards
through the same DatasetView seam. A storage failure discards the operation's
result at its final checkpoint. Bounded query admission currently covers a plain
variable-projected SELECT over a basic graph pattern; unpriced operational
forms return a typed refusal. Construction, full certification, host buffers
and caller-owned outputs have separate memory obligations. The kernel performs
no filesystem or network I/O. See the storage contract
and 3.0 migration guide for the exact boundaries.
Rust's explain_query_fallible_view measures the operational view directly and
returns its explanation with final storage evidence. Its options and stop-signal
variants share the query admission rule; a storage failure discards the entire
explanation, and a stop alone appears in the explanation's governor evidence.
Graph transport with its payloads. GTS is a content-addressed, append-only container with deterministic fold, binary payloads, chained CBOR segments, COSE signing/encryption and pure-Rust crypto. Its container API reaches Rust, Python and C, and the CLI reads it as an input format. The npm / JavaScript package does not expose it. Frozen transport vectors are shared with the authoritative GTS project.
Validation, reasoning and accountable execution
SHACL 1.2 covers Core, SPARQL Extensions, Node Expressions, Inference Rules and SPARQL 1.2 RL, with SHACL-AF spellings mapped to the shared representation. Reports are RDF datasets. ShEx 2.1 supplies ShExC/ShExJ schemas and validation, including imports and semantic actions. Imports resolve from explicit host registries. The Rust schema compiler also projects shapes into JSON Schema, OpenAPI, Pydantic, LinkML, TypeScript and GraphQL, with coverage and loss reports; those schema lanes are Rust-only.
The entailment engine implements all 78 OWL 2 RL rules and all 18 RDF + RDFS
patterns. That is rule-table coverage, distinct from entailment conformance:
on the vendored W3C corpus the chase scores 27 of 27 positive and 23 of 23
negative, the latter recording that no unsoundness was found. The additional
ext-eq-diff-sym rule is disclosed in reasoning reports and excluded from those
rule counts. OWL-Direct supplies an open-world SHOIQ(D) tableau and reasoning
services with certificates; a capped search returns unknown. RIF-Core and
entailment-aware SPARQL run alongside the materialization regimes. See
the rule inventory and
reasoning services.
Query governors bound execution and return evidence about a trip, including which rows can be certified under non-monotone operators. Governed Update commits entirely or not at all. Prepared execution and scoped callbacks reuse the same evaluator. The charge schedule and the frozen 57-case governor corpus are published in the governor profile. Structured diagnostics preserve stable codes and readable English, with named parameters and exact logical anchors in JSON, SARIF and the C diagnostic record.
Quickstart
Rust
cargo add purrdf
use purrdf::{parse_dataset, serialize_dataset, SerializeGraph};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let source = r#"
@prefix ex: <https://example.org/> .
ex:alice ex:knows ex:bob .
"#;
let dataset = parse_dataset(source.as_bytes(), "text/turtle", None)?;
assert_eq!(dataset.quad_count(), 1);
let turtle = serialize_dataset(&dataset, "text/turtle", SerializeGraph::Dataset)?;
let restored = parse_dataset(&turtle, "text/turtle", None)?;
assert_eq!(restored.quad_count(), 1);
Ok(())
}
Use the facade's sparql, shapes, shex, entail, retrieval, columnar,
json and markdown modules as your application grows.
More Rust examples.
Python
pip install purrdf
import purrdf
quads = purrdf.parse(
'<https://example.org/alice> <https://example.org/name> "Alice" .',
purrdf.RdfFormat.TURTLE,
)
print(quads)
Python 3.13+ wheels carry the native extension. Store exposes SPARQL and
Update; shapes, shex and entail expose validation and reasoning. Dataset
and GTS columnar export use the native projection.
Python guide.
An explicit compatibility layer is available at purrdf.compat.rdflib.
For applications that need the top-level rdflib import name:
pip install 'purrdf[rdflib]'
This installs the separate purrdf-rdflib distribution with a matching version.
Its rdflib package and genuine rdflib cannot share one environment; keep real
rdflib environments separate and omit the shadow extra there.
JavaScript / WebAssembly
npm install @blackcatinformatics/purrdf
import { ready, DataFactory, Dataset } from "@blackcatinformatics/purrdf";
await ready();
const f = new DataFactory();
const dataset = new Dataset();
dataset.add(f.quad(
f.namedNode("https://example.org/alice"),
f.namedNode("https://example.org/greeting"),
f.directionalLiteral("مرحبا", "ar", "rtl"),
));
const restored = Dataset.parse(dataset.serialize("nquads"), "nquads");
console.log(restored.size, dataset.id.toString());
The RDF/JS-shaped API also exposes SPARQL, SHACL, reasoning, projections and
static RDF 1.2 SVG visualization. Asynchronous queries can use host-provided
SERVICE / LOAD resolvers through JSPI. In 3.0, dataset identities and
generations are bigint; use decimal strings in JSON.
JavaScript guide.
C and CLI
libpurrdf exposes parse, serialize, iteration, mutation,
SPARQL, validation, reasoning and GTS through a panic-safe C ABI. make capi-build
builds the library with cargo-c; make capi-bundle prepares a relocatable
header/library distribution with recipient notices. The committed
purrdf.h is checked against generated output.
The CLI provides convert, query, update, reason,
entails, consistency, validate, shex, describe, project, lift and
pack verify. Build it from this repository; the CLI crate is not published
on crates.io. See CLI usage.
Every parsing surface accepts an explicit document base for relative IRIs. An unresolved relative IRI is diagnosed when no explicit or in-document base is available. Network access is host-supplied: synchronous shipped surfaces install no federation resolver, and the core ships no HTTP client.
Crate map
| Crate | Role |
|---|---|
purrdf |
Start here: the umbrella facade. |
purrdf-rdf |
Native RDF codecs, GTS adapters, projections and canonicalization. |
purrdf-core |
Interned IR, read sessions, segmented storage, diagnostics, provenance, pack and PURREMB. |
purrdf-sparql-algebra |
SPARQL parsing and algebra. |
purrdf-sparql-eval |
Query/Update evaluation, governors and extension seams. |
purrdf-sparql-results |
Results JSON, XML, CSV and TSV. |
purrdf-shapes |
SHACL validation/rules and schema compilation. |
purrdf-shex |
ShEx schemas and validation. |
purrdf-datalog |
Deterministic semi-naive rule substrate. |
purrdf-entail |
Materialization, OWL-Direct and RIF-Core. |
purrdf-text |
Exact fixed-point full-text search. |
purrdf-geo |
Exact GeoSPARQL geometry and relations. |
purrdf-geo-kernel |
Deterministic geometry, geodesy and spatial indexes shared by PurRDF hosts. |
purrdf-hnsw |
Deterministic approximate nearest-neighbour indexes. |
purrdf-retrieval |
Typed planning, execution and ranked fusion with evidence. |
purrdf-columnar |
Canonical five-table Parquet codec. |
purrdf-gts |
Container, fold, verification and cryptography. |
purrdf-markdown |
Structural Markdown codec. |
purrdf-json |
Ordered JSON byte-cover codec. |
purrdf-toml |
Lossless TOML 1.1 model and verified RDF byte-cover codec. |
purrdf-mime |
Lossless original-byte MIME codec with ordered occurrences and shared cover verification. |
purrdf-glob |
Compiled Unicode glob matching with explicit surfaces and metered execution. |
purrdf-jsonschema |
Native JSON Schema drafts 2020-12, 2019-09 and 07. |
purrdf-slice |
Slice catalogs, artifact ownership and dependencies. |
purrdf-validate |
Shared validation, governor and diagnostic host boundary. |
purrdf-iri |
IRI/URI, language tags, base resolution and standard vocabularies. |
purrdf-xsd |
XSD value spaces, exact numbers and temporal arithmetic. |
purrdf-cdt |
SPARQL composite datatypes and their function library. |
purrdf-events |
Zero-dependency ingestion protocol and text direction. |
purrdf-lex |
Shared terminals, Unicode and JSON/YAML/CBOR/XML codecs. |
purrdf-hash |
Zero-dependency hashes and shared identity kernels. |
purrdf-deflate |
Native deterministic DEFLATE/gzip. |
purrdf-ed25519 |
Ed25519 signing and strict verification. |
purrdf-stack |
Native/WASM stack admission. |
purrdf-wasm |
Engine and ESM bindings for JavaScript. |
The C ABI, CLI, Python extension and test/benchmark tools live in the same workspace but are not published as Cargo packages. Shared first-party lexical, codec, hashing and signature foundations reduce the external dependency surface; each shared job has one enforced home. There are no semantic Cargo features, so an install-time feature selection cannot change the carrier's behavior.
Evidence and performance
The conformance scoreboard distinguishes official
suites, first-party corpora, approved divergences and untested boundaries.
SPARQL evaluation has 1393 passing, 0 ledgered.
SHACL has 129/129 passing on the vendored W3C SHACL 1.0 test suite, zero ledgered,
and 590/591 passing on the vendored W3C SHACL 1.2 test suite.
The 591st entry, hasLang-example, is reported failed: it calls sparql:hasLang with two
arguments where the SPARQL 1.2 grammar takes one.
Conformance gates distinguish official suites, first-party frozen corpora and
explicitly recorded boundaries. The full scoreboard and commands are in
docs/CONFORMANCE.md:
| Engine | Suite | Result |
|---|---|---|
| ShEx 2.1 validation | shexTest v2.1.0 (vectors/shexTest/) |
1,105 / 1,105 attempted, 0 xfail |
| ShEx schemas / negative syntax / structure | shexTest v2.1.0 | 425/425 · 99/99 · 14/14 |
| SHACL | W3C data-shapes (vectors/shacl/) |
129 / 129 pass · 0 ledgered |
| SHACL 1.2 | W3C shacl12-test-suite (vectors/shacl12/) |
590 / 591 pass · 0 ledgered expected failures, 1 spec-contradicted (hasLang-example); 1 unlisted vendored files graded apart |
| SHACL (first-party frozen corpus) | crates/shapes/corpus/ |
73 / 73 |
| SHACL Rules | DASH + first-party (vectors/shacl/af/rules/) |
20 / 20 |
| Syntax codecs | W3C rdf-tests round-trip | 264 / 264 |
| JSON-LD 1.1 context lens | W3C JSON-LD 1.1 REC toRDF + compaction (crates/rdf/tests/fixtures/jsonld-w3c-rec/) |
73 / 73 applicable toRDF · 13 / 13 exact compaction |
| SPARQL 1.0/1.1/1.2 | full W3C sparql10 (data-r2) + sparql11 + sparql12 + first-party, via purrdf-sparql-conformance |
1393 pass · 0 ledgered |
| SPARQL CDT (SEP-0009) | vendored awslabs/SPARQL-CDTs (vectors/sparql-cdt/) |
658 / 658, 0 ledgered — see the lexical-space divergence in docs/CONFORMANCE.md |
| SPARQL execution governors | first-party frozen corpus (vectors/sparql-governors/) |
57 / 57, 0 ledgered |
| Entailment (SPARQL regimes) | W3C sparql11 entailment/ group |
70 / 70, 0 ledgered |
| Entailment (OWL 2 DL consistency) | vendored W3C OWL 2 suite | 262 / 262 agreeing, 0 ledgered, 0 unledgered |
| Entailment (OWL 2 RL, W3C entailment tests) | vendored W3C OWL 2 entailment suite | 50 / 50 agreeing, 0 ledgered, 0 unledgered — negative lane 23 / 23 (no unsoundness), positive lane 27 / 27 |
| RDFC-1.0 | W3C canonicalization fixtures | green |
RDF 1.2 canonicalization profile (purrdf-rdfc12 v2) |
first-party vectors (vectors/rdf12-canon/) |
12 / 12 |
| GTS | frozen cross-language vectors (vectors/) |
38 / 39 fold byte-exactly into their committed expectation, 1 ledgered divergence |
Performance evidence is workload- and host-specific. The benchmark harness
records distributions and allocation evidence; make bench runs the native
microbenchmarks. Scale-corpus, LUBM and WatDiv comparison lanes are report-only
and need their documented inputs. Comparative runs need controlled machine
conditions, matched builds and preserved raw samples. Browser memory caps,
reader ledgers and physical-device limits establish different facts.
See benchmark methodology.
Direction
PurRDF is growing into a foundation for applications that combine graph reasoning, retrieval and document data across deployment sizes. The next gains should make those capabilities easier to compose and carry into more workflows, while keeping identities, resource limits and evidence explicit. The public contracts and the implemented surfaces above are the basis for that growth.
Documentation and development
- The PurRDF Book: language guides, concepts and engine contracts; also in Simplified Chinese.
- Browser playground: parse, query, validate, serialize and compare graphs locally in the browser.
- Migration to 4.0, migration to 3.0 and changelog.
- GTS, PURREMB, RDF 1.2 canonicalization, storage contracts and release process.
make metadata # regenerate and verify projections and license bundles
make check # formatting, clippy, build, tests and hygiene
make bench # report-only microbenchmarks
make scale-corpus # deterministic corpus generation
make lubm # comparison lane; native Rust generator, pinned external ontology/queries
make watdiv # comparison lane; frozen network dataset
Consumers need stable Rust 1.98 or newer. Contributors use the nightly
analysis toolchain declared in rust-toolchain.toml; the source uses no
nightly-only features. CI separately enforces the stable MSRV and builds every
published crate for WASM. Release artifacts use stable Rust.
The Cargo suite, Python distributions and npm package share one coordinated
version and follow semantic versioning. The C ABI is separately versioned,
currently 0.8, with signature checks and purrdf_abi_version at runtime.
See contributing for the verified commit workflow.
PurRDF is developed by Blackcat Informatics® Inc. and is the library backbone of GMEOW. Extraction history and provenance record its relationship to the GTS project.
License
First-party code is offered under MIT, Apache License 2.0, or MulanPSL-2.0, at your option. Separately licensed documentation and third-party material retain their own terms. Actual distribution archives include applicable full texts, recipient notices and provenance inventories. Licensing guidance explains the scope and 提供中文说明.
If you use PurRDF in research, please cite CITATION.cff.