NotBefore

Commit the decision. Randomize later. Verify the result.

New here? How the beacon works — the hourly cycle, why nobody can steer the number, and how to check it yourself, in plain language.

Register the input digest, the decision rule and its parameters before the randomness you will use exists. NotBefore then derives the result deterministically from a public, hourly, host-attested randomness log and packages the evidence an auditor needs to check the registration, the selection, the randomness and the execution — without trusting this site.

What is fixed, and when. Each hour the operator publishes a commitment C = SHA-256(E) to 32 bytes of hardware entropy E it already holds, bound to a drand round about one minute in the future (five minutes before 2026-09-13 18:00 UTC); after the round it reveals E. A consumer's value is V* = SHA-256(domain ‖ C ‖ ρR ‖ chain ‖ R): fixed the instant round R exists, by data committed before it. The producer knows E; nobody knows ρR before drand releases it, under drand's threshold assumptions. A withheld reveal changes nothing about V* — it only removes the QRNG provenance for that hour. Publication before the round is evidenced by two RFC 3161 tokens and a Rekor entry, never by a git date.

The registered decision, end to end

pip install notbefore
notbefore keygen                                                        # once: your Ed25519 identity
notbefore plan --after 2026-10-01T00:00Z --purpose chart-audit-2026-q4 \
               --decision-id NCT01234567/protocol-3/randomization-1 --sample 50 eligible.txt
#   ... wait for the hour ...
notbefore execute notbefore-plan-chart-audit-2026-q4.json               # no choices; halts rather than rerolls
notbefore receipt notbefore-plan-chart-audit-2026-q4.json               # one page, every line re-verified
notbefore bundle  notbefore-plan-chart-audit-2026-q4.json --out r1.zip   # attach to the paper or workpaper
notbefore check-bundle r1.zip                                           # what the reviewer runs, offline

plan signs the contract with your key, timestamps its bytes with FreeTSA and DigiCert, and registers the signed statement in the write-once decision log: the first statement per key and decision id is the authoritative preregistration. execute selects the first eligible commit released at or after your instant — eligible means verified, both tokens and its Rekor anchor before its round — and refuses if the log did not confirm your registration, if a superseded contract is presented, or if a candidate's eligibility cannot be established. It never silently moves to another value. Verdicts are VERIFIED, DEGRADED (a dry run) or INVALID. One page for the person who has to defend the randomization: WORKFLOW.md. Every command: USAGE.md.

Direct derivations — notbefore split 45 --purpose … --frac 0.8 roster.txt — reproduce a result from an already published pulse. They demonstrate reproducibility; on their own they do not establish preregistration. Legacy reveal-based contracts (versions 1–2) still execute, labelled.

The timing record

Every pulse carries signed measurements from the clocks that anchor it. The primary time base is an Intel i210 hardware clock on the p550 host, disciplined to a u-blox ZED-F9T PPS captured in hardware; that same i210 continuously measures a BMC grandmaster disciplined by a separate LEA-6T receiver, and a third host (k3) disciplined by that grandmaster signs its own observations. Two GNSS-disciplined paths, one measured relationship — both start at GPS, so they corroborate clock operation; they are not independent against a GNSS-common failure.

F9T TP1 PPS ──> i210 SDP0 (hardware capture) ──> ts2phc ──> i210 PHC ──── measures ────┐
                                                                                            ▼
LEA-6T PPS ──> P550-BMC grandmaster (trimmed via ptptgt) ──> PTP domain 44 ──> k3 PHC   BMC PHC

One dated record, pulse 0112 (2026-09-13 23:00 UTC), as signed by each host: F9T→i210 discipline 8.9 ns RMS, −20 to +20 ns, 60 samples over 59 s, servo locked; i210's observation of the BMC grandmaster 27.1 ns RMS, −31 to +66 ns, 30 samples over 58 s, path delay 445 ns (an estimate, not a symmetry proof); BMC→k3 discipline 37.9 ns RMS over 120 samples; F9T qErr for the anchoring epoch +1.9 ns, logged and not applied; PHC epoch guard intact on both hosts. The hour itself: k3 started 19.5 µs after the instant on its own PTP-disciplined clock, and p550's i210 stamped its hardware second event 27 µs after the same instant and delivered its signed statement to k3 1.3 ms later, bound into the commit (latency_chain.md). These are windowed precision figures. They are not absolute UTC accuracy: the antenna delay (69 ns) is measured, the rest of the absolute budget is not, and the receiver is L1-only today. Every v0.5 pulse from 0018 carries these signed statements; the verifier authenticates them (host signatures, pulse binding) and, since notbefore 0.13.0, checks them against a versioned timing profile: v1 (clock health) for every v0.5 pulse, and from 0.15.0 v2, which also requires the two-clock cadence provenance above for pulses from 0098. Details and every correction: HARDWARE.md, CLAIMS.md, ERRATA.md.

Log checkpoint

The log is an RFC 6962 Merkle tree over every pulse, published as a C2SP checkpoint in signed-note form:

/checkpoint            current signed head
/checkpoints/NNNNNN    per-size history
/decisions             the decision log (origin notbefore.net/decisions)

Origin notbefore.net/log. Anyone can recompute the root from the published pulses and check consistency with any earlier head. Checkpoints are cosigned by notbefore.net/witness/ryzen — a witness we operate ourselves (same sponsor, second system), which proves the witness path works, not independence; independent witnessing is requested and not yet in place. A split view is detected by consistency proofs against a head a client already holds, by comparing observers' copies, and by the Rekor and OpenTimestamps anchors of every checkpoint — not by any single client alone. See TLOG.md.

Verify it yourself

pip install notbefore
notbefore verify 113       # host signatures, drand BLS offline, RFC 3161, Rekor anchors, checkpoint inclusion
notbefore checkpoint       # the current signed head against the vendored identity and your cached head

The verifier, every key, the drand group key and both RFC 3161 trust chains are inside the package, pinned to a named log commit. Needs git and openssl on PATH. Without the BLS library the CLI fails closed. Timestamp tokens: every v0.5 commit since pulse 0018 carries two, taken at mint; skip pulses carry them when a TSA answered; pulses 0001–0009 predate them. Publication anchors: live from pulse 0042; 0001–0041 were anchored retroactively and their Rekor times are not commit times.

Published data

Source

github.com/docdailey/qrng-beacon-log · notbefore on PyPI · MIT; log data CC BY 4.0