@mindbender1 min read

Why the changelog is hash-linked

Redundant enforcement, and why the read path verifies rather than a script somebody remembers to run.

There are four places a tampered changelog is caught here, and the redundancy is the point: there is no single check to bypass.

The read path verifies

getChangelog() verifies the chain before it returns anything. Every route that shows a changelog entry goes through it, so a broken chain cannot be built, served, or previewed — prerendering throws instead. A verifier that only runs in a script is a verifier somebody eventually forgets to run.

The build refuses to start

prebuild runs the verifier before next build does anything, which turns a render-time stack trace into a one-line error at the top of the log.

CI checks every push

Including pushes that touch nothing else, with signatures required. The chain is audited against full history, because each seal pins the commit that was HEAD when it was written.

CI checks the diff, separately

Verification proves the chain is internally consistent. It does not prove nobody rewrote an entry and resealed it. So on every pull request, a second job asks git a blunter question: did this change modify, rename, or delete anything under content/changelog/? Adding files is fine. Touching what already exists is not.

The two checks answer different questions, which is why both exist.