Technical specification · canonicalization v1

How the Reproducibility Fingerprint is computed.

The rpf_ fingerprint is a deterministic protocol identifier: a protocol's title and sections are distilled to a canonical experimental form, then content-addressed with a 128-bit non-cryptographic hash. Same canonical form → same identifier, on any machine, with no AI and no network. This page documents the exact input, the canonicalization rules, the hash, and — just as importantly — the limits of what the identifier means.

At a glancerpf_<26 base32>
Prefix
rpf_
Digest size
128-bit
Encoding
Crockford base32 · 26 chars
Algorithm class
Non-cryptographic content hash
Canonicalization version
v1
Determinism
Pure — no AI, no network, no clock
Where it runs
Browser, Node, and Edge (identical output)
Reversible
No — one-way identifier
The pipeline

Three pure functions, in order.

Every stage is deterministic and side-effect-free. Given the same input and canonicalization version, the output is byte-identical everywhere it runs.

  1. 01

    Harvest & canonicalize

    Text is gathered from the protocol title, sections, and optional steps, then reduced to sorted, deduplicated entity sets: unit-normalized quantities, and technique / material / statistics / standards vocabulary, plus a small set of design attributes.

    canonicalize(input)
  2. 02

    Serialize

    The canonical form is written to a single JSON string with a fixed key order and pre-sorted arrays. A source-size counter is deliberately excluded, so trimming whitespace never changes the result.

    serializeCanonical(c)
  3. 03

    Content-address

    That exact string is hashed to a 128-bit digest, rendered as 26 Crockford base32 characters, and prefixed to produce the identifier: rpf_<26 chars>.

    fingerprintId(serialized)
Input

What goes in.

The input is a protocol's title and its sections — the 12 structured sections an Olto protocol carries — with the structured step graph included when present. No account, identity, or metadata is read; only the content itself.

interface FingerprintInput {
  title?:    string | null
  sections?: unknown                       // the protocol's 12 sections
  steps?:    Array<Record<string, unknown>> | null
}
  • Title, then sections, then any steps are walked recursively; every string and number encountered is collected (arrays and objects are traversed to a depth of 6).
  • Text is harvested case-preserving, so the quantity scanner can tell molar M / mM / nM from length m / mm / nm.
  • Harvested text is bounded to 80,000 characters — a guard against pathological inputs, not a limit you meet with a normal protocol.
Canonicalization · quantities

Numbers become unit-normalized tokens.

A number followed by a recognized unit is parsed and multiplied to a single canonical unit per dimension, then rounded to 6 significant figures and emitted as a dimension-tagged token. Unit matching is case-sensitive and longest-literal-first, so mM wins over M and molarity never collides with length.

DimensionCanonical unitInputs that collapseToken
VolumemL5 mL · 0.005 L · 5000 µLvol:5mL
Massmg2 g · 2000 mgmass:2000mg
Amount of substancemmol1 mol · 1000 mmolamt:1000mmol
Times1 h · 60 min · 3600 stime:3600s
Lengthmm1 cm · 10 mmlen:10mm
Concentration (molarity)µM1 mM · 1000 µMconc:1000µM
Percentage%70%pct:70%
Rotational speedrpm12000 rpmspin:12000rpm
Relative centrifugal force×g12,000 × g · 12000xggforce:12000xg
Temperature°C37 °C · 98.6 °F · 310.15 Ktemp:37°C

Temperatures in °F or K are converted to Celsius and rounded to the nearest degree. The extracted quantity tokens are deduplicated and sorted; up to 300 distinct tokens are retained. Values that render identically after rounding are, by design, treated as the same quantity.

Canonicalization · vocabulary

Methods become a controlled vocabulary.

On a lower-cased copy of the text, fixed pattern sets map many phrasings to one tag — immunoblot and western blot both become western-blot. Each set is matched, deduplicated, and sorted; only what the vocabulary recognizes contributes to identity.

Techniques

up to 40

pcr · qpcr · western-blot · elisa · crispr · sequencing · flow-cytometry · hplc · mass-spec · centrifugation · microscopy · transfection

Materials & reagents

up to 40

dmem · rpmi · fbs · pbs · tris · edta · sds · dmso · trypsin · antibody · primer · buffer

Statistical methods

up to 20

t-test · anova · chi-square · regression · mann-whitney · kruskal-wallis · tukey · bonferroni · survival · correlation

Cited standards

up to 16

ISO / IEC · ASTM · IEC · USP · EP · EN · OECD · AOAC · CLSI · 21 CFR (matched by code pattern, upper-cased)

Design attributes

A small structured block of methodological signals is also extracted — presence flags plus a replication count — and always contributes to the canonical form.

controlsMentions controls, untreated / vehicle / sham / mock / placebo / baseline conditions
replicationAn integer or null — parsed from n = N, or triplicate / duplicate / quadruplicate
randomizationRandomized assignment / allocation is described
blindingSingle- or double-blind procedure is described
sampleSizeA power analysis / effect-size / explicit n is present
safetyPPE, biosafety level, hazard, IACUC / IBC / IRB, or waste-disposal language appears
statisticsA named statistical test, p-value, or significance language appears
Serialization

One canonical string.

