Что может пойти не так при внедрении политик с учетом типа актера?
Политика с учетом типа актера меняет то, как ваше приложение отвечает в зависимости от того, кто или что действует. Если все сделано правильно, люди получают бесшовный опыт, легитимные агенты получают структурированный путь, а лишние ограничения появляются только там, где это действительно важно. Если все сделано плохо, вы блокируете реальных пользователей, ломаете интеграции, от которых зависят клиенты, и создаете обращения в поддержку, которые никто не может объяснить.
Разница редко в самой логике политики. Она в внедрении. (Саму модель политики см. в разработке политик на уровне приложения для людей и AI-агентов.) В этом руководстве описан поэтапный процесс, которому команды могут следовать для любого маршрута: наблюдать, предварительно просматривать, применять на части трафика, а затем расширять. У каждого этапа есть четкий критерий выхода и быстрый путь назад.
Три режима
Думайте о каждой политике как о работающей в одном из трех режимов для каждого маршрута:
- Наблюдение. Классификации записываются. Приложение отвечает точно так же, как и без них.
- Предпросмотр. Политика вычисляется, и ее решение записывается, но не применяется. Вы видите, что бы произошло.
- Применение. Решение применяется к реальным запросам.
Режим относится к паре маршрут и политика, а не ко всему приложению. Ваши страницы документации могут работать в режиме применения, пока checkout все еще находится в наблюдении.
Шаг 1: Наблюдайте, пока не поймете базовую линию
Начните с каждого маршрута в режиме наблюдения. Собирайте как минимум:
- маршрут и метод,
- класс актера (Human, Human + AI, Agent или Unknown) и его основание (verified, declared, inferred или unknown), как определено в нашей таксономии для трафика приложений,
- статус ответа и простой маркер результата для маршрута, например "account created" или "search returned results".
Достаточно долгое время, чтобы покрыть обычные недельные циклы и любой релиз, который вы выпускаете в этот период. Затем зафиксируйте базовую линию для каждого важного для вас маршрута: состав классов, долю Unknown и долю результатов по классам. Все последующее вы будете сравнивать с этими числами.
Критерий выхода: вы можете описать для каждого кандидата на маршрут, кто им пользуется и чем результаты отличаются по классам.
Шаг 2: Опишите политику как данные
Политики проще проверять, тестировать и откатывать, когда они представлены как данные, а не как разбросанные if операторы.
type ActorClass = "human" | "human_ai" | "agent" | "unknown";
type Basis = "verified" | "declared" | "inferred" | "unknown";
type Action = "allow" | "adapt" | "challenge" | "review" | "limit";
type Mode = "observe" | "preview" | "enforce";
interface Rule {
actor: ActorClass | "*";
basis?: Basis[];
action: Action;
}
interface RoutePolicy {
route: string;
mode: Mode;
enforcePercent: number;
rules: Rule[];
fallback: Action;
}
export const policies: RoutePolicy[] = [
{
route: "GET /api/catalog",
mode: "preview",
enforcePercent: 0,
rules: [
{ actor: "agent", basis: ["verified"], action: "allow" },
{ actor: "agent", basis: ["declared", "inferred"], action: "limit" },
],
fallback: "allow",
},
];У каждой политики есть явный fallback. Это действие используется для результатов Unknown, для таймаутов и для любых случаев, которые не покрыты правилами. Осознанный выбор этого действия - самое важное решение по безопасности во всем процессе.
Шаг 3: Выполняйте оценку в одном месте
Одна функция оценки обеспечивает согласованное поведение во всех режимах.
export function decide(policy: RoutePolicy, actor: ActorClass, basis: Basis): Action {
for (const rule of policy.rules) {
const actorMatch = rule.actor === "*" || rule.actor === actor;
const basisMatch = !rule.basis || rule.basis.includes(basis);
if (actorMatch && basisMatch) return rule.action;
}
return policy.fallback;
}Затем примените режим:
export function applyPolicy(policy: RoutePolicy, actor: ActorClass, basis: Basis, requestKey: string) {
const decision = decide(policy, actor, basis);
const inSlice = bucket(requestKey) < policy.enforcePercent;
const enforced = policy.mode === "enforce" && inSlice;
record({ route: policy.route, mode: policy.mode, actor, basis, decision, enforced });
return enforced ? decision : "allow";
}
function bucket(key: string): number {
let h = 0;
for (const c of key) h = (h * 31 + c.charCodeAt(0)) >>> 0;
return h % 100;
}Стабильная корзина означает, что одна и та же сессия или клиент остается внутри или вне применяемой части, поэтому люди не видят, как поведение меняется от запроса к запросу.
Шаг 4: Как измерить ложные срабатывания до применения?
Переведите один маршрут в предпросмотр. Теперь каждый запрос записывает решение, которое он получил бы. Это тот момент, когда вы понимаете, правильна ли политика.
Ложное срабатывание - это запрос, который политика ограничила бы, хотя его следовало разрешить. Нельзя измерить это только по классификациям, потому что именно классификацию вы и проверяете. Измеряйте это по независимым признакам легитимного использования:
- запрос завершил обычный успешный сценарий, например вошедший в систему пользователь сохранил работу,
- клиент - известная партнерская интеграция или подтвержденный оператор, которого вы согласились обслуживать,
- обращения в поддержку или отчеты пользователей ссылаются на затронутый маршрут,
- ручная проверка выборки запросов, которые были бы ограничены.
Проверьте выборку вручную. Прочитать двадцать реальных запросов, которые политика должна была бы challenged, - это самый быстрый способ найти слишком широкое правило.
Критерий выхода: множество запросов, которые были бы ограничены, в основном состоит из трафика, который вы действительно намерены ограничивать, и у вас есть объяснение для каждой категории найденного ложного срабатывания.
Шаг 5: Применяйте на части трафика
Переведите маршрут в применение с небольшим enforcePercent. Размер части должен быть достаточно малым, чтобы ошибка затронула немного запросов, и достаточно большим, чтобы за день или два появился измеримый сигнал.
Следите за теми же метриками, которые вы задали как базовую линию:
- доля успешных результатов по классам на маршруте,
- доля ошибок и завершения challenge,
- объем обращений в поддержку с упоминанием маршрута,
- задержка, поскольку оценка находится на пути запроса.
Если результаты для трафика Human падают в применяемой части по сравнению с остальным трафиком, остановитесь и разберитесь, прежде чем расширять.
Шаг 6: Расширяйте постепенно
Увеличивайте долю по шагам, например с небольшой части до четверти, затем до половины, затем до всего трафика, задерживаясь на каждом шаге достаточно долго, чтобы увидеть обычный цикл. Расширение скучное, когда ранние этапы были выполнены хорошо. В этом и состоит цель.
Выбор запасного варианта и поведение при сбое
Заранее решите, что происходит, когда нет данных или оценка не может выполниться.
- Fail open означает, что запрос проходит так, как будто контекста актера нет. Используйте это для низкорисковых маршрутов, таких как публичные страницы, документация и endpoint только для чтения каталога.
- Fail closed означает, что применяется ваша существующая более строгая проверка, например повторная аутентификация или очередь на проверку. Используйте это для действий с высоким воздействием, где такая проверка у вас уже есть.
Никогда не допускайте, чтобы timeout или ошибка давали результат Human. Отсутствие данных - это Unknown, и Unknown получает запасной вариант маршрута. В нашей публикации почему Unknown - допустимый результат при классификации AI-трафика объясняется, почему это правило важно.
async function actorWithTimeout(evaluate: () => Promise<{ actor: ActorClass; basis: Basis }>) {
const timeout = new Promise<{ actor: ActorClass; basis: Basis }>((resolve) =>
setTimeout(() => resolve({ actor: "unknown", basis: "unknown" }), 150),
);
return Promise.race([evaluate(), timeout]);
}Как быстро откатить политику?
Откат должен быть изменением конфигурации, а не deploy. Храните политики в хранилище, которое команда может быстро редактировать, и сделайте эти действия мгновенными:
- Вернуть маршрут в режим предпросмотра, что останавливает применение, сохраняя измерение.
- Установить
enforcePercentв ноль. - Отключить одно правило, не затрагивая остальные.
Записывайте каждое изменение политики с указанием, кто его сделал и когда. Когда результаты меняются, первый вопрос всегда один: что изменилось?
Избегайте решений, имеющих последствия для людей
Классификации акторов описывают доказательства об взаимодействии. Это не оценка человека. Не используйте inferred-класс как единственное основание для решений, которые влияют на занятость, кредит, образование, жилье или доступ к жизненно важным услугам. Для таких потоков используйте контекст актера, чтобы выбрать процесс, например направить на ручную проверку, а не определять итог.
Сообщите до того, как начнете применять
Политики, влияющие на автоматизированных клиентов, влияют и на людей и компании, которые ими управляют. Небольшое оповещение сильно сокращает объем поддержки:
- Опубликуйте правила для автоматизированного доступа. Укажите, какие маршруты открыты, какие ограничения действуют и как клиенты могут идентифицировать себя с помощью подписанных запросов, используя HTTP Message Signatures (RFC 9421) и черновик протокола IETF Web Bot Auth.
- Заранее предупредите партнеров и интеграторов. Если известная интеграция попадает в ограниченную часть во время предпросмотра, свяжитесь с ее владельцем до того, как начнете применять.
- Возвращайте полезные ответы. Когда политика ограничивает запрос или требует challenge, отвечайте понятным кодом статуса, например
429 Too Many RequestsсRetry-After, и ссылкой на вашу документацию. Машиночитаемое тело в формате Problem Details дает автоматизированным клиентам структурированную причину. Хорошо построенные агенты адаптируются, когда понимают, почему это произошло. - Дайте вашей службе поддержки доказательства. Когда приходит обращение о заблокированном запросе, поддержка должна уметь найти маршрут, класс, основание и решение политики без обращения к engineering.
Команды, которые объявляют изменения и объясняют их, видят гораздо меньше сюрпризов, чем команды, которые молча переключают правила, а клиенты, которые адаптируются, со временем становятся легче распознаваемыми.
Чек-лист для каждого маршрута
- Зафиксирована базовая линия по составу классов, доле Unknown и результатам.
- Политика описана как данные с явным запасным вариантом.
- Предпросмотр запущен, выборка проверена, категории ложных срабатываний объяснены.
- Применение начато на небольшой части, метрики отслеживаются.
- Выбрано поведение при сбое: fail open или fail closed.
- Откат протестирован до расширения.
Как Proof of Actor вписывается в это
Proof of Actor построен вокруг этого процесса. Наблюдение - это режим по умолчанию, каждый результат несет свое основание, а политики Route - это то, что вы определяете и применяете в своем коде, маршрут за маршрутом. Detect, Understand, Route: именно в таком порядке.
Чтобы пройти через внедрение в вашем собственном приложении вместе с нашей командой, подайте заявку на ранний доступ. Для полного потока принятия решений прочитайте Как работает Proof of Actor.
Источники
- RFC 6585: Additional HTTP Status Codes, Section 4: код статуса
429 Too Many Requests - RFC 9110: HTTP Semantics, Retry-After: как сообщать клиентам, когда повторить попытку
- RFC 9457: Problem Details for HTTP APIs: машиночитаемые тела ошибок
- RFC 9421: HTTP Message Signatures: как автоматизированные клиенты подписывают запросы
- draft-ietf-webbotauth-httpsig-protocol: черновик IETF Web Bot Auth для подписанного автоматизированного трафика (work in progress по состоянию на November 2026)