Keep a clear record.
Hand it over in one file.

Log each call, letter, chat, or denial from an automated government system. When you are ready, export one ZIP with a plain cover page a lawyer can read in 90 seconds.

1 · Your cases

You can keep more than one case. Each case has its own independent hash chain. Your words stay on this device only — there is no account and no server. Data is stored in this browser's IndexedDB database.

Storage: checking…

All cases on this device

No case saved yet. Save a case to start the hash chain.

2 · Log an entry

Aim for under a minute. You only need what happened, when, and what the system said.

Each file is hashed with SHA-256 and the hash goes into this entry's chain record. The file itself is stored only in this browser, on this device. You can also attach files to an entry later from the timeline — that adds an edit record carrying the new hashes.

3 · Timeline

Each entry gets an Entry ID and a place in a hash chain. If one entry is changed later, the chain no longer matches. Edits and deletions are chain records too: an edit adds a new position holding only what changed, and a deletion removes the entry's content from this device but keeps every position's hash, so the chain still replays.

No entries yet. Log your first entry above, or load the sample case below.

    What may be missing

    Chain verification

    Replays the chain in position order: records with content are re-hashed and checked; positions whose content was deleted are checked by link continuity only (the next record's previous-hash must equal the hash kept for that position). The head must equal the last position's hash.

    4 · Export & cold read

    The ZIP holds three things: packet.pdf (the cover plus the full timeline), packet.json (the full record in PTPF 1.0, listed in chain-position order), and an attachments/ folder holding the actual attached files. Keep the exact file you export — the hash proof only matches those exact bytes.

    Attachment storage

    No attachments stored.

    This proves this packet existed by this date. It does not prove its contents are true.
    Keep this exact file. A re-export is a different file and will not match this hash.

    If you set a passphrase, the whole ZIP is sealed with the same B6 encryption as backups (Argon2id + AES-256-GCM, chunked) and downloads as a .zip.ptpf file instead; whoever opens it needs this passphrase and TrailKept — step 5 below opens it. A packet passphrase is for this export only, and it can never be your backup passphrase: type that here and the export is refused.

    Cold read — can a new reader answer these in 90 seconds from the packet (cover + timeline pages)?

    1. Who are the parties in this case?
    2. What was denied?
    3. Why was it denied?
    4. What is the deadline?
    5. What has the claimant already tried?

    The fixture is a made-up sample case (5 entries). Expected answers, from the packet (cover + timeline pages): 1) Elena Ruiz, claimant — County Benefits Office. 2) Food benefits (SNAP). 3) The latest denial (Entry 4): residency paperwork was missing — the lease copy was not on file. 4) Dec 1, 2026. (That the date is based on the notice, and that the appeal is in writing, is extra detail on the timeline pages — not required for this answer.) 5) Applied online (Entry 1), called the office (Entry 3), then appealed in writing with the missing paperwork (Entry 5). The fixture also triggers all five missing-item flags: no reference number (Entry 2), no deadline (Entry 2), no denial reason (Entry 2), no file attached to a denial (Entries 2 and 4), and an entry logged more than 7 days after it happened (Entry 3, logged 8 days later).

    5 · Encrypted backup & restore

    A packet (step 4) is one case, made to hand to someone. A backup is different: every case on this device — all records and all attached files — sealed into one encrypted file that only your backup passphrase can open. Keep the backup file somewhere off this device (a USB stick, a computer, a cloud folder you trust): if this browser's data is cleared, the backup is how everything comes back.

    Encryption self-checks: running…

    Make a backup

    If you forget this passphrase, the backup cannot be opened — by anyone, including you. There is no reset, no recovery, and no copy kept anywhere: the passphrase is never stored, only the file it sealed. Use a passphrase for TrailKept backups and nothing else. The backup uses the B6 format: an Argon2id key (19 MiB, 2 passes) and AES-256-GCM encryption in 1 MiB chunks.

    Restore from a backup — or open an encrypted packet

    Restoring a backup replaces everything on this device — all current cases are removed and the backup's cases take their place. Nothing is merged. Before anything is replaced, the file's format version is read from its plain header (a file from a newer TrailKept is refused before you are ever asked for a passphrase), then every case's chain is recomputed and checked against the backup's recorded heads. If anything fails, nothing is imported. An encrypted packet (.zip.ptpf) opens here too — it just downloads the ZIP inside and changes nothing.

    6 · Standalone verifier & D1 test vector

    The D1 test vector is a fixed case built only from fixed inputs — fixed case ID, timestamps, and record salts; no random values and no real clock — so its chain head must come out identical every run. The standalone verifier is a second, separate implementation of PTPF verification (written from spec sections B2+B3+B7, with its own canonicalizer): it checks an unencrypted packet — packet.json plus its attachments — position by position, and either says VERIFIED or names each failure. It shares no code with the chain code above, so a bug in one cannot hide in the other.

    D1 test vector

    Recorded expected head: computing…

    Verifier checks

    Runs the standalone verifier on four packets that must verify — the D1 vector's packet, the same D1 packet with every string carried in decomposed (NFD) form, a Case A fixture packet, and a redacted Case A packet (Entry 4 withheld, so its positions are hash-only placeholders) — and three packets that must fail: a Case A packet with one content character changed, a D1 packet whose tombstone placeholder carries an extra key, and a D1 packet whose tombstone placeholder is missing its deletedAt.

    Verify a packet you have

    Choose a packet.json from an unencrypted export, plus the files from its attachments/ folder (if any). Nothing is uploaded — the check runs on this device.

    7 · App lock & erase

    TrailKept has three separate credentials, and they must never be the same: your app lock passcode (opens this app on this device), your backup passphrase (step 5 — opens a backup file), and a packet passphrase (step 4 — seals one export). Setting any one of them to match another is refused.

    App lock: checking…

    Set an app lock passcode (optional)

    With a lock on, the app opens to a lock screen and your stored records are encrypted on this device — each stored record is encrypted on its own with AES-256-GCM and a fresh random nonce, under a key derived from your passcode (Argon2id). Unlocking decrypts into memory only; the passcode itself is never stored.

    Warning: a forgotten lock passcode is UNRECOVERABLE. There is no reset and no way back in — not for you, not for anyone. Before you rely on the lock, make an encrypted backup (step 5) and save it off this device, so a forgotten passcode does not mean losing your records. You do not have to set a lock now: you can skip it and turn it on here later.

    Erase everything

    Erase Everything permanently deletes all cases on this device — every entry, edit, attachment, tombstone, and withheld/redaction record — plus all credentials and keys (app lock, backup fingerprint, backup status). It permanently ends verifiability: once the chains and their hashes are gone from this device, no packet head stored only here can ever be verified again, and deleted entries' tombstones are removed too — this is the only way tombstones are removed. If you have an exported ZIP or an encrypted backup saved off this device, those files still exist; everything on this device does not.