Claude Platform Docs
АдминистрированиеПрозрачность доступа

Проверка событий Access Transparency с помощью журнала прозрачности

Используйте подписанные контрольные точки и доказательства Меркла из Compliance API, чтобы убедиться, что ни одно событие Access Transparency не было удалено или изменено после его фиксации в журнале.

Узнайте, как криптографически проверить, что ни одно событие Access Transparency не было удалено или изменено после его фиксации в журнале прозрачности вашей организации.

Как работает журнал прозрачности

«Transparency log» (журнал прозрачности) — это метод, позволяющий сделать запись защищённой от незаметного вмешательства. Записи только добавляются. Каждый раз, когда журнал растёт, его оператор подписывает короткое утверждение, называемое «checkpoint» (контрольная точка), которое фиксирует все записи на данный момент через хеш «Merkle tree» (дерева Меркла). Любой, кто сохранил контрольную точку, может позже потребовать доказательство того, что текущий журнал по-прежнему содержит всё, что охватывала эта контрольная точка, без изменений и в том же порядке. Поэтому удаление или перезапись записи не может остаться незамеченной для проверяющего, который сохранил контрольную точку, охватывающую эту запись. Certificate Transparency и база контрольных сумм модулей Go построены на том же методе. C2SP tlog-tiles — это открытая спецификация для предоставления такого журнала в виде подписанных контрольных точек и статических кэшируемых тайлов хешей и записей, чтобы клиенты могли получать хеши и самостоятельно вычислять каждое доказательство.

Когда Access Transparency включена, Anthropic ведёт журнал прозрачности для вашей организации. Это доступная только для добавления, криптографически подписанная запись событий Access Transparency (anthropic_access и cmek_preserve). Каждое такое событие, записанное для вашей организации после создания журнала, добавляется в него. Журнал следует формату C2SP tlog-tiles, поэтому инструменты, созданные для этого стандарта, понимают его контрольные точки, тайлы и доказательства.

  • Один журнал на организацию. Журнал каждой организации имеет фиксированную строку происхождения (origin): axt.anthropic.com/<your organization UUID>. Origin никогда не меняется в течение всего существования организации.
  • Каждое новое событие становится листом. Когда событие Access Transparency становится доступным для отображения в вашем Activity Feed, оно сначала добавляется в ваш журнал как «leaf» (лист), и только затем предоставляется в ленте. Лист — это детерминированная сериализация документированных полей события. Событие в вашей ленте содержит transparency_log_leaf_index — его позицию в вашем журнале, отсчитываемую от нуля.
  • Контрольные точки фиксируют всю историю. Журнал представляет собой дерево Меркла. Всякий раз, когда он растёт, Anthropic публикует подписанную контрольную точку: короткий текстовый документ, указывающий origin журнала, его текущий размер и корневой хеш, который фиксирует каждый лист. Каждая контрольная точка содержит ровно одну подпись ключом подписи журнала.
  • Из этого следуют два доказательства. «Inclusion proof» (доказательство включения) показывает, что конкретное событие присутствует на своей позиции в рамках контрольной точки. «Consistency proof» (доказательство согласованности) показывает, что более поздняя контрольная точка является расширением только путём добавления более ранней, которую вы сохранили, поэтому ничего между ними не было удалено или изменено.
  • Ключи проверки предоставляются внутри того же канала. Эндпоинт ключей проверки возвращает открытые ключи, которыми подписываются контрольные точки. При плановой ротации ключей новый ключ добавляется в этот список до того, как начнёт подписывать, а прежние ключи остаются в списке. Поэтому контрольные точки, которые у вас уже есть, продолжают проходить проверку.

Что доказывает журнал прозрачности

  • Поля листа события, которое у вас есть (перечислены в разделе Как событие становится листом), байт в байт совпадают с тем, что Anthropic зафиксировала в журнале.
  • Журнал вашей организации только растёт. Проверка по имеющейся у вас контрольной точке завершается неудачей, если событие, зафиксированное в журнале, позже удаляется или перезаписывается в нём. Она также завершается неудачей, если вам предоставляется история, отличная от той, которая предоставлялась ранее.
  • Новые записи можно только добавлять. Событие нельзя вставить в историю, которую вы уже проверили.

Что он не доказывает и не меняет

  • Он не доказывает, что каждый доступ был записан или что записанное событие точно описывает доступ. Он доказывает только то, что зафиксированное Anthropic в журнале с тех пор не изменилось.
  • Он не меняет то, что охватывает Access Transparency, или время поступления событий.
  • Предоставляемые поля вне листа, такие как workspace_uuid и любые поля, добавленные позже, не охватываются доказательством.
  • Доказательство включения относится к событию, которое вам было предоставлено. Само по себе оно не доказывает, что лента перечислила каждый лист, содержащийся в журнале. Пакеты записей журнала содержат каждый лист, поэтому при необходимости вы можете напрямую прочитать полный набор зафиксированных событий.
  • Наличие transparency_log_leaf_index у события — это указатель, а не доказательство. Всегда проверяйте включение, прежде чем считать событие зафиксированным в журнале.
  • Защита от перезаписанной истории обеспечивается контрольными точками, которые вы сохраняете. Подпись контрольной точки ключом, указанным в разделе Опубликованные отпечатки ключей, доказывает, что она получена из журнала Anthropic. Доказательство согласованности от контрольной точки, сохранённой вами в прошлый раз, доказывает, что уже наблюдавшаяся вами история только росла.

Перед началом работы

