audit-chain — команда для Claude Code: проверка цепочки receipt'ов
Проверяет подписи Ed25519 у всех receipt'ов в receipts.jsonl и показывает строки, которые не прошли. Пригодится перед релизом или аудитом.
/plugin marketplace add wshobson/agents
/plugin install protect-mcp@claude-code-workflowsЧто делает audit-chain
Команда читает receipts.jsonl из ./receipts/ или из каталога, указанного через --dir, и сверяет подпись каждой строки с публичным ключом из ./protect-mcp.key (или из файла, названного в переменной PROTECT_MCP_KEY). Флаг --last N оставляет только последние N строк — удобно, когда файл разросся. При этом нумерация выбранных строк идёт с 1, поэтому команда печатает смещение, которое надо прибавить, чтобы получить номер строки в исходном файле.
Внутри — bash-скрипт, который разбирает аргументы и вызывает npx @veritasacta/[email protected] --replay-chain. Первый запуск скачивает пакет из сети. На машине без интернета поставьте его заранее: npm install --no-save @veritasacta/[email protected], тогда npx возьмёт локальную копию. Ещё нужен Node.js — ключ читается через node -p.
Важное ограничение: receipt'ы protect-mcp 0.7.4 не ссылаются на предыдущую запись. Поэтому удалённую, вставленную или переставленную строку эта проверка не найдёт. Чтобы ловить удаления, держите копию файла там, где оператор не может её изменить. Коды выхода: 0 — всё сошлось, 1 — хотя бы один receipt не прошёл (подпись, битая строка, неверный или отсутствующий ключ, неподдерживаемый алгоритм), 2 — проверку не удалось запустить.
Какие задачи решает
- проверить подписи всех receipt'ов в файле, а не по одному
- найти строку с изменённым после подписи receipt'ом
- показать аудиторам, что журнал не подменяли
- прогнать проверку целостности в CI, чтобы поймать тихое повреждение
- сверить только последние N записей, не читая весь файл
Примеры запросов агенту
- /audit-chain
- /audit-chain --last 50
- /audit-chain --dir /var/log/receipts
Как установить audit-chain
1Через маркетплейс плагинов
/plugin marketplace add wshobson/agents/plugin install protect-mcp@claude-code-workflows2Вручную: положить файлы
.claude/commands/audit-chain.mdВызов — /audit-chain. Для всех проектов — ~/.claude/commands/
Вручную: положить файлы
~/.codex/prompts/audit-chain.mdВызов — /prompts:audit-chain. В Codex этот формат помечен устаревшим, замена — скиллы
Вручную: положить файлы
.github/prompts/audit-chain.prompt.mdВручную: положить файлы
.gemini/commands/audit-chain.tomlGemini хранит команды в TOML: текст запроса — в поле prompt
Вопросы о audit-chain
Как установить audit-chain в Claude?
Добавьте маркетплейс: /plugin marketplace add wshobson/agents, затем поставьте плагин: /plugin install protect-mcp@claude-code-workflows. Команда появится как .claude/commands/audit-chain.md.
Что делает audit-chain?
Читает receipts.jsonl, сверяет подпись Ed25519 каждой строки с публичным ключом и печатает номера строк, которые не прошли проверку.
Поймает ли команда удалённую строку?
Нет. Receipt'ы protect-mcp 0.7.4 не связаны с предыдущей записью, поэтому удаление, вставку или перестановку строк так не увидеть. Держите неизменяемую копию файла отдельно.
Исходный текст
audit-chain.md · MIT
---
description: "Verify every receipt in ./receipts/receipts.jsonl against the signer's public key. Detects tampered or malformed receipts across the audit trail."
argument-hint: "[--last N] [--dir path]"
---
# Audit Chain
Verify every receipt in the audit trail, not just a single receipt.
protect-mcp 0.7.4 appends receipts to `receipts.jsonl` in `./receipts/` (or
the specified directory), one per line, and this command checks the signature
on each line.
## Usage
```
/audit-chain # Verify all receipts in ./receipts/
/audit-chain --last 50 # Verify only the last 50 receipts
/audit-chain --dir /var/log/receipts # Use a different directory
```
## What This Command Does
1. Reads `receipts.jsonl` in the target directory
2. Keeps only the last N lines when `--last N` is given
3. Verifies each Ed25519 signature against the `publicKey` value in
`./protect-mcp.key` (or the file named by `PROTECT_MCP_KEY`)
4. Reports the line number of each receipt that fails. With `--last N`, the
verifier numbers the selected lines from 1, so the command prints the
offset to add to get the line in `receipts.jsonl`
protect-mcp 0.7.4 receipts carry no link to the previous receipt, so this
check cannot detect a deleted, inserted, or reordered line. To detect deleted
lines, keep a copy of the receipts file where the operator cannot change it.
## Implementation
```bash
RECEIPT_DIR="./receipts"; N=""
while [ $# -gt 0 ]; do
case "$1" in
--last|--dir)
if [ $# -lt 2 ]; then
echo "usage: /audit-chain [--last N] [--dir path]" >&2; exit 2
fi
if [ "$1" = "--last" ]; then
case "$2" in
''|*[!0-9]*) echo "--last takes a positive whole number" >&2; exit 2 ;;
esac
N="$2"
else
RECEIPT_DIR="$2"
fi
shift 2 ;;
*) shift ;;
esac
done
FILE="$RECEIPT_DIR/receipts.jsonl"
if [ -n "$N" ]; then
N=$((10#$N))
[ "$N" -gt 0 ] || { echo "--last takes a positive whole number" >&2; exit 2; }
TOTAL=$(wc -l < "$FILE"); OFFSET=$(( TOTAL > N ? TOTAL - N : 0 ))
echo "Checking lines $((OFFSET + 1)) to $((TOTAL)). Add $OFFSET to each reported line number."
TMP="$(mktemp)"; tail -n "$N" "$FILE" > "$TMP"; FILE="$TMP"
fi
PUB=$(node -p 'JSON.parse(require("fs").readFileSync(process.env.PROTECT_MCP_KEY || "./protect-mcp.key")).publicKey')
npx @veritasacta/[email protected] --replay-chain "$FILE" --key "$PUB"
```
Exit 0 means every receipt verified. Exit 1 means at least one receipt
failed, because it was tampered with, a line is malformed, the key is wrong or
missing, or the algorithm is unsupported. With `--replay-chain`, the verifier
reports those cases per line with exit 1. Exit 2 means the check could not
run, e.g., because the file could not be read or an option had no value.
`npx` downloads `@veritasacta/[email protected]` the first time it runs. For an
offline machine, install it in the project first with
`npm install --no-save @veritasacta/[email protected]`, and `npx` then runs the
local copy without network access.
## What to Show the User
### All receipts verify
```
Audit verification: PASSED
Scanned: 247 receipts in ./receipts/receipts.jsonl
Signatures: 247/247 valid ✓
Key: 0faf558a90dfbf88...
All 247 receipts verify. A deleted or reordered line would not show here,
because 0.7.4 receipts carry no link to the previous receipt.
```
### Tampered receipt
```
Audit verification: FAILED
Scanned: 247 receipts
Signatures: 246/247 valid (1 failed)
FAILED at line 89: invalid_signature
Request: tu-1790427588265-c8x5
Tool: Bash
Issued at: 2026-09-26T14:22:01Z
The signature on this line does not verify, so the receipt was modified
after signing, or the key is not the signer's key. Compare the line against
a known-good copy to find the altered field.
```
## When to Run This
- Before shipping a release, to confirm that no development receipt was altered
- During security audits, to show auditors that every receipt verifies
- After incidents — verify logs were not tampered with during the incident
- Periodically — CI/CD job to catch silent corruption
- Before compliance reviews — provide evidence of continuous integrity
## References
- [@veritasacta/verify on npm](https://www.npmjs.com/package/@veritasacta/verify)
- Use `/verify-receipt` for single-receipt verification
© Tom Farley · MIT · wshobson/agents