The canonical form is serialized to JSON with a fixed key order and arrays that are already sorted, so the bytes are stable. The source-character count is excluded — it is a size metric, not part of the experiment's identity — which is why reformatting or trimming whitespace never changes the fingerprint.

{ "v": 1,
  "quantities": [...],   // sorted, deduplicated
  "techniques":  [...],
  "reagents":    [...],
  "stats":       [...],
  "standards":   [...],
  "design": { "controls", "replication", "randomization",
              "blinding", "sampleSize", "safety", "statistics" } }
The hash

A 128-bit non-cryptographic content hash.

The serialized string is hashed to a 128-bit digest and rendered as 26 characters. The hash is hand-rolled to run identically in the browser, on the server, and on the edge — it uses only 32-bit integer math (Math.imul and shifts), with no node:crypto and no big-integer literals.

Four 32-bit lanes

Each lane is an independent FNV-1a-style rolling hash seeded with a distinct constant and stepped by a distinct prime; character position is folded in so anagrams do not collide. Two cross-mixing steps per character perturb the lanes against each other.

Avalanche finalizer

The input length is folded into each lane, then every lane is run through Murmur3’s fmix32 finalizer, so a single-character change flips roughly half the output bits.

Base32 rendering

The four 32-bit words are read big-endian into 26 lowercase Crockford base32 characters (the alphabet omits i, l, o and u to stay unambiguous when read aloud or transcribed).

This is a content address, not a signature. There is no secret key and no cryptographic guarantee of preimage, second-preimage, or collision resistance. “Tamper-evidence” here means exactly one thing: anyone can recompute the fingerprint from the public protocol and compare. That detects accidental drift and honest mistakes — it does not, and is not meant to, stop a determined adversary.

Versioning & format

The rpf_ prefix, and why the version matters.

  • Format: rpf_ followed by 26 Crockford base32 characters (128 bits). A compact rpf_<8> short form exists for display, but the full identifier is what you cite and compare.
  • Canonicalization version: the current version is v1, and it is embedded in the serialized form (the v field). Two fingerprints are only meaningfully comparable when they were produced by the same version.
  • Evolving the rules: improving the canonicalizer changes the canonical form, and therefore the identifier, for the same protocol. That is expected — a fingerprint identifies content under a specific algorithm version, so the version travels with it.
Collisions

128 bits, honestly.

Across any realistic corpus of protocols, an accidental collision of two distinct canonical forms is astronomically unlikely at 128 bits. That is the property the fingerprint relies on to serve as an identifier.

Because the hash is non-cryptographic and unkeyed, it is not collision-proof against a determined adversary who deliberately constructs inputs to collide, or who works to craft content matching a target fingerprint. Treat rpf_ as an identifier, not a security boundary: excellent for citation, deduplication, and detecting accidental drift; never a substitute for a signature where an adversarial party is in scope.

Known limitations

Where it can be wrong.

Canonicalization is a deliberate, lossy reduction to a reproducibility backbone. That produces two symmetric error modes — and knowing them is the point of publishing this spec. It is why we say the same experiment usually, not always, yields the same fingerprint.

False equivalence

Different experiments → the same fingerprint.

  • Two protocols share the same normalized quantities, techniques, materials, statistics, standards, and design flags but differ in detail the canonicalizer never captures — a specific gene target, cell line, vendor, or the ordering of steps.
  • Numeric values that round to the same 6 significant figures, or units that reduce to the same canonical token, are treated as equal.
  • Anything outside the recognized vocabularies and quantity grammar is simply not part of the identity, so two experiments can match on the parts that are captured while differing on the parts that are not.
False difference

The same experiment → different fingerprints.

  • A quantity written in a form the grammar does not match — spelled out ("five milliliters"), a range ("5–10 mL"), or a unit not in the table — is dropped, so an otherwise identical protocol can fingerprint differently.
  • A technique, reagent, or statistic phrased outside the recognized patterns, or a typo / unusual abbreviation, is not captured.
  • Any change to the canonicalization version produces a different canonical form; fingerprints are only comparable within the same version.
Scope

What a fingerprint does not do.

It identifies normalized content per a specific algorithm version. That is a genuinely useful thing — and it is only that thing.

  • Prove authorship — anyone with the same content computes the same identifier; it carries no author identity.
  • Prove that the method is scientifically valid or correct.
  • Prove that the procedure was ever actually performed.
  • Provide a trusted timestamp — it contains no time and no external attestation.
  • Constitute a digital signature or legal provenance — there is no key, so it cannot bind an identity or resist a determined adversary.
  • Reconstruct the protocol — a 128-bit identifier cannot be inverted back into the source text.
Related artifact

The identifier vs. the capsule.

Because the fingerprint is one-way, it cannot reconstruct a protocol. When you need the content back, Olto emits a separate, lossless artifact — the Reproducibility Capsule — that carries the protocol itself and re-derives its fingerprint on decode.

rpf_… · fingerprint

26 characters, one-way, irreversible. An identifier for the canonical form — for citing, deduplicating, and detecting whether that form has changed.

rpc1_… · capsule

The protocol's title and sections, losslessly compressed into one portable token that decodes offline — and recomputes the fingerprint so a mismatch flags altered content.