Вам понадобится:

  • Compliance Access Key с областью доступа read:compliance_activities — тот же ключ и та же область доступа, которые вы используете для Activity Feed. Ключ родительской организации может читать журнал каждой подключённой дочерней организации, указывая дочернюю организацию в каждом запросе.
  • UUID вашей организации. Найдите его в Claude Console в разделе Settings > Organization. Это то же значение, которое Activity Feed предоставляет как organization_uuid, но берите его из Console. Именно это значение делает контрольную точку вашей, поэтому оно не должно поступать из API, который вы проверяете. Из него вы выводите origin вашего журнала как axt.anthropic.com/<organization UUID>. Формируйте эту строку самостоятельно. Не считывайте её из ответа API.
  • Надёжное место для хранения последней проверенной вами контрольной точки. Именно эта сохранённая контрольная точка превращает утверждение «журнал согласован сегодня» в «журнал согласован с тех пор, как вы начали наблюдение».

Сроки

  • События: события Access Transparency появляются в вашем Activity Feed в течение двух рабочих дней после доступа. Событие попадает в журнал только тогда, когда оно становится доступным для предоставления, поэтому журнал никогда не раскрывает событие раньше времени. Поскольку запись в журнал происходит до того, как лента предоставит событие, запись может ненадолго появиться в журнале раньше, чем её событие появится в вашей ленте. Этот разрыв не является расхождением.
  • Контрольные точки: новая контрольная точка публикуется всякий раз, когда ваш журнал растёт.
  • Доказательства включения: доказательство для недавно предоставленного события становится доступным после публикации контрольной точки, охватывающей позицию события, обычно очень скоро после появления события. Если вы запросите его раньше, вы получите 404 и повторите попытку после небольшой задержки.
  • Периодичность проверки: выполняйте проверку как минимум ежедневно. Ежечасная проверка вполне разумна.
  • Отключение: если ваша организация перестаёт использовать Access Transparency, ничего не удаляется. Ваш журнал остаётся доступным для чтения через те же эндпоинты. Если Access Transparency позже снова будет включена, продолжится тот же журнал.

Хранение и удаление

  • Журнал прозрачности: Anthropic не удаляет записи из вашего журнала, и у журнала нет срока действия. Он сохраняется, если ваша организация перестаёт использовать Access Transparency, а также после удаления вашей организации, поскольку удаление записей — это именно то изменение, для обнаружения которого существует журнал. Пакеты записей содержат поля листа каждого события, поэтому эти поля хранятся столько же, сколько и журнал.
  • Activity Feed: события Access Transparency в Activity Feed подчиняются правилам хранения ленты. Действия хранятся 6 лет. См. Запросы к ленте активности.
  • Удаление с вашей стороны невозможно: эндпоинты журнала прозрачности доступны только для чтения. Удалить или изменить запись невозможно.

Эндпоинты журнала прозрачности

По адресу https://api.anthropic.com/v1/compliance/transparency_log/ предоставляются шесть эндпоинтов только для чтения:

ЭндпоинтВозвращает
GET /checkpointПоследнюю подписанную контрольную точку
GET /keysНабор ключей проверки
GET /inclusionДоказательство включения для одного события
GET /consistencyДоказательство согласованности от имеющейся у вас контрольной точки до последней
GET /tile/{level}/{index}Тайл хешей Меркла
GET /tile/entries/{index}Пакет записей с байтами листьев

Контрольные точки, тайлы и пакеты записей в точности следуют формату передачи C2SP tlog-tiles. Два эндпоинта доказательств предоставляются для удобства: каждое доказательство также можно вычислить из тайлов, поэтому вам никогда не нужно доверять выводу эндпоинта доказательств. Вы проверяете возвращаемые им хеши по подписанной контрольной точке.

Аутентификация и область доступа

Отправляйте ваш Compliance Access Key в заголовке x-api-key вместе с заголовком anthropic-version, как и для любого запроса к Compliance API (см. Версионирование). Compliance API должен быть включён для вашей организации.

Отдельного разрешения для журнала прозрачности нет. Любой ключ, который может читать Activity Feed вашей организации — для вашей организации или её родительской организации, — может читать весь ваш журнал, включая поля событий в его пакетах записей.

Каждый запрос читает журнал ровно одной организации:

  • Ключ уровня организации читает журнал своей собственной организации. Параметр запроса organization_id необязателен. Если он указан, он должен указывать на собственную организацию ключа.
  • Ключ уровня родительской организации должен передавать organization_id, указывающий одну дочернюю организацию.
  • organization_id принимает тегированный ID вида org_... или UUID организации.

404 означает, что нет журнала, который этот ключ может прочитать. Организация вне области доступа ключа, несуществующая организация и организация, журнал которой ещё не создан, намеренно неразличимы. Журнал организации, которая с тех пор перестала использовать Access Transparency, к этому случаю не относится: он продолжает предоставляться.

Ошибки

Ошибки используют стандартную JSON-обёртку ошибок Compliance API на каждом эндпоинте, включая текстовые и бинарные. См. Ошибки для описания обёртки и общих типов ошибок.

СтатусЗначение для этих эндпоинтов
400organization_id имеет неверный формат или опущен при использовании ключа родительской организации, Compliance API не включён, параметр запроса неизвестен или не пройдена проверка, специфичная для эндпоинта
401Ключ API отсутствует или недействителен
403У ключа нет требуемой области доступа
404Нет журнала, доступного для чтения этим ключом, либо специфичные для эндпоинта случаи «не охвачено» и «за пределами дерева»
429Превышено ограничение скорости. Эти эндпоинты разделяют ограничение скорости Compliance API на уровне родительской организации. Соблюдайте retry-after
503Журнал временно недоступен. Повторите попытку с экспоненциальной задержкой

Кэширование

Ответы могут кэшироваться только запрашивающим клиентом. Cache-Control всегда включает private, а ответы содержат Vary: x-api-key. Не размещайте общий кэш перед этими эндпоинтами. Полные тайлы и полные пакеты записей никогда не меняются и предоставляются с Cache-Control: private, max-age=604800, immutable. Всё остальное, включая контрольные точки, доказательства, ключи, частичные тайлы и ошибки, предоставляется с Cache-Control: private, no-store.

