simbiot-harness/docs/audit.md

71 lines
No EOL
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Криптографический аудит харнеса (t-260930083716)
Запрос Alex (m-516173240): у харнеса свой приватный ключ; каждое событие
стора и каждая команда подписаны. Цели: полная аудируемость, доказуемое
авторство («сделал харнес»), защита стора и командной шины от инъекций.
## Схема
- **Алгоритм:** ed25519 (библиотека `cryptography`).
- **Ключи:** прив. `/root/simbiot-harness/.audit/ed25519.key` (0600, создан
атомарно tmp+rename), публ. рядом `ed25519.pub` (0644, отдавай внешним
аудиторам). `key_id` = первые 16 hex sha256 от публ. ключа.
- **Активные ключи (созданы 2026-10-02):**
- pubkey (raw b64): `P8puVpwg9UtKtEnYUKCCGz/NA4zXU1ubgkdurp2V+CY=`
- key_id: `faf8d19d9aed71fe`
## Что подписывается
1. **События стора** — `es.append_event` подписывает каждое событие при
записи. Плайлоад: `aggregate|aggregate_id|event_type|canonical_json(data)|
timestamp|version|prev_sig|key_id` (`\x1f`-сшит). В колонки события
пишутся `sig, key_id, prev_sig`.
2. **Тампер-цепочка:** `prev_sig` каждого события = подпись предыдущего —
переписать середину стора, не сломав голову цепочки, нельзя.
3. **Команды CLI** — `cli.py audit-command '{"op":…}'` → конверт
`{envelope, payload_b64, signature, key_id}`; вход в командную шину
верифицируется `cli.py verify-command` (выход 0/2).
## Верификация
- `cli.py verify` — полный аудит цепочки (выход 0/2): криптопроверка
каждой подписанной строки + link-check `prev_sig`. Может выполнять
любая внешняя сторона с публичным ключом.
- Проекции (`es.run_projections`) проверяют хвост-дельту: событие с битой
подписью или разрывом цепочки ⇒ RuntimeError — подделка не попадает в
read model (проверено тестом).
- `cli.py audit-key` — публичный ключ/отпечаток/пути.
## Граница доверия: genesis и legacy
- Все события **до** внедрения подписи (2026-10-02, 465 255 шт.) помечены
ретро-маркером `sig='genesis:<id>'` (водяной знак `projection_meta.
sig_genesis_upto` — раз и навсегда). Это честная граница: до неё
авторство не доказывалось криптоключом.
- Подписанная строка после границы, чей `prev_sig` указывает на дого-
генезисное состояние, не бракуется по link-check (граница сбрасывает
проверку сцепки), но её payload-подпись строго проверяется — контент
послегенезисной строки тамперить нельзя.
- Неподписанные послегенезисные строки (старый код демонов до их рестарта)
= `legacy`: аудит их считает, ошибкой является только тампер
**подписанной** строки. После рестарта сервисов (просьба к Alex в
дайджесте дня) всё новое гарантированно подписано.
## Инвариант защиты
| Атака | Чем ловится |
|---|---|
| Правка data/timestamp события | подпись payload (verify) |
| Правка middle-строки всего стора | подпись + цепочка (full audit) |
| Вставка фейкового события | нет валидной подписи → legacy-статус, но не «валидный харнес»; в хвосте проекций — RuntimeError |
| Подмена команды | конверт-подпись (verify-command) |
| Кража подписи | плайлоад привязан к содержимому; ключ 0600 |
## Файлы
- `harness/audit.py` — ключи, каноника, sign/verify, командные конверты
- `harness/es.py` — миграция (sig-колонки/genesis), подпись в
`append_event`, хвост-верификация в `run_projections`
- `cli.py` — `verify`, `audit-command`, `verify-command`, `audit-key`
- Тест: `tests/test_audit.py` (17 проверок, hermetic: тампер/genesis/
legacy/конверты/CLI)