Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/bkuan001/halo-record
ФорензикаБезопасность Цепочки ПоставокРеагирование на ИнцидентыБезопасность ИИ
GitHubbkuan001/halo-record

halo-record

Защищённые от несанкционированного вмешательства журналы аудита для ИИ-агентов: связанные хэш-цепочкой записи Runtime Records, без зависимостей, проверяемые кем угодно.

Репозиторий
63610224 дней назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Сайт
Поделиться
# halo-record

**Аудит-трейлы для AI-агентов с защитой от подмены** — Runtime Records, связанные хеш-цепочкой и отображаемые в виде Runtime Report, который ваши клиенты могут проверить сами.

Каждое действие, фиксируемое вашей инструментацией (вызовы инструментов, вызовы моделей, доступ к данным, подтверждения), становится одной **Runtime Record** в журнале, доступном только для добавления и связанном хеш-цепочкой; **Runtime Report** — это та же цепочка, отрендеренная в виде HTML-страницы, которая пересчитывает хеш-цепочку в браузере читателя и отображает то, что показывает, на основе проверенных ею записей (для проверки, не полагающейся на код самой страницы, запустите `halo verify` на JSONL). Любая сторона, владеющая контрольной точкой цепочки, может убедиться, что записи вплоть до этой контрольной точки не были изменены с момента её создания, не доверяя тому, кто их создал — эта контрольная точка является несущим элементом: одна лишь цепочка обеспечивает защиту от подмены для всех, кроме стороны, управляющей регистратором ([LIMITS.md §1](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md)). Когда служба безопасности клиента спрашивает: «что ваш агент делал с нашими данными?», вы отправляете им ссылку вместо абзаца текста. Проверки безопасности уже включают вопросы об AI рядом с чек-листом SOC 2 — и всё чаще эти вопросы исходят из ISO 42001, статей EU AI Act о ведении записей и собственных опросников клиентов. Сегодня письменное заверение всё ещё проходит. Ставка этого проекта в том, что так будет недолго.