Чтение последней контрольной точки

GET /v1/compliance/transparency_log/checkpoint

curl --fail-with-body -sS \
  "https://api.anthropic.com/v1/compliance/transparency_log/checkpoint" \
  --header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
  --header "anthropic-version: 2023-06-01"

Ответ имеет тип text/plain: это C2SP signed note. Строки тела — это origin, размер дерева в десятичной записи и корневой хеш в base64. Далее следует пустая строка, затем строка подписи, которая начинается с длинного тире (U+2014), называет origin и заканчивается значением в base64. Значения здесь приведены для иллюстрации:

axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b
1207
C6C4HzGRqDNlbu54LWCvpDX0NcB5DRTmLcjM4u5vWUI=

— axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b q83vATBFAiEAvL8m…(base64)…
  • Первые четыре байта декодированного значения подписи — это key_hash ключа подписи, который указывает, какой записью из набора ключей проверки следует выполнять проверку. Остальные байты — это подпись ECDSA P-256 в формате ASN.1 DER над SHA-256 тела заметки: всех байтов до пустой строки, включая завершающий символ новой строки тела.
  • Контрольная точка может содержать дополнительные строки после корневого хеша. Игнорируйте строки, которые вы не понимаете. Они охватываются подписью.
  • Игнорируйте строку подписи, имя в которой не совпадает с вашим origin или хеш ключа которой у вас отсутствует.
  • Никогда не кэшируйте контрольную точку. Устаревшая контрольная точка скрывает текущий размер журнала, из-за чего недавно предоставленные события выглядят неохваченными.

Чтение ключей проверки

GET /v1/compliance/transparency_log/keys

curl --fail-with-body -sS \
  "https://api.anthropic.com/v1/compliance/transparency_log/keys" \
  --header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
  --header "anthropic-version: 2023-06-01"
{
  "type": "transparency_log_keys",
  "origin": "axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b",
  "log_keys": [
    {
      "verifier_key": "axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b+<key_hash>+<base64 key>",
      "key_hash": "<8 lowercase hex digits>",
      "fingerprint": "<64 lowercase hex digits>",
      "algorithm": "ecdsa_p256_sha256",
      "public_key": "<base64 DER SubjectPublicKeyInfo>"
    }
  ]
}
ПолеТипОписание
typestringВсегда transparency_log_keys
originstringСтрока origin, которую содержит каждая контрольная точка этого журнала. Носит информационный характер: сравнивайте контрольные точки с origin, который вы выводите самостоятельно, а не с этим полем
log_keysarrayСначала ключ, которым подписываются новые контрольные точки, затем все остальные ключи, предоставляемые журналом, от новых к старым. Никогда не бывает пустым
log_keys[].verifier_keystringКлюч в виде строки C2SP note-verifier, <origin>+<key_hash>+<base64 key>, принимаемой инструментами tlog-tiles, поддерживающими ключи заметок ECDSA (например, модулем Go github.com/transparency-dev/formats). Часть в base64 декодируется в байт алгоритма 0x02, за которым следует открытый ключ в кодировке DER
log_keys[].key_hashstringВосемь шестнадцатеричных цифр в нижнем регистре. 4-байтовый селектор, сопоставляющий этот ключ со строкой подписи контрольной точки. Это первые четыре байта fingerprint, и он не является идентификатором
log_keys[].fingerprintstring64 шестнадцатеричные цифры в нижнем регистре: SHA-256 от DER SubjectPublicKeyInfo
log_keys[].algorithmstringТип ключа, в настоящее время ecdsa_p256_sha256. Могут быть добавлены новые значения. Пропускайте ключ, алгоритм которого вы не поддерживаете
log_keys[].public_keystringОткрытый ключ в виде base64 DER SubjectPublicKeyInfo

key_hash охватывает только байты ключа: это первые четыре байта SHA-256 от DER SubjectPublicKeyInfo, что соответствует правилу, используемому кодировкой ECDSA note-verifier. Это не зависящий от имени ID ключа, который базовый формат signed-note определяет для ключей Ed25519, поэтому он не меняется вместе с origin. Действительная подпись ключом, указанным в разделе Опубликованные отпечатки ключей, доказывает, что контрольная точка получена от службы журнала прозрачности Anthropic. Привязку к вашей организации обеспечивает строка origin внутри подписанной контрольной точки. Именно поэтому вы сравниваете эту строку с origin, который выводите самостоятельно.

Ключи могут ротироваться:

  • Ротация — это переключение. Начиная с некоторой контрольной точки, новые контрольные точки подписываются новым ключом.
  • При плановой ротации новый ключ появляется в log_keys до того, как что-либо подпишет, а прежние ключи остаются в списке. Поэтому контрольная точка, сохранённая вами до ротации, продолжает проходить проверку.
  • Проверяющий может получать набор ключей при каждом запуске или хранить его локально. Проверяющий, хранящий его локально, повторно обращается к этому эндпоинту, когда встречает подпись с key_hash, которого у него нет.

Опубликованные отпечатки ключей

Anthropic публикует здесь, вне API, отпечаток каждого ключа, которым подписываются контрольные точки. Это позволяет сверить хранящийся у вас локально ключ с источником, который не может быть изменён через канал предоставления данных. Имеющийся у вас ключ может быть получен из более раннего ответа GET /keys или из инструментов, закрепляющих ключ.

Хеш ключаОтпечаток SHA-256АлгоритмПодписывает сСтатус
1dff5fe41dff5fe420d49743fe444a04fc17f818eea856699dec2ebbc24df15602c74a58ecdsa_p256_sha2562026-08-17Текущий ключ подписи

