ktonkton turns each step of an analysis, and each statement about it, into a small, signed, content-addressed record. From those records you get lineage, reproduction, and review that a reader can verify themselves, with no central server and no need to trust whoever produced them.
When results move between people, scripts, and tools, you lose track of where a file came from, whether it can be reproduced, and who reviewed or approved it. A shared database "solves" this only if everyone trusts that one system. kton takes the opposite route: every step becomes a portable record, identified by the hash of its content, signed by whoever made it, and copyable between tools. Independent people and programs converge on one lineage graph that each of them can re-check by re-hashing and re-running. Think of it as git for data provenance and sign-offs, across tools.
Records reproducible computations. Its record is a foton: input files -> a command
-> output files, where every file is named by its content hash. Machine-checkable, re-run or
re-hash and you know if it matches. plankton stores none of the bytes, only the hashes and which
file went where.
Records signed opinions. Its record is a claim: a signed subject-predicate-object statement about something, "this model was reviewed by X", "this output is derived from that input". A machine can only check who signed it, not whether it is true, that is the point of a signature.
The substrate as a whole (plankton + nekton) plus a thin command that conducts both. "kton" is what
you say when you mean the system; plankton and nekton are its two kinds of record. The examples call
plankton and nekton directly - the kton command is optional,
needed only for the network features in example 08 (anchoring to a transparency log).
Two kinds, both are just a small signed file identified by the hash of its content:
a recorded computation: the hashes of its inputs, an opaque command/protocol, and the hashes of its outputs. It is an edge in a lineage graph — the files it connects (its inputs and outputs) are the nodes.
a signed statement whose subject is usually a foton or a file (by hash), so claims attach to exactly the thing they are about.
PLANKTON_DIR=<dir>
(and NEKTON_DIR for the nekton claim store the same way), and a different folder is a
different, independent registry. Registries federate by being read together: point a query at
several with --source and they converge on one lineage by content hash, with nothing
copied and no shared folder (plankton mirror then copies records into one store only as
an optimization, for offline or single-store reads). (A registry is a store, not an
execution environment like a container or an OS, that is a separate thing plankton can record
on its own.)
Each one both creates records and uses them, and renders the resulting graph in the viewer. Start at 01.
The smallest create + use: record one computation as a signed foton, then show it, verify its signature, and ask "who produced this file?" by output hash.
Two independent registries that never share a folder converge on one lineage by content hash -
read together with --source, nothing copied. mirror comes last, as an
optimization. A stranger who knows neither party gets the same graph.
Record a computation, re-derive its output, and prove it matches: identical bytes give L0 reproduction; a tampered re-run gives none.
plankton records a reproducible foton; nekton records a signed opinion about it. The claim's subject is the foton's id, so the two layers join by hash.
A review is its own registry, seeded from a public parent and handed over whole. It carries its enrolled reviewers in its own signed chain, so completeness is mechanical: a reviewer who rejects - or one who is enrolled but never delivers - blocks release. You cannot strip a reject to get a clean review; you get an incomplete one, fail-closed. The verdict is a reproducible plankton foton over the review.
The plankton lineage and the nekton claims export to RDF that merges at the same hash IRIs, so a reasoner sees provenance and attestation as one graph.
A key is an identity: give a model its own key and trace which claims came from which model. Then bind a key to a named principal with a separate signed claim, verifiable, not just asserted.
The strongest identity tier - authority-backed, defined in example 07 - made real: sign a kton record with your GitHub identity via Sigstore keyless (Fulcio certificate + Rekor transparency log), verifiable with no long-lived key and no trust in you. Hands-on and interactive, so no live graph.
The whole arc: run locally, pin the exact docker image (carried, opaque), then define a spectrum - the test suite of an R package at exact versions, one foton per test - and verify the image reproduces every test. COVERED qualification vs CARRIED digest, made concrete.
A spectrum defines a tool by its reference outputs. This one really runs an R package's test suite twice, in two environments, and the graph shows per test whether the runs are byte-identical (an L0 edge) or agree only after a normalizer strips a volatile line (an L1 edge), then binds the environment to the spectrum with qualifies-as. Nothing fabricated.
The classical way to author a claim: a template. Three reviewers each approve a foton (approve/reject reusing schema.org, a comment as a file), nothing overwritten. The template is registered as a federated record, and a SPARQL query over the exported RDF tests that the review is complete - every required reviewer approved, no rejects. It is first-class when that check runs as a foton: the nekton (the signed reviews) in, the verdict out, recorded in the graph.
Everything at once. A CRO builds a popPK model, a sponsor reviews and submits it, and the agency re-verifies the whole thing - reproduction, a qualified environment, a signed model tree, typed sign-offs with evidence - across three registries with no shared server. It ends with a single SPARQL release gate that decides whether the submission may be accepted - which the agency records as a verdict-foton (its inputs the exact evidence, its output the decision). Real R throughout.
A kton record is an in-toto Statement in a DSSE envelope - the language of SLSA, sigstore, and in-toto - so any DSSE-aware tool reads it. Here a twenty-line verifier using only standard crypto (no kton code) checks a foton's signature and rejects a tampered one. "Verify it yourself" means with any tool, not only ours.
plankton stores no bytes, only hashes - so "verify by re-hashing" needs the bytes from
somewhere. A signed dcat:downloadURL says where; kton fetch dereferences
it and checks sha256 == hash before trusting a byte. A forged mirror is rejected on
arrival: the hash is the authority, the URI only a hint.
The hardest test of “trust no one”: an adversarial security engagement against kton, documented in kton itself — each attack is a foton, each finding a signed claim, and the regression suite a spectrum. Two dozen attacks (co-signature drop, normalizer forge, federation withholding, four-eyes graph-poll, viewer XSS …) with the fixes that closed them.
The point of a substrate that says "trust no one" is that it is honest about the few things it cannot settle with a hash, a signature, or a chain. What they can settle - lineage, reproduction, who signed what, that a sealed chain was not silently edited or a committed link dropped - is mechanical. What they cannot is named here, surfaced rather than hidden:
A signature proves which key signed, never that you should trust that key. Which identities and authorities you accept is your decision, never the substrate's. The identity examples (07/08) give you verifiable bindings; they do not tell you whom to trust.
Over an open union - the records you merely happened to load - completeness is a boundary: sealing is tamper-evidence, not append-control, so a reject already in the chain cannot be silently dropped, but no hash proves that every relevant review is in what you loaded. A withheld failing review, never federated to you, leaves no trace - you cannot prove a negative over a partial union. That is the model the release gate (example 12) uses, so it names and commits to its corpus (a smaller-corpus rerun is a different, comparable verdict). But completeness becomes mechanical when the review carries its own corpus: a sub-nekton that commits, in its own signed seed-chain, to its enrolled reviewers and a close authority (example 05). There the check flips - a withheld reject is a missing enrolled reviewer, and missing BLOCKS. So: mechanical within a committed, enrolled scope; a boundary only over an open union.
A chain proves a head's integrity, not that it is the current one. Anchoring makes a superseding round undeniable and time-ordered, but confirming you hold the latest anchored head before you rely on it is a consumer obligation. A missed reopen is negligence, not ignorance.
Records are kept forever and cheaply; the file bytes are kept per a retention policy and located, not stored. Availability is never a trust problem - content addressing self-checks on arrival, so a location is a hint, not an authority - but whether the bytes still exist somewhere is a retention obligation, stated, not assumed.
The full argument - honesty, completeness, freshness, finality, and graded verification, each with its boundary - is in the protocol's Trust chapter.