Sovereign, semantic, multi-participant state — governed, provable, and reachable only through one typed door over NATS. No REST. No query surface. The engine stays invisible; the meaning stays sovereign; the proof chain stays whole.
pgCK makes a database the living home of concept kernels — units of meaning whose types are ontology, whose every change is shape-gated, sealed, and proof-chained, and whose only interface to the world is a single typed verb carried over NATS-WSS.
- Semantic, not tabular. A kernel's types are RDF classes with SHACL shapes and OWL-RL rules — designed to ground into upper ontologies (the Basic Formal Ontology, BFO) and domain vocabularies, not hand-rolled columns. Meaning is the schema.
- Strongly typed over pure NATS. Participants — browsers, agents, services — reach a kernel through exactly one capability,
ckp.dispatch(verb, payload), over NATS-WSS. No REST endpoint, no SQL handle, no query engine is ever exposed. The door is the whole surface. - Multi-participant by design. Many participants act on one kernel at once; every fact seals into the shared graph and emits to NATS, so they converge on a single governed truth — without anyone holding more than the door.
- Provable by construction. Every landing runs
validate → seal → HMAC-chained ledger → verifiable proof, in one transaction. Nothing lands that violates its shape. Each change carries PROV-O provenance and a proof anyone can re-verify. - Self-governing. A kernel changes its own types by consensus —
propose → vote → apply— so the very next write is bound by a quorum-approved shape, with a proof chain from proposal to applied epoch.
This is the Concept Kernel Protocol (CKP v3.11). The root ontology is published at conceptkernel.org/ontology/v3.11/core.ttl and pinned by digest (e5f7d1e5… — verify with shasum against the published sidecar). Reference authority: conceptkernel.org.
The shortest path from zero to sealed, governed, provable state — driven the way a browser or agent drives it: the cklib client over NATS-WSS → relay → ckp.dispatch. No SQL, no REST, only Docker.
# from the oci-germination repo — one script, only Docker required:
bash examples/hello-kernel/run.sh① activate the kernel CK.activate(kernel, { wssEndpoint, token })
② land sealed, proof-chained state create(Project) → proof_digest, verified
③ read it back + re-verify the proof verify · query
④ PROVE enforcement is real incomplete → REFUSED · anonymous → REFUSED
⑤ relate + traverse link → reach
And here's what your app (or browser, or agent) actually writes — cklib over NATS-WSS, nothing else. Types are the v3.11 root's own (always full IRIs on the wire):
import { CK } from 'cklib';
// realm-connected (quick-install door ②): your token is verified AT the door,
// and the seal derives who-you-are from the wire — identity is never payload
const k = await CK.activate('demo', { wssEndpoint: 'wss://host/wss', token });
const Project = 'https://conceptkernel.org/ontology/v3.11/core#Project';
const p = await k.create(Project, { label: 'hello', projectKind: 'personal',
ownedBy: 'urn:ckp:participant:you' });
// ownedBy is DOMAIN data — any IRI you designate. WHO SEALED IT is not yours
// to claim: createdBy is stamped from your verified connection.
// → { ok: true, id, verified: true, proof_digest } — sealed + proof-chained in one
// transaction, stamped createdBy / producedBy / sealedAtEpoch / conformsToShape
await k.create(Project, { label: 'incomplete' }); // omit shape-required fields
// → { ok: false } — REFUSED at the seal, with every violated clause named
// and on the ANONYMOUS bundle (door ①), this same create refuses too:
// → 'unattributed write refused' — there are no anonymous facts, only
// anonymous readers. A fact belonging to nobody never lands.
await k.verify(p.id); // independently re-checks the proof chain
await k.reach(p.id, '…/core#ownedBy'); // traverse the links you've sealedEvery step asserts. The client holds exactly one capability — ckp.dispatch — and cannot run SQL, reach the query engine, or land a fact that did not pass its shape gate and mint a proof. That is the point: the door is the only surface, the engine is invisible. (Full runnable example: oci-germination hello-kernel.)
Strip away every mechanism, and this is what remains: a concept kernel is a place where meaning lives and is answerable for itself.
Not a database — a database stores what you tell it and does not care what it means. Not a service — a service does what it is told and does not know why. A concept kernel is closer to a small, sovereign institution of meaning: it declares what kinds of things exist for it, it accepts only facts that honor those declarations, it remembers who said each thing and under which of its laws the thing was judged, and it changes its laws only by the agreement of those who live under them.
Three questions define it — the three loops of one sovereign entity, in a strict order:
- What can I mean? — its declared world: the kinds, shapes and relations it recognizes. This is its identity, and nothing outside it can write there.
- What can I do? — the acts it offers others: ways to add to it, ask it, link through it. Capability is always derived from meaning, never invented beside it.
- What have I done? — the sealed record. Every fact carries who said it, whose law governed it, which version of that law was in force, and which rule judged it. Knowledge here is never anonymous and never unjudged.
The founding sentence holds all of it: you do not enforce your own shape — you declare it, and the ground refuses what violates it. A kernel never argues. It declares, and the substrate beneath it refuses everything that violates the declaration — including the kernel's own attempts. That is what makes its record trustworthy to a stranger: the kernel cannot exempt itself from its own law. The boundary is real because it is held by write authority, not convention: storing a fact can never change the ontology, and running a verb can never rewrite the rules.
And it is sovereign: whole on its own, joined to others only by its own sealed choice. Everyone who can hold a key is a participant of the same standing — a person, an agent, whatever arrives next. The door does not ask what you are, only whether you can answer for what you say.
pgCK is a PostgreSQL extension (Rust / pgrx) that composes pgRDF: pgRDF holds the ontology and runs SHACL / SPARQL / OWL-RL; pgCK governs operations, owns the NATS bridge, and turns ontology into enforced, routable, provable behaviour — all inside one transaction boundary. The semantics live in the graph engine; the authority lives in Postgres roles; pgCK is where they meet. (Why an RDF engine inside Postgres rather than beside it: a kernel's meaning and the boundary that protects it have to be the same transaction.)
Every release is multi-arch (amd64 + arm64), PostgreSQL 18 only (glibc ≥ 2.38 base —
trixie/noble), with a SLSA build-provenance attestation, in two flavors: the plain extension
and the -nats build (in-process NATS relay + auth-callout). The current attested head lives
in LATEST.md — auto-generated by CI after attestation verifies, never by hand.
gh attestation verify oci://ghcr.io/styk-tv/pgck:0.4.77-pg18-amd64 --owner styk-tv # exit 0✅ Real today
- One governed door —
ckp.dispatchover a Postgres role floor; a sealed affordance registry is the only routing authority; epoch invalidation clears compiled plans on every kernel change; no caller SQL/SPARQL expression position is reachable. - Governed write + proof —
validate → seal → HMAC-chained ledger → verifiable proof, atomic, SHACL-gated against the kernel's own shape.instance.verifyre-checks the chain independently;instance.retireis a retraction seal. - Kernel-derived typed surface — generic typed
createagainst the kernel's declared shape;query/update/validateover declared properties (full SHACLValidationReport); per-kernel sealed transition maps; governedconcept.match; declared-predicatelink/reachthat traverses participant links (by bare id or@id). - Self-changing types —
propose → vote → applymutates the kernel shape by quorum; the next seal is bound by it, with a full proof chain from proposal to applied epoch. - Install-from-zero —
CREATE EXTENSION pgck CASCADEyields a working governed door for a realck_participantlogin, floor intact, zero setup. - NATS bridge — a
pgrxbackground worker bridges the governed write path to NATS and drains sealed facts to the wire, so participants observe each other.
⏭ The honest edge
- Verified identity is live in the
-natsbuild — pgCK itself answers the NATS auth-callout: an EdDSA (Ed25519) JWT is verified in-memory against a JWKS document delivered at container start (never a URL, no egress), the verified subject rides broker-enforced subjects intockp:createdBy, and unattributed writes refuse rather than mint anonymous participants. Anonymous connections are admitted subscribe-only. - Module adoption is governed and pinned — a module reaches a kernel's enforcement
surface only through a sealed, digest-cited
ckp:Adoption; the substrate pins each adopted graph (byte and structural planes) so later drift is detectable, and fresh installs carry the pin ledger out of the box (v0.4.77). - Upper-ontology grounding (BFO and friends) and cross-kernel federation are the trajectory — captured as direction, built only when a real consumer needs them, never speculatively.
ed25519will replace the shippedhmac+sha256proof method.
Per-version detail and the full capability boundary: CHANGELOG.md.
Both are attested oci-germination bundles that carry pgCK + pgRDF + NATS pre-composed. One docker run, no build.
① Localhost, anonymous — the fastest working kernel (ociger-pg18-pgrdf-pgck-nats-micro): PostgreSQL 18 + both extensions + NATS core/WSS in one container. No identity plane — right for a private localhost bench, exploration, and CI. Anonymous dispatch reads freely (surface checks, queries, events) — and crucially, instance.validate runs the full SHACL gate and returns the complete report without sealing, so every shape, clause and negative control is testable with no identity at all: anonymous tests the law; a named identity tests the ledger. Writes refuse unless an identity is declared — over the wire that means door ②, and on the operator/SQL path it means naming one explicitly (set_config('ckp.requester', 'svc:my-bench', true)) before sealing. A fact belonging to nobody never lands, even on a toy bench.
Set your kernel explicitly on both planes. Through ≤ 0.4.78 the SQL/operator path falls back to the project
demowhenckp.projectis unset, while the wire serves whateverpgck.kernelsnames — so mixingpsqlwrites and wire writes can split your facts across two kernels without saying so. Setckp.project(session orpostgresql.conf) to the same kernelpgck.kernelsserves. The pre-composed bundles already pin both.
docker run -d -p 5432:5432 -p 4222:4222 -p 9222:9222 \
ghcr.io/sporaxis-com/ociger-pg18-pgrdf-pgck-nats-micro:latest② Realm-connected — identities sealed from the wire (ociger-ck-allinone): the full bundle with the identity boot-provisioner. Hand it your OIDC realm's JWKS document at container start (a document, never a URL — verification is in-memory, zero egress) and pgCK itself answers the NATS auth-callout: each user's EdDSA token is verified at the door, and the verified identity rides the broker-enforced wire onto every fact they seal — attribution is derived by the substrate, never claimed by the client. Without a realm configured it boots in the same anonymous mode as ①.
Current tags, digests and the realm environment contract: oci-germination LATEST.md.
The local loop is Docker on the colima context. just builds the Linux artifacts into compose/extensions/ and runs the isolated stack.
just pgrdf-fetch # fetch released pgRDF artifacts
just build-ext # build pgck.so + control + sql
just compose-up # bring up the stack
just smoke-s4 # warm governed suite (s4…s69)
just smoke-s34 # fresh-install gate (CREATE EXTENSION from zero)
just psql # psql into the compose postgres — operator/debug onlyA browser-facing NATS-WSS stack (just nats-wss-up, just smoke-nats-wss) is available for end-to-end WSS testing. Working drafts, planning notes, and helper material live in a local-only, gitignored _WIP/ and are not part of the public repo surface.
Operator/debug aside (not the adopter surface). You can reach the door directly:
SELECT ckp.dispatch('instance.create', '{"type":"urn:ckp:demo/type/Ship", …}'::jsonb)asck_participant. That bypasses the wire and exists for debugging only — the surface a real app or browser integrates against is cklib over NATS-WSS, exactly ashello-kernelruns it.
MIT — see LICENSE.