О плановой ротации объявляется на этой странице не менее чем за 30 дней до того, как новый ключ подпишет свою первую контрольную точку. В течение этого периода уведомления новый ключ указан в log_keys и в этой таблице вместе с датой переключения. Выведенные из эксплуатации ключи остаются в списке с датами их использования. Ключ, отсутствующий в этой таблице, не является легитимным, что бы ни возвращал GET /keys. Считайте контрольную точку, которая не проходит проверку ни одним из перечисленных ключей, неудачей проверки и сообщите об этом вашему представителю Anthropic или в службу поддержки Anthropic.

axt-verify содержит текущий ключ в каждом выпуске и никогда не считывает ключ из API. Каждый выпуск содержит ровно один ключ. В дату переключения Anthropic начинает подписывать новым ключом и публикует выпуск axt-verify, содержащий его. В ту же дату Anthropic повторно выпускает последнюю контрольную точку каждой организации под новым ключом, даже для журнала, который не вырос. Обновитесь в дату переключения. Запуск старого выпуска после переключения завершается с кодом выхода 1, как и запуск нового выпуска до него. Любая из этих ошибок исчезает, как только вы запускаете соответствующий выпуск. В проверяющий инструмент, который вы поддерживаете самостоятельно, необходимо добавить новый отпечаток с его датой переключения до этой даты.

Получение доказательства включения

GET /v1/compliance/transparency_log/inclusion?leaf_index={index}

ПараметрТипОписание
leaf_indexinteger, обязательныйПозиция события в журнале: transparency_log_leaf_index, предоставленный Activity Feed для события. Должен быть равен нулю или больше
organization_idstring, необязательныйСм. Аутентификация и область доступа
curl --fail-with-body -sS -G \
  "https://api.anthropic.com/v1/compliance/transparency_log/inclusion" \
  --data-urlencode "leaf_index=41" \
  --header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
  --header "anthropic-version: 2023-06-01"
{
  "type": "transparency_log_inclusion_proof",
  "leaf_index": 41,
  "hashes": [
    "mUdyOWMp0zXIq0CDMvSYDUSBl9yAvnTZzdm51RwWpUM=",
    "yR6tDHkAhKvdQSLqQATVjXOo4GM3FDyiKF2XCKTtMUI=",
    "..."
  ],
  "checkpoint": "axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b\n42\nCsRlS31ITFHrX9GR5XjyPw8n0MkfrB8Yh2UDHl3Lr3E=\n\n— axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b q83vATBEAiB0…(base64)…\n"
}
ПолеТипОписание
typestringВсегда transparency_log_inclusion_proof
leaf_indexintegerПозиция события в журнале, повторённая из запроса
hashesarray of stringsСоседние хеши пути аудита в base64, упорядоченные от листа к корню
checkpointstringПоследняя подписанная контрольная точка, по которой проверяется доказательство. Она содержит размер дерева

Поиска по ID действия нет. Индекс всегда у вас есть, поскольку он поступает вместе с событием, и вы проверяете доказательство по байтам события, полученным из ленты.

404 означает, что последняя опубликованная контрольная точка не охватывает указанную позицию:

  • Для индекса, считанного из предоставленного события, это временное состояние. Охватывающая контрольная точка вскоре будет опубликована, поэтому повторите попытку после небольшой задержки.
  • Тот же 404 возвращается для любой другой неохваченной позиции, например для индекса, который лента никогда не предоставляла. Для такой позиции нет гарантии, что охватывающая контрольная точка когда-либо будет опубликована. Ответ не сообщает, какой из случаев имеет место.

Отсутствующий leaf_index или leaf_index, не являющийся неотрицательным целым числом, возвращает 400.

Получение доказательства согласованности

GET /v1/compliance/transparency_log/consistency?from={size}

ПараметрТипОписание
frominteger, обязательныйРазмер дерева более ранней контрольной точки, которая у вас есть. Должен быть не меньше 1 и не больше размера дерева последней контрольной точки
organization_idstring, необязательныйСм. Аутентификация и область доступа
curl --fail-with-body -sS -G \
  "https://api.anthropic.com/v1/compliance/transparency_log/consistency" \
  --data-urlencode "from=1180" \
  --header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
  --header "anthropic-version: 2023-06-01"
{
  "type": "transparency_log_consistency_proof",
  "hashes": [
    "dGw0aPzu2N0pdc4C5ZAvNIbkXF7J6F9ZQLkPpV6v8Vg=",
    "9PSWm1T9RUmhjF6z6YQzB9CW6E2m2n3mK0aVgqf5Qm0=",
    "..."
  ],
  "checkpoint": "axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b\n1207\nC6C4HzGRqDNlbu54LWCvpDX0NcB5DRTmLcjM4u5vWUI=\n\n— axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b q83vATBFAiEAvL8m…(base64)…\n"
}
ПолеТипОписание
typestringВсегда transparency_log_consistency_proof
hashesarray of stringsХеши доказательства в base64 в порядке RFC 9162
checkpointstringПоследняя подписанная контрольная точка, до которой простирается доказательство. Она содержит размер дерева
  • Доказательство всегда простирается до последней опубликованной контрольной точки. Этот API никогда не предоставляет исторические контрольные точки: вы сохраняете те, которые вам предоставляются.
  • from, равный размеру дерева последней контрольной точки, возвращает пустое доказательство.
  • Для имеющейся контрольной точки с размером дерева 0 доказательство согласованности не требуется, поскольку любой журнал является расширением пустого журнала. В этом случае принимайте последнюю контрольную точку напрямую.
  • from меньше 1 или больше размера дерева последней контрольной точки возвращает 400.
  • Если журнал больше не может доказать, что он является расширением контрольной точки, которую когда-то подписал для вас, считайте это неудачей проверки, а не ошибкой использования.

