Это фактическое описание софта, а не юридическая консультация и не сертификат соответствия. Какие
из этих фактов значимы для вашего регулятора и что с ними делать — решение ваше и вашего юриста.
Кто чем владеет
Veriqa поставляется как код, который вы запускаете у себя. В self-hosted-модели это и есть весь ответ на вопрос «куда уходят данные»:- Контроллер — вы. База, ключевой материал и логи находятся на вашей инфраструктуре, под вашими строками подключения. Ничего не разворачивается за вас.
- Veriqa (вендор) не контроллер и не процессор данных ваших пользователей. Вендору Veriqa не передаётся ничего: продукт не звонит домой, не шлёт телеметрию и не имеет вендорского эндпоинта в принципе. Единственные исходящие адреса в коде — API мессенджеров, которые настроили вы, и SMTP-сервер, на который вы его направили (см. Что уходит за периметр).
- Провайдеры мессенджеров — ваши контрагенты, а не вендора Veriqa. Telegram, MAX и WhatsApp Cloud API видят сообщения, которые вы отправляете через собственные боты. Отношения с каждым из них у вас прямые.
Инвентарь персональных данных
Всё, чего касается поставляемый продукт, — и ничего сверх того.
Чего нет в списке: тела сообщений из канала (адаптер читает то, что нужно для опознания
отправителя и подтверждения, и не сохраняет остального) и любой долгоживущий профиль пользователя сверх собранных claims выше. Справочника пользователей
продукт не поставляет — см.
Идентичности каналов.
Умолчания сбора
Это включено «из коробки». Ни один пункт не требует вашего действия, чтобы начать; каждый требует действия, чтобы прекратить.
Две оговорки, которые важнее самих флагов.
Геолокация включена по умолчанию, но по умолчанию бездействует. Для поиска нужны сателлитный
пакет
Veriqa.Core.AuthServer.MaxMind и локальная база .mmdb, а базовые пакеты не несут ни
того, ни другого. Без них провайдер объявляет себя недоступным, и гео-поля остаются пустыми — то
есть штатная установка местоположения не собирает, хотя флаг говорит true. Сбор начинается ровно с
добавлением базы.
IP собирается, но никогда не показывается и не логируется. Он попадает в снапшот внутри
транзакции и дальше не идёт: сообщение подтверждения называет только приложение, браузер, ОС и
регион, а диагностическая запись о недоверенной конфигурации проксирования фиксирует код результата,
а не адрес.
Выключается всё это одной секцией:
appsettings.json
Enabled: false снапшот не строится, а сообщение подтверждения просто не несёт строки
контекста. Можно и сузить, сохранив контекст: убрать region из DisplayFields или поставить
CollectIpAddress: false (тогда отпадёт и геолокация — искать будет не по чему). Подробности и
сужение на уровне приложения — в Контексте инициатора.
Где это хранится
Идентичности каналов: по умолчанию не хранится ничего
Порт, который сохранял бы идентичность канала — id пользователя, телефон, email, отображаемое имя, upsert’ом, без TTL и без удаления, — этоIChannelIdentityRepository, и Veriqa не поставляет его
реализации и не регистрирует ни одной. Вход работает и без неё: разрешённая идентичность едет
вместе с транзакцией и исчезает вместе с ней. Хранить эти данные бессрочно — действие, которое вы
совершаете осознанно, зарегистрировав свою реализацию; см.
Хранилища.
Сроки хранения
Итог: хранилище транзакций опустошает себя примерно за пятнадцать минут после входа, и
единственное хранилище Veriqa, где что-то живёт днями, — журнал аудита. Всё, у чего срок жизни
бессрочный, добавили вы: репозиторий идентичностей канала, хранилище собранных claims или токены со
сроком, который выбрали вы.
Аудит выключен, пока вы не попросите дважды
Два независимых переключателя, и нужны оба:- Сателлит opt-in — хост, который не вызвал
AddVeriqaAuditTrail, журнала не имеет вовсе. Veriqa:Logging:Modeпоставляется какSystem, а записи пишутся только в режимеAudit.DisabledиSystemдля приёмника — одно и то же: не писать.
RetentionDays.
ConfigureRetention лишь настраивает частоту прохода и размер батча — он не «включает» ретенцию, и
его отсутствие не оставляет записи без срока. Ретенция в ноль и меньше отвергается на старте, а не
читается как «не хранить ничего».
Единственный случай, когда не подметает ничто, — ваш собственный приёмник, поданный через
UseSink<TSink>(). Записи тогда живут в вашем хранилище, встроенный проход не регистрируется, и
хост говорит об этом на старте. Границу такому хранилищу ставите вы.
appsettings.json
Что на самом деле лежит в записи аудита
Закрытый набор атрибутов, зафиксированный схемой, — по колонке на атрибут, без произвольного payload: момент, актор, код действия, объект (id транзакции), исход и код причины, плюс тип транзакции, тип канала, correlation id, тенант,client_id, локаль и таймзона интерфейса,
собственные безопасные детали канала и объявленный для него уровень входящей верификации.
Актор замаскирован. Для действия, которое пользователь совершил в канале, это
{канал}:{маскированный id} — читаемыми остаются не более двух последних символов идентификатора.
Немаскированное значение не покидает хранилища транзакций.
Ни IP, ни User-Agent, ни геолокация, ни отображаемое имя, ни email в запись аудита не попадают.
Контекст инициатора живёт в транзакции и умирает вместе с ней.
Единственное исключение, которое можно включить, — параметры подтверждаемой операции: заявленный вид
действия и значения его слотов. Это предметные данные вашего приложения и в них может быть что
угодно, поэтому по умолчанию их нет, и в запись они копируются только по вашему требованию
(Харденинг).
Шифрование
Прикладного шифрования хранимых персональных данных сверх этого одного защищённого поля нет, как нет
и собственного управления ключами. Если ваша модель угроз требует шифрования ПД at-rest, это
требование закрывается на слое хранения, которым управляете вы — шифрованные тома, TDE, защищённое
соединение с базой, — а не настройкой в Veriqa.
Секреты —
client_secret, токены ботов, учётные данные SMTP — живут в переменных окружения или
secret-store, но не в конфигах в репозитории. Пароли в лог не попадают: там, где пароль нужно
сравнить, сравнение идёт по SHA-256-хешу.
Ключи
Три вида ключевого материала, три разных дома. Сертификаты подписи и шифрования токенов. ВDevelopment используются dev-сертификаты
OpenIddict. Вне Development загружаются ваши X.509-сертификаты — путём или base64
(Veriqa:OpenIddict:Server:SigningCertificate* / EncryptionCertificate*), и без них хост не
стартует.
Кольцо ключей DataProtection. Приоритет — Redis
(Veriqa:DataProtection:RedisConnectionString), затем каталог
(Veriqa:DataProtection:KeysDirectory); если не задано ни то, ни другое, ключи живут в памяти и
теряются при перезапуске. Для разработки это нормально, везде остальное — нет: после рестарта
защищённые ожидания живых транзакций уже не прочитать. Data Protection ротирует свои ключи сам, и
значения, записанные прежним ключом, читаются, пока тот в кольце, — так что кольцо на устойчивом
хранилище делает ротацию незаметной.
Секреты каналов и приложений — токены ботов, webhook secret token, client_secret, учётные
данные SMTP. Их ротация — операция на стороне канала и клиента; в Veriqa они не кешируются дольше
перечитывания конфигурации.
Что уходит за периметр
Только то, для чего вы настроили канал. На одно подтверждение исходящее сообщение несёт:- имя приложения, начавшего вход;
- браузер, ОС и регион инициатора — там, где они известны и включены к показу;
- ссылку или кнопки подтверждения и срок действия запроса.
User-Agent, ни профильных данных пользователя, ни того, что
ваше приложение заявило о транзакции.
Куда именно — зависит от канала: api.telegram.org для Telegram, platform-api.max.ru для MAX,
graph.facebook.com для WhatsApp Cloud API и ваш собственный SMTP-сервер для Email. В обратную
сторону канал возвращает профиль отправителя — поля из таблицы инвентаря выше. Мессенджер видит
содержимое сообщения и получателя, потому что это и означает «доставить сообщение»; канал Email
видно ровно столько, сколько видит ваш SMTP-релей.
Внешняя шина событий. Если подключить публикатор RabbitMQ, события транзакций покидают процесс,
неся только безопасную атрибуцию — в том числе маскированную идентичность канала. Параметры
подтверждаемой операции явно исключены из сериализации и на шину не попадают ни при какой настройке
аудита.
Логи
Логи приложения — не журнал аудита и не задуманы как доказательство. Для этой страницы важно, чего в них быть не должно и что с этим делает код: идентификаторы пишутся 16-символьным необратимым отпечатком (старшие байты SHA-256), а не собой, — так оператор по-прежнему сшивает шаги одного входа, а лог при этом не держит идентичности. Токены, секреты и IP инициатора не логируются вовсе. Это поставляемое поведение собственных лог-записей Veriqa. Ваш хост, ваш обратный прокси и request-логирование платформы — вне его: access-лог перед auth-сервером по умолчанию пишет IP клиентов, и границы ему ставятся тем же шагом развёртывания, что настраиваетForwardedHeaders:KnownProxies.
Что остаётся решить вам
Ни у одного пункта нет правильного ответа, который продукт мог бы выбрать за вас.- Держать ли контекст инициатора вообще и добавлять ли базу GeoIP.
- Включать ли аудит, с каким сроком хранения и должны ли записи нести параметры подтверждаемых операций.
- Хранить ли идентичности каналов — и если да, как они удаляются.
- Включать ли хранилище собранных claims и с каким сроком хранения.
- Сколько истёкшие и отозванные записи токенов живут в базе OpenIddict до чистки.
- Где живёт кольцо ключей DataProtection.
- Шифрование at-rest, бэкапы и их сроки — на слое хранения.
- Как исполняется запрос пользователя на удаление по всем вашим хранилищам. Свои строки транзакций
Veriqa удаляет по собственному расписанию, а записи аудита — по ретенции; хранилище собранных
claims вы чистите по
sub(эндпоинтом или вызовом хоста); до всего, что добавили вы, дотягиваетесь вы.
Дальше
Харденинг перед продом
Чек-лист перед выходом в прод.
Хранилища
Какое хранилище что держит и как каждое подключается.
Известные ограничения
Чего продукт не делает.