Mohamed AjabSoftware / security / dataLet’s talk
Back to the project mapRL / 06 / CASE STUDY
Working developer tool4 min read

RunLedger

Keep experiment records that reveal later edits.

RunLedger links each experiment record to the one before it. If a saved record changes, a verification check can reveal that the sequence no longer matches.

Read the case study
01 / CONTEXT

What this project is about

RunLedger is a compact Python command-line tool that links experiment summaries into a verifiable sequence. A hash is a fixed-length fingerprint calculated from data. Each JSON record stores its own hash and the previous record's hash, making certain edits detectable. The project demonstrates this specific integrity check without requiring a database or external service.

Internal consistency is not the same as trustworthy provenance—evidence of where a record came from. A valid chain means the current records agree with their hashes. It does not prove an experiment happened, that the metrics are correct or that the entire file has not been replaced. Someone controlling every record can recalculate the complete chain.

02 / IMPLEMENTATION

How it works

The workflow, at a glance
  1. Experiment record
  2. Hash-linked entry
  3. Chain verification

Hash content consistently

The hash function excludes the stored sha256 field, converts the remaining values to a standard JSON representation with sorted keys and compact separators, then applies SHA-256 to the UTF-8 bytes. This consistent representation prevents ordinary changes in key order or formatting from changing the record's logical fingerprint.

Check before adding records

Before appending, the tool reads the file, rejects reused run IDs and verifies the existing chain. Each new record contains its run ID, status, metrics, UTC timestamp and previous record's hash. The first record uses a fixed all-zero starting value because it has no predecessor.

Locate an inconsistency

Verification checks records in order, recalculating each hash and checking its link to the previous record. It reports the first mismatching line. Invalid JSON also produces a line-specific error. The command's success or failure exit status allows another program to act on the result without interpreting a human-written report.

03 / REASONING

The important design choices

Keep records readable

Use JSON Lines: one readable JSON record per line in a local file.

The trade-offThe history is easy to inspect and version, but the implementation reads the whole file into memory and does not coordinate programs writing to it at the same time.

Separate integrity from authenticity

Link records without digital signatures or an independent timestamping service.

The trade-offThis exposes inconsistent edits, but cannot prevent a complete rewrite or prove the final stored hash matches an independently trusted original.

04 / WALKTHROUGH

Detect a changed metric

ILLUSTRATIVE EXAMPLE

Create two linked synthetic experiment summaries in a local ledger.

  1. Verify the original file and retain its final hash as a separate reference.
  2. Edit one stored metric without recalculating its hash.
  3. Run verification again and inspect the first mismatch.

What this showsThe verifier detects the inconsistency. If an attacker recalculates every affected hash instead, exposing the rewrite requires a comparison with an independently trusted reference.

Illustrative example, not an additional measured result.

05 / EVIDENCE

How it was tested—and what it shows

The checks

The tests included in the repository check a valid two-record chain, modification of an existing metric and rejection of a reused run ID. They cover basic behaviour, not experiment truth or every case of file corruption, removed records or simultaneous writes.

What to take from the results

The deliverable is an inspectable integrity mechanism, not a measured performance improvement. Hashing and trustworthy provenance solve different problems: editing a metric without updating hashes is detectable, but rebuilding the entire chain is not prevented. Keeping the final hash in an independently protected location would provide an external reference against which later versions could be checked.

06 / BOUNDARIES

What to keep in mind

  • Someone who can replace the whole chain and its reference can create a different history.
  • A consistent record does not prove that its contents are true.

Where the work could go next

Possible next steps—not features or experiments already completed.

  1. Publish final hashes independently or digitally sign them with a protected key, specifying how keys are replaced and signatures checked.
  2. Coordinate simultaneous writers, verify large files incrementally and test removed or reordered records, invalid input and interrupted writes.
07 / REFERENCE

Technical notes & source

Built with

Python · hashing · experiment records

Terms used in this project

Hash
A compact fingerprint calculated from data.