Чтение тайла хешей

GET /v1/compliance/transparency_log/tile/{level}/{index}

Возвращает application/octet-stream: конкатенированные 32-байтовые хеши SHA-256 согласно tlog-tiles. Адресация тайлов в точности следует tlog-tiles, включая грамматику пути {level} и {index}, форму индекса x001/234 для больших деревьев и суффикс частичного тайла .p/{width}. Тайлы хешей — это единица, из которой клиенты tlog-tiles самостоятельно вычисляют доказательства.

  • Полные тайлы неизменяемы и предоставляются с Cache-Control: private, max-age=604800, immutable.
  • Частичные тайлы заменяются по мере роста дерева и предоставляются с Cache-Control: private, no-store. После заполнения тайла запрос его прежней частичной формы может вернуть 404, даже если полный тайл существует. Переход от частичного тайла к полному — задача клиента, как указано в tlog-tiles, и стандартные клиенты уже это делают.
  • Неверный формат level, index или ширины частичного тайла возвращает 400. Позиция тайла за пределами текущего размера дерева возвращает 404.

Чтение пакета записей

GET /v1/compliance/transparency_log/tile/entries/{index}

Возвращает application/octet-stream: последовательные записи листьев, каждая с префиксом своей длины в формате big-endian uint16, согласно tlog-tiles. Пакеты записей содержат открытый текст событий: канонические байты каждого события Access Transparency. Именно поэтому для всех этих эндпоинтов требуется область доступа Activity Feed. Адресация, частичная форма, кэширование и ошибки идентичны тайлам хешей.

Поле transparency_log_leaf_index в событиях Activity Feed

События anthropic_access и cmek_preserve в GET /v1/compliance/activities содержат transparency_log_leaf_index — целое число — всякий раз, когда у события есть лист. Другие типы действий никогда его не содержат.

  • Когда у события нет листа, ключ отсутствует, а не равен null. Надёжный проверяющий инструмент обрабатывает отсутствующий ключ и значение null одинаково.
  • Событие предоставляется без transparency_log_leaf_index только в двух случаях. Первый — пока ваша организация не подключена к Access Transparency, то есть до подключения или между отключением и повторным подключением. Второй — когда событие было записано до создания журнала вашей организации. Для организации, подключённой до появления журнала прозрачности, это включает её более раннюю историю. После того как ваш журнал существует и пока вы подключены, каждое событие добавляется в журнал до того, как лента его предоставит. Если сбой не позволяет ленте узнать индекс, лента задерживает событие, а не предоставляет его без индекса. Событие не теряется: оно уже находится в журнале и появляется в ленте вместе с индексом после устранения сбоя. Событие без индекса не ожидается, если оно датировано после создания вашего журнала и попадает в период, когда вы были подключены.
  • Наличие индекса — это указатель, а не доказательство. Проверьте включение, прежде чем считать событие зафиксированным в журнале. Аномалия, о которой стоит сообщить, — это присутствующий индекс, доказательство включения для которого по-прежнему невозможно получить спустя долгое время после того, как должна была быть опубликована охватывающая контрольная точка.
  • Индекс назначается при добавлении события в журнал и не входит в число полей, составляющих лист.

Как событие становится листом

Запись листа — это байт версии схемы 0x01, за которым следует канонический JSON из 11 полей. JSON соответствует RFC 8785 (JSON Canonicalization Scheme), а поля берутся из события в точности в том виде, в каком его предоставляет Activity Feed:

  • id, type, created_at, accessed_at, organization_id, organization_uuid, workspace_id, accessor_department и reason_code
  • actor с вложенными type и email_address
  • resource_details с вложенными type, id и parent

Правила:

  • Предоставляемые поля вне этого набора, такие как workspace_uuid и сам transparency_log_leaf_index, игнорируются.
  • Документированное поле, которое предоставленное событие опускает, попадает в лист как null. Пустая строка отличается от null.
  • actor и resource_details — это объекты ровно с их документированными ключами, когда предоставленное событие их содержит. В версии 0x01 actor.email_address и resource_details.parent всегда равны null. Когда предоставленное событие опускает один из этих объектов или предоставляет его как null, всё значение в листе равно null, а не объекту с полями null. Многие события доступа не содержат resource_details.
  • Строковые значения, включая обе временные метки и reason_code, берутся байт в байт в том виде, в каком они предоставлены. Если вы заново выводите временную метку из другого представления, точно воспроизведите предоставленное отображение:
    • RFC 3339 UTC с суффиксом Z.
    • created_at не имеет дробных цифр, когда его микросекунды равны нулю, и ровно шесть в противном случае.
    • accessed_at имеет ноль, три, шесть или девять дробных цифр — наименьшее количество, точно сохраняющее его наносекунды.
  • Канонический JSON означает отсортированные ключи объектов, отсутствие незначащих пробелов и минимальное экранирование строк. Числа в листе нигде не встречаются.
  • Хеш листа — это SHA-256(0x00 || entry) по RFC 6962. Внутренние узлы хешируются как SHA-256(0x01 || left || right).
  • Проверяющий инструмент отклоняет неизвестный байт версии, а также лист 0x01, type которого не является одним из двух типов Access Transparency. Новые типы событий или изменения правил выпускаются под новым байтом версии. Существующие листья никогда не перехешируются.

Например, это событие доступа в том виде, в каком его предоставляет Activity Feed:

