HOW TO CHECK THIS FILE

1. Unzip it, open a terminal in the unzipped folder, and run

     node verify/verify-chain.mjs

   (Node.js 18 or later; the script has no dependencies and reads only this folder.)

   It checks that
     - every file matches the sha256 the manifest gives for it;
     - every event in 11-chain-of-custody/events.json hashes to its row_hash:
         row_hash = sha256_hex( prev_hash || "|" || canonical )
         canonical = "tev1|" + organization_id + "|" + chain_seq + "|" + engagement_id + "|"
                     + kind + "|" + tier + "|" + rule_id + "|" + outcome + "|" + occurred_at
       with empty strings for nulls, and occurred_at in UTC as YYYY-MM-DDTHH:MM:SS.ffffffZ;
     - every link of the spine (11-chain-of-custody/spine.json) names the previous link's hash, from
       position 1 to the head in manifest.json.

2. Ask the institution for the manifest sha256 it recorded when it cut this file,
   and compare it with the value the script prints. The institution can also
   check the manifest against its live chain from the Portfolio
   (POST /api/portfolio/examiner-file/verify), which reports whether every link
   in this file is still the link the platform holds today.

The spine carries hashes only for events that concern other merchants; their
content is not in this file. The chain is the institution's own and covers
every event on its trail, so a removed or altered event anywhere breaks it.
Rows chained when the chain was introduced (chained_at earlier than their
first appearance here) are attested from that moment on.