**Упоминается в [Help Net Security](https://www.helpnetsecurity.com/2026/08/31/halo-record-open-source-ai-agent-audit-trail/)** (август 2026).

Формат записей открыт и свободен для реализации. Этот пакет — эталонная реализация: регистратор, верификатор, клиент-свидетель и сервер отчётов.

> **Используете halo-record или думаете об этом?** Расскажите, кто вы и для чего → [Кто использует halo-record?](https://github.com/bkuan001/halo-record/discussions/7)

## Проверьте сами

Вас просят внедрить регистратор внутрь вашего агента. Не стоит принимать это на веру:

- **Ноль зависимостей времени выполнения.** Только стандартная библиотека. `pip install halo-record` устанавливает ровно один пакет.
- **Никаких сетевых вызовов**, кроме четырёх опциональных — привязка к свидетелю (отправляет id субъекта, количество записей и два отпечатка цепочки — голову и корень цепочки), чтение контрольных точек свидетеля обратно (отправляет id субъекта), метка времени RFC 3161 (отправляет только хеш состояния контрольной точки в Timestamp Authority) и `halo serve --verify-email` (отправляет одноразовый код и имя субъекта отчёта по SMTP через сервер, настроенный в `$HALO_SMTP_HOST`, на адрес, введённый просматривающим отчёт). Все они отключены, пока вы их не вызовете; никакое другое содержимое записей не покидает вашу инфраструктуру.
- **Сырые аргументы инструментов хешируются, рядом — отредактированная сводка.** Аргументы хранятся как канонический хеш плюс сводка: текст аргументов с маскированием известных шаблонов секретов и PII, обрезанный до 200 символов. Короткий ввод, не совпадающий ни с одним шаблоном, попадает в сводку целиком; режим только хешей (`summaries=False`) не сохраняет сводку вовсе. Редактирование выполняется по мере возможностей (регулярные выражения по распространённым форматам секретов и PII плюс энтропийный перехватчик): относитесь к этому как к дополнительному уровню защиты, а не как к гарантии. Поля результата, которые вы передаёте помимо `summary`, сканируются и маскируются теми же шаблонами, но не обрезаются до 200 символов (LIMITS §13).
- **Достаточно мал, чтобы его можно было проверить.** ~8 700 строк Python, включая встроенные JavaScript и CSS страницы отчёта (строки кода, без учёта пустых строк, комментариев и docstring). Прочитать всё можно за день.
- **Apache-2.0.**
- **Документация первостепенна.** [LIMITS.md](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md) (что цепочка не может доказать), [PRIVACY.md](https://github.com/bkuan001/halo-record/blob/main/PRIVACY.md) (что содержат записи и что покидает вашу машину), [RETENTION.md](https://github.com/bkuan001/halo-record/blob/main/RETENTION.md) (работа в условиях политики хранения) и [REVIEWERS.md](https://github.com/bkuan001/halo-record/blob/main/REVIEWERS.md) — независимая проверка из четырёх команд плюс формат цитирования для результатов проверки.

Что доказывает каждый уровень — несущее различие в этом проекте ([LIMITS.md §1](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md)): цепочка, которую вы храните сами, доказывает, что записи не были **отредактированы**, относительно головы, которая уже есть у кого-то; только контрольные точки, хранящиеся вне оператора, доказывают, что ни одна не была **удалена**; и никакой хеш не доказывает, что каждое действие было **зафиксировано**.

| Утверждение | Собственная цепочка | + Внешние контрольные точки | + Доверенная фиксация |
|---|---|---|---|
| Обнаружение правок в установленном артефакте | ✔ | ✔ | ✔ |
| Обнаружение перезаписи зафиксированной истории | — | ✔ | ✔ |
| Обнаружение отсутствующих/запоздалых контрольных точек | — | ✔ (согласованная периодичность) | ✔ |
| Доказательство, что каждое действие было записано | — | — | зависит от границы фиксации |

**Посмотрите до установки:** [пример Runtime Report](https://bkuan001.github.io/halo-record/sample-report.html) — вымышленные данные, настоящая цепочка, и его скрипт пересчитывает хеш-цепочку встроенных записей в вашем браузере при открытии.

## Демо за 60 секунд

Агент не нужен. С [uv](https://docs.astral.sh/uv/) устанавливать ничего не требуется:

```
uvx --from halo-record halo demo --serve
```

или классическим способом:

```
pip install halo-record
halo demo --serve
```

Либо создаёт вымышленного поставщика support-агента с двумя клиентами, фиксирует цепочки (с локальным файлом-свидетелем, заменяющим одного внешнего по отношению к оператору — см. [LIMITS.md §1](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md)), выдаёт их защищённые Runtime Reports и открывает консоль оператора в вашем браузере. Затем попробуйте тест на подмену: удалите строку из одного из файлов `.jsonl` и перезагрузите. Отчёт это обнаружит.

## Запишите собственного агента

Одна строка на границе:

```python
from halo_record import trace

agent = trace(run_my_agent, profile="my-agent", log="audit.jsonl")   # wraps your entrypoint; records the run boundary to ./audit.jsonl — add record_call() or a framework adapter at each tool boundary to capture individual calls
```

Удобный shim `from halo import ...` также поставляется — но имя `halo` на PyPI принадлежит не связанному с ним пакету терминального спиннера, и если этот пакет установлен, он выигрывает импорт. `halo_record` однозначен, поэтому в примерах используется он.

Без `log=` записи попадают в `~/.halo/my-agent.jsonl` (одна цепочка на агента). Обёртка фиксирует границу запуска; доказательства содержатся в записях отдельных вызовов. Захватывайте их с помощью адаптера фреймворка (матрица ниже) — или явно, что также показывает, как связываются делегирования:

```python
from halo_record import Recorder, record_call

rec = Recorder("audit.jsonl")

with record_call(rec, "crm.lookup", {"account": "acct-9"}) as call:            # one sealed record per tool call
    call.result = crm.lookup("acct-9")

with record_call(rec, "payments.refund", {"amount": 120},
                 parent_id=rec.last_record_id()) as call:                      # child links to the action that spawned it
    call.result = payments.refund(120)
```

Затем сформируйте отчёт:

```
halo report audit.jsonl -o report.html    # one chain -> HTML that re-verifies in the browser
halo serve ./records --port 8721          # all tenants, gated per customer
```

Обновление каталога, впервые обслуживаемого версией 0.2.45? `halo serve` перечитывает каждое ранее выданное разрешение при запуске. Разрешение на файл, записи которого не содержат идентификатора субъекта (обычный файл `Recorder`, например `agent.jsonl`), помещается в карантин и выводится при каждом запуске вместе с командой `halo grant`, которая его переиздаёт — см. [LIMITS.md §17, "Serving a directory first served by 0.2.45"](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md#17-one-chain-file-per-subject).

Быстрый старт заканчивается, когда вы смотрите на Runtime Report вашего собственного агента в браузере. Если вы получили файл JSONL и никакого отчёта, что-то не так: откройте issue.

### Блок верификации

Если слой guardrail или политики проверил действие, его вердикт может быть прикреплён к записи — необязательный блок, фиксирующий решение шлюза, запечатанный в хеш-цепочку, как и любое другое поле:

```python
from halo_record import build

build("tool_call", "security", tool="payments.refund",
      verification={"status": "allowed", "verifier": "gate/1.2",
                    "policy_ref": "sha256:1f3a...",
                    "checked_at": "2026-08-01T12:00:00Z"})
```

Одно замечание по именованию: пакет экспортирует *функцию* `record` (декоратор), которая затеняет *модуль* `halo_record.record` в объекте пакета. Импортируйте напрямую из пути модуля, когда вам нужны его внутренности — `from halo_record.record import build` — а не `import halo_record.record as record`.

что запечатывается в запись как:

```json
"verification": {"status": "allowed", "verifier": "gate/1.2", "policy_ref": "sha256:1f3a...", "checked_at": "2026-08-01T12:00:00Z"}
```

`record_call(...)` принимает тот же ключевой аргумент `verification=`. `status` обязателен внутри блока; `verifier`, `policy_ref` и `checked_at` необязательны. Что означает каждый статус:

| Статус | Что сообщает шлюз | Выполнилось ли действие? |
|---|---|---|
| `allowed` | он разрешил действие | да — действие продолжилось |
| `blocked` | он запретил действие | определяется интеграцией, а не этим полем — запись всё ещё может содержать результат, и блокировка сама по себе не доказывает невыполнение |
| `modified` | он изменил действие перед выполнением — `action.input` описывает действие **в том виде, в котором оно было выполнено**, после изменения | да, в изменённой форме |
| `unverified` | он выполнился (или был задействован), но не вынес решения — отличается от отсутствующего блока, который означает, что заявление о верификации вообще не делалось | да — действие продолжилось без вердикта |

Блок предоставляется кодом интеграции оператора и фиксирует то, что, по его сообщению, сказал шлюз — та же модель доверия, что и у `principal` (см. [LIMITS](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md#11-verification-status-is-the-gates-report-not-halos-finding)). Запечатывание доказывает, что статус не был изменён задним числом; оно не доказывает, что проверка состоялась, что вердикт был правильным или что заблокированное действие не выполнилось. Это не независимая верификация.

Чтобы `policy_ref` можно было использовать как доказательство, используйте хеш содержимого набора правил и сохраняйте артефакт набора правил — неразрешимая метка делает это поле декоративным.

## Подключение к тому, что вы уже используете

| Захватывается на границе | Загружается из существующей телеметрии |
|---|---|
| Встроенный регистратор (`from halo_record import trace`) | Спаны OpenTelemetry GenAI |
| Перехватчик MCP | Колбэки LiteLLM |
| Колбэк LangChain / LangGraph | Экспорт Langfuse |
| Хуки OpenAI Agents SDK | Любой лог шлюза / обратного прокси |
| Хук Claude Agent SDK | Хуки `PostToolUse` Claude Code и Codex CLI (срабатывают после выполнения инструмента) |

Адаптеры фреймворков и пути загрузки помечают каждую запись тегом `source`, поэтому отчёт раскрывает, как был собран каждый фрагмент доказательств. Захваченные и загруженные записи находятся в одной цепочке.

Для LangChain / LangGraph это обработчик колбэков:

```python
from halo_record import Recorder
from halo_record.integrations.langchain import HaloCallbackHandler

recorder = Recorder("audit.jsonl")
result = my_chain.invoke(inputs, config={"callbacks": [HaloCallbackHandler(recorder)]})   # every tool call becomes a record
```

Для MCP один вызов оборачивает клиентскую сессию — и затем *любой* агент, использующий MCP, генерирует записи для каждого вызова инструмента, независимо от того, какой фреймворк им управляет:

```python
from mcp import Client   # mcp 2.x
from halo_record import Recorder
from halo_record.integrations.mcp import instrument_client_session

async def run(server):   # an MCPServer, a server URL, or stdio parameters
    async with Client(server) as client:
        instrument_client_session(client, Recorder("audit.jsonl"), server="stripe")
        await client.call_tool("charge", {"customer": "cus_123", "amount": 500})   # recorded
```

Каждый вызов `call_tool()` на обёрнутом клиенте записывается, а инструмент, возвращающий результат с ошибкой, помечается как `error` (адаптер читает как `isError`, так и `is_error` из mcp 2.x). В mcp 1.x передавайте инициализированный `ClientSession` вместо `Client`; обёртка та же.

Для логов шлюза или прокси (Cloudflare AI Gateway, Portkey, nginx перед моделью) сопоставьте строку лога с цепочкой — явно помеченную как полученную из внешнего источника, а не захваченную на границе:

```python
from halo_record.integrations.gateway import record_log

record_log(Recorder("audit.jsonl"), {"tool": "gen_ai:gpt-4o", "model": "gpt-4o", "status": 200, "subject": "acme-corp"})
```

Всё, что генерирует спаны OpenTelemetry GenAI (CrewAI, LlamaIndex и большинство агентных фреймворков с OTel-инструментацией), попадает в цепочку через OTel-адаптер, а [пакет TypeScript](https://github.com/bkuan001/halo-record-ts) поставляется с нативными адаптерами для Vercel AI SDK и JS-экосистемы агентов. Нет адаптера для вашего стека? Откройте issue. Большинство адаптеров — около сотни строк.

## Записывайте своего кодирующего агента (Claude Code или Codex)

Claude Code вызывает хук `PostToolUse` после каждого вызова инструмента. Направьте его на `halo hook`, и каждое действие — запись файлов, shell-команды, вызовы MCP-коннекторов — становится записью в локальной цепочке. Без изменений кода; одна запись в настройках:

```json
{
  "hooks": {
    "PostToolUse": [
      {"matcher": "*", "hooks": [{"type": "command", "command": "halo hook"}]}
    ]
  }
}
```

Добавьте это в `~/.claude/settings.json`, и записи будут попадать в `~/.halo/audit.jsonl` (переопределяется через `$HALO_LOG`). Инструменты чистой оркестрации, которые не касаются данных, сети или внешнего состояния, пропускаются — цепочка фиксирует действия на границах доверия, а не размышления. Установите `HALO_HASH_ONLY=1`, чтобы записывать хеши содержимого без сводок. Установите `HALO_AGENT_VERSION` (и, при необходимости, `HALO_AGENT_MODEL`), чтобы привязать каждую запись к сборке агента, которая её создала — когда аудитор спросит о версии, работавшей в заданном окне, экспорт ответит по столбцу, а не по памяти.

Codex CLI поставляет те же хуки жизненного цикла с той же формой событий (хуки включены по умолчанию). Добавьте это в `~/.codex/hooks.json`, и shell-команды Codex, правки через `apply_patch` и вызовы MCP попадут в ту же цепочку:

```json
{
  "hooks": {
    "PostToolUse": [
      {"matcher": ".*", "hooks": [{"type": "command", "command": "halo hook"}]}
    ]
  }
}
```

Хук различает их по самому событию (Codex добавляет `turn_id` и `model`) и помечает каждую запись как `claude-code` или `codex`; задайте `HALO_HOOK_AGENT`, чтобы принудительно выбрать один из них. Оба относятся к уровню ingested: хук `PostToolUse` срабатывает после выполнения инструмента, поэтому запись строится из того, что сообщает харнесс.

Если нужно, чтобы отчёт отвечал на вопрос «по каким правилам выполнялся этот запуск?», задайте `HALO_AUTHORITY_FILE` как JSON-снимок действующих полномочий для сессии. Держите его безопасным с точки зрения приватности: хеши и ссылки, а не сырые промпты, текст приватных политик, секреты или полные схемы инструментов — известные форматы секретов и персональных данных маскируются в момент запечатывания, но хеши и ссылки проходят без изменений, а свободный текст не обнаруживается (см. LIMITS §6). Повторно используйте `snapshot_id` только пока лежащие в основе полномочия не изменились; последовательные записи с одинаковым id и неизменным содержимым компактируются — повторно использованный id при изменённом содержимом сохраняется полностью, с уведомлением.

```json
{
  "snapshot_id": "auth_2026_07_08T1100Z",
  "captured_at": "2026-07-08T11:00:00Z",
  "scope": "session",
  "workspace": {"path_hash": "sha256:...", "git_commit": "abc1234"},
  "refs": [
    {"kind": "project_rules", "id": "CLAUDE.md", "hash": "sha256:...", "loaded": true, "truncated": false},
    {"kind": "mcp_tool_registry", "id": "filesystem", "hash": "sha256:..."}
  ],
  "omissions": [{"kind": "private_policy", "reason": "customer_secret", "hash": "sha256:..."}],
  "stale_if": ["project_rules_hash_changed", "mcp_tool_registry_hash_changed"]
}
```

```sh
HALO_AUTHORITY_FILE=./authority.json halo hook
```

Снимок запечатывается в ту же хеш-цепочку, что и записи действий. Хорошим значением по умолчанию является один снимок уровня сессии в начале, плюс новый снимок при изменении правил, Skills, хуков, реестров инструментов MCP или политики компакции. Чтобы длинные сессии оставались компактными, последовательные записи с одинаковым `authority.snapshot_id` компактируются после первого полного снимка: последующие записи сохраняют только `{"snapshot_id": "...", "same_as_previous": true}`. Указатель остаётся в хеш-цепочке, но громоздкий блок refs/omissions/stale-if не повторяется при каждом действии. (Компакция выполняется для каждого процесса-рекордера: захват в стиле хуков, порождающий один процесс на каждый вызов инструмента, заново сохраняет полное тело всякий раз, когда предыдущий полный снимок не является последней записью, поэтому короткоживущие процессы обменивают размер цепочки на защиту от повторного использования.)

Пользователи SDK прикрепляют тот же блок напрямую — `build(..., authority={...})` или `record_call(..., authority={...})`; захват только хеша использует ту же поверхность (`summaries=False` для любого из них):

```python
from halo_record import Recorder, record_call

rec = Recorder("audit.jsonl")
with record_call(rec, "crm.lookup", {"account": "acct-9"},
                 authority={"snapshot_id": "auth_1", "rules_hash": "sha256:..."},
                 summaries=False) as call:              # hash-only: no summaries, no excerpts
    call.result = crm.lookup("acct-9")
```

Затем, как обычно:

```
halo verify ~/.halo/audit.jsonl
halo report ~/.halo/audit.jsonl -o report.html
```

Любая среда выполнения агента, предоставляющая хук после действия, может передавать ту же команду — хук читает одно событие как JSON из stdin и добавляет одну запись.

Одна цепочка, один писатель за раз. Цепочка — это связный список: два писателя, которые читают одну и ту же голову и оба добавляют запись, создадут развилку (две записи, претендующие на одного и того же предшественника), и верификация назовёт затронутые записи. `Recorder` сериализует свои добавления с помощью бокового замка (здесь POSIX `flock`; в пакете TypeScript — каталог-замок), а `halo hook` добавляет записи через `Recorder`, поэтому приведённая выше настройка хука покрыта. Всё, что пишет в файл цепочки напрямую — самодельный хук, параллельные воркеры, поставщик логов — должно удерживать эквивалентный эксклюзивный замок на протяжении всей последовательности «прочитать голову, затем добавить», либо писать в отдельные цепочки для каждого процесса. [LIMITS.md, раздел 9](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md#9-single-writer-chains) полностью описывает это, включая межъязыковую границу.

## Когда запись не удаётся

Записи создаются после выполнения действия. Halo не блокирует действие, когда его запись не может быть создана; запись перед действием не предлагается.

- **По умолчанию: результат действия проходит без изменений.** Если запись не может быть создана (диск заполнен, проблемы с правами, тайм-аут замка), `trace()`, `record_call`, `@record`, адаптеры фреймворков (OpenAI Agents, LangChain, LiteLLM, OpenTelemetry), обёртка MCP и `halo hook` возвращают собственный результат действия без изменений либо повторно возбуждают собственное исключение действия, если оно завершилось неудачей. Предупреждение в stderr называет отсутствующую запись: `halo-record: FAILED to record '<tool>' (<error>); the action ran, but its record is NOT in the evidence log. ...` (если stderr недоступен, оно направляется в логгер `halo_record`). Обработчик LangChain и экспортёр OTel также подсчитывают потери (`lost_records`). Ничто в цепочке не может показать запись, которая никогда не была создана, поэтому оставшиеся записи всё равно проходят верификацию. Ревьюер, следящий за частотой контрольных точек свидетеля, видит цепочку, которая остановилась; единственная пропущенная запись между более поздними видна только в строке stderr.

---

[Read more](https://github.com/bkuan001/halo-record)
Скачать инструмент