{
  "id": "activity_01GPXmAhizavrUuoXNn3tzeA",
  "type": "anthropic_access",
  "created_at": "2025-07-08T18:40:00Z",
  "accessed_at": "2025-07-08T18:39:58Z",
  "organization_id": "org_015gtSHLz269eTwgrH8NX5yk",
  "organization_uuid": "25f6429a-3293-49bf-afed-cb312911554b",
  "workspace_id": "wrkspc_01PaGUP2rbg1XDh7Z9W1CEpd",
  "workspace_uuid": "b6ce2143-1083-d4a7-247c-17530f55a076",
  "accessor_department": "Trust & Safety",
  "reason_code": "safety_review",
  "actor": { "type": "anthropic_actor", "email_address": null },
  "resource_details": { "type": "message", "id": "msg_01HXAMPLE12345678" },
  "transparency_log_leaf_index": 17
}

превращается в этот канонический JSON. Он содержит ровно 11 документированных ключей, отсортированных, в одной строке. workspace_uuid и transparency_log_leaf_index исключаются, а resource_details.parent, отсутствующий в предоставленном событии, попадает как null:

{"accessed_at":"2025-07-08T18:39:58Z","accessor_department":"Trust & Safety","actor":{"email_address":null,"type":"anthropic_actor"},"created_at":"2025-07-08T18:40:00Z","id":"activity_01GPXmAhizavrUuoXNn3tzeA","organization_id":"org_015gtSHLz269eTwgrH8NX5yk","organization_uuid":"25f6429a-3293-49bf-afed-cb312911554b","reason_code":"safety_review","resource_details":{"id":"msg_01HXAMPLE12345678","parent":null,"type":"message"},"type":"anthropic_access","workspace_id":"wrkspc_01PaGUP2rbg1XDh7Z9W1CEpd"}

Запись листа — это байт 0x01, за которым следуют эти байты UTF-8. Её хеш листа, SHA-256(0x00 || entry), в base64 равен 6ro7vTcFq+sYDZiiGvZaFetUIoMSLig3DGDrCKK1HFU=. Используйте этот пример как тестовый вектор для собственного кода канонизации.

Проверка вашего журнала

Проверка выполняется на вашей собственной инфраструктуре. Всё, что возвращает API, считается недоверенным, пока не пройдёт проверку по двум вещам, которые вы храните сами. Первая — origin, который вы выводите из UUID вашей организации. Вторая — контрольная точка, сохранённая вами при последнем запуске. Полный запуск проверки выполняет следующее по порядку:

  1. Получите набор ключей проверки. Самостоятельно вычислите отпечаток каждого ключа как SHA-256 от его декодированного из base64 public_key. Оставьте только ключи, отпечаток которых указан в разделе Опубликованные отпечатки ключей, вместе со статусом каждого ключа там. Проверяйте только что полученную контрольную точку только ключом, который эта таблица указывает как текущий на эту дату. Принимайте выведенный из эксплуатации ключ только для контрольной точки, сохранённой вами до даты его вывода.
  2. Установите последнюю контрольную точку. При первом запуске получите её из эндпоинта контрольной точки. При каждом последующем запуске запрашивайте доказательство согласованности от сохранённого вами размера дерева. Ответ содержит последнюю контрольную точку вместе с доказательством.
  3. Сначала проверьте строку origin контрольной точки. Сравните её первую строку байт в байт с выведенным вами origin. Отклоните любую контрольную точку с отличающимся origin, прежде чем делать что-либо ещё.
  4. Проверьте подпись контрольной точки. Найдите строку подписи с именем вашего origin, первые четыре декодированных байта которой равны key_hash сохранённого вами действующего в данный момент ключа. Проверьте оставшиеся байты как подпись ECDSA P-256 над SHA-256 тела заметки, используя public_key этого ключа. Если ни одна строка подписи не соответствует такому ключу или подпись не проходит проверку, отклоните контрольную точку.
  5. Докажите, что журнал только дополнялся. Если новый размер дерева меньше сохранённого вами, проверка не пройдена. Если он равен, корневые хеши должны совпадать. Если он больше, проверьте доказательство согласованности RFC 9162 от сохранённых вами размера и корневого хеша до нового размера и корневого хеша.
  6. Докажите, что каждое событие включено. Прочитайте каждое событие Access Transparency, предоставляемое Activity Feed. Для каждого нового события заново постройте его лист, вычислите его хеш и получите его доказательство включения. Пройдите путь аудита от хеша вашего листа по индексу события до корневого хеша контрольной точки. Несовпадение означает, что предоставленное вам событие не является событием, зафиксированным журналом. Ответ с доказательством может содержать контрольную точку, отличную от имеющейся у вас. Свяжите её с вашей историей с помощью доказательства согласованности, прежде чем проверять что-либо по ней.
  7. Перепроверьте то, что видели ранее. Всякий раз, когда вы снова читаете событие, оно должно предоставляться с тем же индексом и теми же байтами листа, что и при его проверке. Ни одно событие не может потерять имевшийся у него индекс, и пока вы подключены, ни одно событие не может впервые появиться без индекса. События, предоставленные без индекса при вашем первом запуске, — это ваша история до появления журнала. Запуск, который повторно читает только недавние события, перепроверяет только их. Чтобы перепроверить более старые, снова проверьте сохранённые вами копии (шаг 8).
  8. Сохраните проверенную контрольную точку и запись о каждом проверенном событии. Они являются вашими доказательствами и отправной точкой для следующего запуска.

Проверка с помощью axt-verify

axt-verify — это проверяющий инструмент Anthropic с открытым исходным кодом для этого журнала. Это единый бинарный файл Go, который вы запускаете на своей собственной инфраструктуре. В каждый выпуск встроен ровно один ключ подписи журнала из раздела Опубликованные отпечатки ключей, поэтому он никогда не спрашивает у API, какому ключу доверять. Когда Anthropic ротирует ключ, вы обновляетесь до выпуска, содержащего новый ключ, в дату переключения. axt-verify выводит ваш origin из UUID организации, который вы передаёте с помощью --org, — того, который вы взяли из Console в разделе Перед началом работы. Он отклоняет любую контрольную точку с отличающейся строкой origin.

