# Receipt format written by protect-mcp 0.7.4 The plugin's `sign.sh` hook runs `protect-mcp@0.7.4 sign`, which appends one receipt per line to `./receipts/receipts.jsonl`. Each line is a v2 envelope like this one: ```json { "v": 2, "type": "decision_receipt", "algorithm": "ed25519", "kid": "generated", "issuer": "protect-mcp", "issued_at": "2026-09-26T12:59:48.265Z", "payload": { "tool": "Read", "decision": "allow", "reason_code": "post_execution_receipt", "policy_digest": "none", "scope": "tu-1790427588265-c8x5", "mode": "enforce", "request_id": "tu-1790427588265-c8x5", "spec": "draft-farley-acta-signed-receipts-01", "issuer_certification": "self-signed" }, "signature": "0b5d28f45db30666..." } ``` The receipt records the tool name, and it does not record the tool input or output. The signature covers every other field, so changing `issued_at`, `issuer`, or `payload.decision` after signing makes verification fail. The receipt holds no public key, and `@veritasacta/verify` rejects a key embedded in a receipt. Pass the `publicKey` value from `./protect-mcp.key` with `--key`. The receipts carry no hash of the previous receipt. The verifier checks each signature, so it cannot detect a deleted or reordered line. ## Rotating the signing key Each receipts file verifies against one public key, so the setup command never replaces an existing `./protect-mcp.key`. To rotate the key, first move `./protect-mcp.key` and `./receipts/receipts.jsonl` to an archive, then run the setup command again. Verify the archived receipts with the old public key and the new receipts with the new one.