Контракт хранения и очистки заявок
Текущее состояние
Публичный Supabase endpoint не подключён. Сайт работает в режиме:
lead_capture:
mode: "web3forms"
endpoint: ""
Политика retention подготовлена только в исходниках и после применения миграции остаётся выключенной:
enabled = false
Значения 365, 180 и 7 дней являются техническими стартовыми параметрами для тестирования. Они не считаются утверждённым юридическим сроком и не должны активироваться до отдельного решения владельца, проверки применимых требований и обновления документов сайта.
Миграция
supabase/migrations/202607140001_broker_lead_retention.sql
Миграция добавляет:
retention_hold;anonymized_at;retention_reason_code;- таблицу настроек
broker_lead_retention_settings; - обезличенный журнал успешных запусков
broker_lead_retention_runs; - агрегированный preview
broker_lead_retention_preview(); - подтверждаемое применение
apply_broker_lead_retention(text).
Применение миграции само по себе не запускает очистку и не создаёт Cron job.
Разрешённые terminal-статусы
Retention может учитывать только:
closed;lost;archived;cancelled.
Настройка terminal_statuses ограничена SQL constraint. Добавить в неё new, in_progress, неизвестный или произвольный статус нельзя.
Условия обезличивания
Лид может быть обезличен только при одновременном выполнении всех условий:
anonymized_at is null;retention_hold = false;- статус входит и в настроенный terminal-набор, и в жёсткий SQL whitelist;
notification_statusравенsentилиdisabled;- с даты заявки прошло не меньше настроенного срока;
- политика явно включена;
- оператор передал точную строку подтверждения
APPLY_BROKER_RETENTION.
Заявки со статусами уведомления pending, sending или failed не обезличиваются независимо от возраста.
Любой активный, неизвестный или неутверждённый статус защищён по принципу fail-closed.
Retention hold
retention_hold = true запрещает:
- обезличивание лида;
- удаление связанных событий этой заявки.
Hold снимается только отдельным осознанным административным действием после проверки основания. Автоматического снятия hold нет.
Preview
broker_lead_retention_preview() возвращает только агрегаты:
- включена ли политика;
- текущие сроки;
- количество кандидатов;
- количество активных или неизвестных лидов;
- количество заявок с незавершёнными уведомлениями;
- количество hold-записей;
- количество старых событий и rate-limit записей;
- дату самого старого кандидата.
Preview не возвращает UUID, request ID, имя, телефон, город, источник, комментарий или содержимое заявки.
Preview обязателен перед каждым реальным запуском.
Что удаляется при обезличивании
Очищаются контактные, содержательные и трассировочные данные:
- имя, телефон и город;
- предпочтительный способ связи;
- ипотечная цель, объект, цена, взнос и доход;
- банковская история и комментарий;
- UTM, referrer, URL, User-Agent и source page;
- tracking, qualification и spam payload;
- полный
raw_payload; - preparation и оставшиеся вопросы;
- свободные технические пояснения ошибки уведомления.
Поле phone заменяется техническим значением [anonymized], потому что базовая схема запрещает null.
Сохраняются только минимальные технические признаки, необходимые для целостности и агрегированного аудита, включая внутренний UUID, request ID, даты, terminal-статус, статус доставки, счётчики попыток и время обезличивания.
Что не удаляется
Механизм намеренно не выполняет:
delete from public.broker_leads
Строки лидов не удаляются физически. Это защищает от удаления активной заявки из-за ошибочной настройки и сохраняет минимальную доказуемость выполненной очистки.
Hard delete может быть разработан только отдельной миграцией, отдельным контрактом и отдельным smoke-тестом.
События и rate limit
События удаляются только если:
- связанный лид уже обезличен;
- на лиде нет hold;
- событие старше настроенного срока.
События активных и необезличенных лидов не удаляются.
Rate-limit записи не содержат исходный IP, полный телефон или payload и очищаются существующей функцией purge_broker_lead_rate_limits по отдельному короткому сроку.
Атомарность
Один вызов retention выполняется в одной транзакции.
Если обезличивание, удаление событий, очистка rate limit или запись результата завершаются ошибкой, весь вызов откатывается. Частично очищенного набора и ложной записи completed быть не должно.
broker_lead_retention_runs получает строку только после полного успешного выполнения.
Журнал запуска содержит только:
- run ID;
- время начала и завершения;
- снимок числовых сроков и terminal-статусов;
- количество обезличенных лидов;
- количество удалённых событий;
- количество удалённых rate-limit записей.
Идентификаторы и содержимое заявок в журнал не записываются.
Доступ
Таблицы и RPC:
- недоступны
public; - недоступны
anon; - недоступны
authenticated; - доступны только
service_role.
Функции используют фиксированный search_path = public. Публичный браузер не должен вызывать retention RPC.
Web3Forms и email
Retention Supabase не удаляет:
- email, уже доставленный через Web3Forms;
- данные в стороннем почтовом ящике;
- сообщения в SMS, MAX или ВКонтакте;
- данные в сторонних CRM и переписке.
Сроки и удаление в этих каналах регулируются отдельными настройками и процедурами. Нельзя сообщать пользователю, что Supabase purge удалил копии в сторонних каналах.
Планировщик
Автоматический Cron job намеренно не создаётся миграцией.
После применения миграции и успешного smoke-теста допускается отдельно настроить Supabase Cron на вызов retention-функции. До этого каждый запуск выполняется вручную после preview. Cron не должен включаться одновременно с первым production-тестом.
Активационный барьер
Политика может быть включена только после:
- подтверждения Supabase-проекта;
- применения всех миграций по порядку;
- проверки RLS и прав RPC;
- утверждения terminal-статусов;
- утверждения сроков хранения;
- проверки preview на тестовых данных;
- проверки active, unresolved notification и hold-защит;
- проверки атомарного отката;
- утверждения ответственного и журнала запусков;
- обновления политики и согласия сайта перед реальным серверным хранением;
- отдельной проверки Web3Forms/email retention;
- фиксации результата в issue.
До выполнения этих условий сохраняются enabled = false, mode: web3forms и пустой публичный endpoint.