Установите его с помощью Go 1.26 или новее. Он считывает ваш Compliance Access Key из переменной окружения ANTHROPIC_COMPLIANCE_ACCESS_KEY, никогда из флага или файла. Для запуска по расписанию предназначена команда run:

go install github.com/anthropics/axt-verify/cmd/axt-verify@latest

export ANTHROPIC_COMPLIANCE_ACCESS_KEY="<your Compliance Access Key>"
axt-verify --org 25f6429a-3293-49bf-afed-cb312911554b \
  --state /var/lib/axt-verify/25f6429a-3293-49bf-afed-cb312911554b.state \
  run

Каждый run получает последнюю контрольную точку и проверяет её подпись и строку origin. Затем он доказывает, что журнал является расширением только путём добавления контрольной точки, сохранённой предыдущим запуском. Далее он постранично просматривает события Access Transparency в вашем Activity Feed. Он начинает за семь дней (по created_at) до самого нового события, прочитанного предыдущим запуском, чтобы события, появившиеся в списке с опозданием или не по порядку, всё равно были учтены. Он заново строит лист каждого события, проверяет для него доказательство включения и сравнивает любое ранее проверенное событие с тем, что было записано тогда. Наконец, он сохраняет новую контрольную точку и свой прогресс в файл --state, с которого начинается следующий запуск. Запускайте его как минимум ежедневно. Ежечасный запуск вполне разумен. С ключом родительской организации запускайте по одному экземпляру на каждую дочернюю организацию, каждый со своими --org и файлом --state. UUID каждой дочерней организации также берётся из Claude Console, а не из проверяемых вами ответов Compliance API. Найдите его на странице Settings > Organization дочерней организации или в списке организаций вашей родительской организации в Console. axt-verify checkpoint выполняет только шаги проверки контрольной точки и добавления. axt-verify events FILE проверяет события, которые у вас уже есть, например выборку аудитора или ваш собственный экспорт. Он доказывает, что каждое событие в файле по-прежнему зафиксировано в журнале в рамках текущей контрольной точки. Он не читает ленту и не затрагивает файл состояния.

Из этого окна следует одно ограничение: run повторно читает только события за последние семь дней, поэтому он перепроверяет недавно предоставленные события (шаг 7), а не всю вашу историю. Сохраняйте экспортируемые вами события (см. Ведение собственного архива контрольных точек). axt-verify events FILE в любой более поздний момент доказывает, что эти копии по-прежнему зафиксированы в журнале, но не перечитывает ленту. Чтобы обнаружить более старое событие, удалённое из ленты или перезаписанное в ней, повторно экспортируйте этот диапазон из Activity Feed и сравните его с сохранёнными копиями. Вы также можете проверить сам повторный экспорт с помощью axt-verify events FILE. Семидневное перекрытие длиннее двухдневного (в рабочих днях) срока доставки ленты, поэтому событие, поступившее с опозданием, всё равно попадает в окно более позднего запуска. При необходимости --overlap изменяет эту продолжительность.

Если вместо этого вам нужна собственная реализация, следуйте приведённому выше контрольному списку, используя библиотеку tlog-tiles, поддерживающую ключи заметок ECDSA.

Интерпретация результата

axt-verify выводит ваш origin, размер дерева и корневой хеш проверенной им контрольной точки, размер дерева, с которого началась проверка того, что журнал только дополнялся, а также количество событий по каждому исходу. Передайте --json, чтобы получить тот же отчёт в виде одного JSON-объекта на строку. Каждое событие имеет один из четырёх исходов:

  • Verified: лист, восстановленный из полученного события, зафиксирован по индексу события в подписанном журнале.
  • Pending: индекс события находится за пределами последней опубликованной контрольной точки. Это нормально в течение короткого времени после появления события. В режиме run axt-verify запоминает событие, проверяет его при одном из последующих запусков, как только его охватит контрольная точка, и помечает его как неудачное, если это занимает более 24 часов. У events FILE нет последующего запуска, который мог бы это разрешить, поэтому он ждёт до минуты публикации охватывающей контрольной точки. Если такая контрольная точка не появляется, он сообщает, что событие ещё не охвачено, и завершается с кодом выхода 3. Запустите его снова позже. Если events FILE сообщает, что одно и то же событие ещё не охвачено, при двух запусках с интервалом не менее суток, считайте это сбоем проверки и эскалируйте так же, как для кода выхода 1.
  • Not logged: событие было предоставлено без индекса. Событие предоставляется без transparency_log_leaf_index только пока ваша организация не подключена к Access Transparency или если оно было записано до создания журнала вашей организации (см. Поле transparency_log_leaf_index в событиях Activity Feed). axt-verify сообщает о таких событиях как о незарегистрированных в журнале и не считает запуск неудачным из-за них. Событие без индекса не ожидается, если оно датировано временем после создания вашего журнала и попадает в период, когда вы были подключены. Просматривайте список незарегистрированных событий в сводке запуска или в выводе --json, а не полагайтесь только на код выхода.
  • Failed: см. код выхода 1.

