How the paid file is made ========================= Two claims on this site are the kind that ought to be checkable rather than believed. This note says exactly what we do, and points at the code that does it, so you can check both without taking our word for anything. 1. The paid file is generated from the demo file ------------------------------------------------ The journal you can try at /demo and the journal you receive when you buy are not written separately and then compared. The paid file is produced *from* the demo file by a script, every time we cut a release: scripts/build-journal-shipping.mjs published verbatim at /verification/build-journal-shipping.txt The script reads public/demo-app/index.html, removes exactly two things, and writes release/The_Eternal_Journal.html. Those two things are the only permitted differences between the two files: (a) one CSS declaration setting the caret colour, which exists only because the demo runs inside an iframe on this site; (b) the demo bootstrap script block, which loads the sample entries and allows the short passphrase "demo". Nothing else is added, removed, or rewritten. The script then greps the output for any surviving demo-only identifier (demoBoot, seed.json, the short passphrase flag) and refuses to write the file if it finds one. So the parity claim is not a promise we make. It is a property of how the file is built: the paid file cannot contain anything the demo does not contain, because it is the demo with two known blocks cut out. The SHA-256 of every released file is published at /downloads/SHA256.txt. You can hash your own copy and compare. 2. The base64 fix is covered by a regression test -------------------------------------------------- Before v2.0.3 the encoder used a single spread call, which threw a RangeError on large attachments. It was replaced with a chunked encoder. The test suite that covers this is published verbatim at: /verification/base64-regression-test.txt (source: src/__tests__/journal-v203.test.ts) It runs 17 round-trip cases from 0 bytes to 8193 bytes -- deliberately straddling the chunk boundary -- plus a 1 MB buffer, which is the size class that broke the old encoder. For every input below the old encoder's failure threshold, the new encoder's output is asserted byte-identical to the old one's, so the fix changes what the code can survive without changing what it produces. Old data decodes exactly as it did before. If you find either claim to be untrue, write to hello@offline.ltd and we will correct it here in public.