
Inside the Append-Only, Hash-Chained Journal
How the Ranex journal blocks ordinary rewrites, detects edited rows, and where its rollback and truncation limit remains open.
TL;DR: Ranex keeps verdict records in an append-only, hash-chained SQLite journal so ordinary rewrites are blocked and edited rows are detectable, while rollback and truncation remain an explicit open limit. Read how the kernel works.
Someone asks why a change was allowed out the door. You open the audit record and find a clean story. What stops that story from being cleaned up after the fact?
A record that can be quietly rewritten is not evidence of a decision. Ranex records verdict activity in an append-only hash-chained journal. The design does not turn a local database into an untouchable historical archive. It does give you a concrete way to detect a row edit and a concrete command to check the chain.
In this note
- The record must resist a quiet rewrite
- Two controls cover different paths
- Check the journal you depend on
- The limit is rollback and truncation
The record must resist a quiet rewrite
An append-only journal preserves the sequence of admitted events rather than a polished final summary. That matters when your question is not “what does the database say now?” but “what evidence and verdict existed when this decision happened?”
Ranex’s journal is a SQLite record. Ordinary updates and deletes are prohibited by SQLite triggers. Each journal row also carries a link into a hash chain, so a row has a relationship to the history before it. The operator command ranex journal verify recomputes that chain. Those facts provide a useful control: the normal application path cannot edit or delete a row, and an edit made around that normal path is not supposed to blend into the sequence unnoticed.
Do not reduce this to “there is a database.” A database can retain the latest story while losing the important question. When did the story change, and what did it replace? Append-only changes the shape of what the journal is for. The journal is a record to replay alongside the deterministic verdict path, not a mutable dashboard state that happens to contain audit-looking fields.
This is particularly useful when a worker produces a result you did not watch arrive. Ranex does not take the worker’s summary as proof; it reads the diff on disk and runs checks. The evidence, verdict, and journal give the operator something stronger than a completion message. They give the operator materials to inspect after the excitement has passed.
Two controls cover different paths
SQLite triggers and a hash chain are not duplicates. The triggers block ordinary rewrite attempts; the chain makes an out-of-band row edit visible when verification recomputes the links.
Imagine a program, a stray maintenance script, or an agent with access to the database trying to issue an ordinary update or delete. The SQLite triggers prohibit that normal operation. That is a direct guard where application behavior meets the journal. It helps keep “fix the record” from becoming a casual recovery move.
Now take a different route. An attacker edits the database file outside the normal path. A trigger cannot fire for a change that bypasses the SQL operation it protects. The hash chain is for that case. A changed row breaks the relationship with following rows, and ranex journal verify recomputes the chain for the operator. Verification is the important verb here. A chain nobody checks is only a claim about how rows were written.
There is no magic in the word hash. The value of the design is that it gives you a defined test against a defined class of edits. You can run the verifier instead of accepting an application’s self-description. You can ask whether the record still links as it should. If it does not, the journal has evidence of a problem rather than a quietly amended history.
The repository also says concurrent appenders are serialised before reading the previous link. That keeps append operations from racing into incompatible predecessor links. It is a consistency property for the chain. It is not a claim that the journal has solved every preservation problem, which brings us to the line that needs to stay visible.
Check the journal you depend on
You can apply the lesson before you use Ranex. Find the record your release process calls an audit trail, then ask whether it can tell an edit from an original event.
- Does the normal application path prohibit updates and deletes of decision records?
- Can an operator independently verify the relationship between successive records?
- Does the record name the evidence, subject, and verdict it is preserving?
- Would an edit outside the application leave a detectable break?
- Who can copy, replace, or restore the record store?
- Can a reviewer distinguish a current status from the sequence that produced it?
These questions are the reason the journal exists. Generated work can leave you with more activity than a person can remember. A future reviewer needs to connect a requirement, evidence, the exact artifact evaluated, and the verdict that allowed a next step. The journal is one part of retaining that connection. It does not decide whether the requirement was good; the approved flow graph is intended as the root of trust in the broader designed loop. It retains what the kernel saw and decided.
There is a natural boundary with signed evidence. Signatures establish something about who held a registered private key. The journal records the admitted sequence. Neither control replaces the other, and neither should be stretched into a claim it does not make.
The limit is rollback and truncation
The journal does not detect rollback or truncation. An internally consistent earlier prefix still verifies after later rows are removed.
That is the boundary named in the README’s known gaps. If later rows disappear and the remaining database ends at an older valid point, recomputing the retained chain succeeds. The verifier detects an edited row in the retained history; it does not know, by itself, that history was made shorter. Serialising appenders does not close this gap. Trigger protection does not close it either.
Keep the distinction sharp. “Tamper-evident for out-of-band row edits” is a useful claim. “Permanent history that detects every deletion” is not a claim Ranex makes. The repository’s Status section lists the append-only hash-chained journal as working today and names rollback or truncation as a known gap. The project remains pre-release.
That clarity is better for your incident response. If verification fails, you have a reason to investigate an altered chain. If it passes, you know the retained rows are internally consistent, not that no later history was removed. You can decide what additional retention or external anchoring your own risk requires without pretending the local journal already supplied it.
Questions people actually ask
How does a hash-chained journal detect tampering?
The Ranex journal links each row hash to the previous row, and journal verify recomputes the chain to expose an out-of-band row edit.
Can a hash-chained journal detect deleted entries?
The Ranex journal cannot detect rollback or truncation because an internally consistent earlier prefix still verifies after later rows are removed.
What stops ordinary journal updates and deletes?
Ranex uses SQLite triggers to prohibit ordinary updates and deletes, while the hash chain detects edits outside that normal path.
Try it. Break it. Tell me what broke. Read the Ranex repository, then inspect whether your own audit record can show a rewrite.
Disclosure: this post was drafted with AI assistance. Every factual claim traces to the repository’s README or slice records — the same fact gate the product enforces on code. It ships only after Anthony’s own review.
About the author

Anthony Garces
Anthony Ryan M. Garces is a Senior Principal Lead Architect with 17+ years in IT, including four years at Pantheon on mission-critical platform work. He is building Ranex in public.
Keep reading

Absence Blocks: Why No Evidence Is a Fail, Never a Skip
Why Ranex fails a required claim with no evidence, including why a fresh clone correctly starts with a failing verdict.

Why a Verdict Has to Be a Pure Function
Why a Ranex verdict uses only gate, evidence, subject, and approver so the same proof always gets the same result.

Cause Is Structure, Not Prose
A failure sentence cannot reliably carry its category. Keep the cause as structured data, render the prose from it, and block unknown values.