Код выхода сообщает вашему планировщику, что произошло:

  • 0: Ничего не завершилось неудачей. О незарегистрированных событиях сообщается, но они не считаются неудачными; то же относится к ожидающим событиям в run.

  • 1: Сбой проверки. Это находка в области безопасности, а не временная ошибка. Сохраните файл состояния и вывод и сообщите об этом вашему представителю по работе с клиентами Anthropic или в службу поддержки Anthropic. Причины:

    • Контрольная точка с неверным origin или подпись, которая не проходит проверку ключом, встроенным в ваш выпуск axt-verify. Сравните key_hash в строке подписи контрольной точки, не прошедшей проверку, с разделом Опубликованные отпечатки ключей. Если ключ указан там с датой переключения, к которой вы не обновились, вам нужен соответствующий выпуск. Ключ, не указанный там, — это находка в области безопасности, какой бы выпуск вы ни использовали. При этом сбое axt-verify выводит хеш ключа каждой подписи в полученной контрольной точке и хеш ключа, которому он доверяет, — каждый в виде восьми шестнадцатеричных цифр. Этого вывода достаточно для сравнения.
    • Контрольная точка, которая не является корректно сформированной подписанной заметкой (signed note), например такая, у которой корневой хеш не равен 32 байтам.
    • Журнал, который уменьшился или не может доказать, что он расширяет сохранённую вами контрольную точку. В этом случае вывод содержит обе контрольные точки и доказательство, так что доказательная база самодостаточна.
    • Две подписанные контрольные точки для одного и того же размера дерева с разными корневыми хешами. Вывод содержит обе контрольные точки.
    • Файл контрольной точки, переданный с --from, подпись которого не проходит проверку ключом, встроенным в ваш выпуск axt-verify, или файл --from либо --from-trusted, origin которого не ваш. Об архиве, подписанном до ротации ключа, см. Ведение собственного архива контрольных точек.
    • Доказательство включения, которое не воспроизводит подписанный корневой хеш для предоставленного вам события.
    • Событие внутри окна запуска, предоставленное иначе, чем его записал предыдущий запуск: другие байты листа, другой индекс или отсутствие индекса там, где он был.
    • Событие, всё ещё ожидающее через 24 часа после того, как запуск впервые его увидел.
    • Отказ в доказательстве включения (400, 401 или 403) для события, которое вам предоставила лента.
    • Доказательство включения, возвращённое для другого leaf_index, чем запрошенный.
    • В events FILE — событие с индексом, который последняя контрольная точка уже охватывала на момент начала проверки, но для которого доказательство включения не было предоставлено до истечения времени ожидания.
    • Событие, у которого organization_uuid не совпадает с UUID организации, переданным через --org. Когда родительская организация запускает events FILE на экспорте, охватывающем несколько дочерних организаций, события всех остальных организаций завершаются неудачей именно так, поэтому сначала разделите экспорт по организациям и проверьте каждую часть с её собственным --org.
    • Один и тот же id активности по двум разным индексам или дважды по одному индексу с разным содержимым в рамках одного запуска или одного входного файла events FILE.
    • Событие, лист которого невозможно восстановить: например, документированное поле, не являющееся строкой, имя поля, встречающееся дважды, или type, который отсутствует или является нераспознанным вариантом типа Access Transparency. events FILE пропускает строки других типов активности и не считает их неудачными.
  • 2: Ошибка использования или конфигурации. Причины:

    • Отсутствующий или некорректный флаг.
    • Отсутствует ANTHROPIC_COMPLIANCE_ACCESS_KEY.
    • Ключ, который API отклоняет (401 или 403) до того, как была проверена хотя бы одна контрольная точка.
    • Файл состояния, который невозможно прочитать или который принадлежит другому origin.
  • 3: Запуск не удалось завершить. В run то, что уже было проверено, сохраняется в файл состояния. Запустите снова. Причины:

    • Событие в events FILE, индекс которого не был охвачен ни одной опубликованной контрольной точкой за время ожидания. Для такого события исход Pending указывает, когда прекратить повторные запуски и эскалировать.
    • Сетевые ошибки, ограничение скорости или ошибки сервера, продолжавшиеся дольше повторных попыток.
    • Неожиданный ответ.
    • Файл состояния или --save, который не удалось записать.

    Код выхода 3 с ответами 404 ожидаем, пока Anthropic не запишет первое событие Access Transparency для вашей организации, поскольку каждый эндпоинт журнала прозрачности возвращает 404, пока это событие не создаст журнал. Эскалируйте, если эндпоинты журнала прозрачности всё ещё возвращают 404 спустя более нескольких дней после того, как в вашем Activity Feed впервые появилось событие Access Transparency, независимо от того, содержит ли это событие transparency_log_leaf_index. Такое сочетание не ожидается. После того как запуск однажды завершился успешно, эскалируйте устойчиво повторяющийся код выхода 3.

Ведение собственного архива контрольных точек

Самое надёжное доказательство, которым вы можете располагать, — это ваша собственная запись того, что журнал показывал в определённый день. axt-verify --save FILE дословно записывает контрольную точку, проверенную запуском, а --from FILE при последующем запуске заставляет журнал доказать, что он по-прежнему расширяет эту контрольную точку. Архивируйте сохранённую контрольную точку в хранилище, которое вы контролируете, например ежедневно. Спустя месяцы доказательство согласованности от размера дерева этой архивной контрольной точки по-прежнему должно вести к любой контрольной точке, которую предоставляет журнал, иначе проверка завершится неудачей. После плановой ротации прежние ключи остаются в наборе ключей проверки, поэтому архивная контрольная точка продолжает проходить проверку. Если при использовании axt-verify ключ, подписавший архивную контрольную точку, с тех пор был выведен из ротации, передайте этот архив с --from-trusted вместо --from. Сохраняйте и события. События Access Transparency, которые вы экспортируете из ленты, являются допустимыми входными данными для axt-verify events FILE, который в любой последующий момент доказывает, что эти копии по-прежнему зафиксированы в журнале в рамках его текущей контрольной точки. Поскольку events FILE не перечитывает ленту, сохранённый вами экспорт также служит эталоном, с которым вы сравниваете последующий повторный экспорт того же диапазона.

Часто задаваемые вопросы

Was this page helpful?