Прямой ответ
Право на удаление (right to erasure, статья 17 GDPR) позволяет субъекту требовать удаления своих персональных данных. Сложность не юридическая, а инженерная: данные за годы жизни продукта успевают распространиться по таблицам, витринам, очередям, кэшам, резервным копиям и системам аналитики.
Как устроен процесс:
- Приём запроса. Фиксируются дата получения, канал и объём требования. Запрос регистрируется как задача со сроком.
- Идентификация субъекта. Нужно убедиться, что запрос исходит от того, чьи данные удаляются, и не удалить данные по чужому запросу.
- Поиск мест хранения. Инвентаризация по реестру обработки и по фактическому поиску в схемах и коде.
- Удаление или анонимизация. Удаление там, где нет оснований хранить; анонимизация там, где данные нужны для статистики.
- Уведомление получателей. Если данные передавались третьим сторонам, их нужно уведомить об удалении.
- Ответ и доказательство. Ответ субъекту в установленный срок и внутренняя запись о выполненных действиях.
Ключевое различие между удалением и анонимизацией:
- Удаление применяется, когда данные больше не нужны ни для какой цели.
- Анонимизация допустима, когда обезличенные данные необходимы (статистика, обучение моделей) и необратимо не позволяют определить субъекта. Псевдонимизация удалением не является — см. маскирование и анонимизацию.
Законные основания не удалять: требования бухгалтерского и налогового учёта, незавершённые договорные отношения, судебные споры, обязательства по безопасности. В этих случаях обработка ограничивается, а данные не используются для иных целей.
Практика: техническая реализация
1. Единый идентификатор субъекта. Все таблицы с персональными данными должны ссылаться на него. Если e-mail скопирован как текст в десять таблиц, надёжно выполнить удаление невозможно.
2. Процедура удаления как код.
def erase_subject(subject_id: int, reason: str) -> dict:
report = {}
# 1. основные таблицы
report["customers"] = db.execute(
"DELETE FROM customers WHERE id = %s", (subject_id,)).rowcount
# 2. связанные записи
report["orders"] = db.execute(
"UPDATE orders SET customer_pseudo = %s, customer_name = NULL WHERE customer_id = %s",
(pseudo(subject_id), subject_id)).rowcount
# 3. обращения и вложения
report["support"] = db.execute(
"DELETE FROM support_messages WHERE author_id = %s", (subject_id,)).rowcount
# 4. кэши и поисковые индексы
redis.delete(f"user:{subject_id}:*")
search.delete_by_query({"term": {"customer_id": subject_id}})
audit(actor=SYSTEM, action="subject.erase", resource=f"subject/{subject_id}",
result="allowed", details={"report": report, "reason": reason})
return report
3. Резервные копии. Полное удаление из уже созданных копий обычно невозможно. Рабочий подход: копии хранятся ограниченный срок, по истечении которого данные исчезают естественно; доступ к копиям ограничен и журналируется; в ответе субъекту это объясняется. Копия, из которой данные можно восстановить и использовать, — это не «архив», а продолжение обработки.
4. Аналитика и хранилища. В витринах персональные данные заменяются псевдонимами, в сыром слое — удаляются по расписанию. Очереди и потоки событий требуют отдельного внимания: событие с персональными данными могло быть обработано несколькими потребителями.
5. Срок и доказательство. Запрос имеет срок исполнения; процесс должен показывать, на каком шаге он находится. Внутренний отчёт о выполненных действиях — часть подотчётности.
Рекомендации:
- Тестируйте удаление на фиктивном субъекте. Создайте тестового пользователя, «размажьте» его данные по системам, выполните удаление и проверьте, что ничего не осталось. Такой тест ловит новые таблицы, в которые данные начали попадать.
- Не удаляйте то, что нужно хранить по закону, но ограничьте доступ. Отметка «обработка ограничена» и техническое закрытие доступа лучше, чем удаление с последующим восстановлением из копии.
- Логируйте сам факт удаления. Запись о том, что удаление выполнено, не должна содержать удаляемых данных — см. audit log.
- Автоматизируйте регулярное удаление по срокам. Значительная часть запросов не возникнет, если данные удаляются по истечении срока хранения автоматически — см. GDPR и 152-ФЗ.
Практический сценарий: запрос выполнен, но данные остались в аналитике
Контекст: пользователь получил подтверждение удаления. Через месяц он обнаружил свои данные в отчёте, который строится из аналитического хранилища.
- Причина. Процедура удаления охватывала основную БД и кэш, но не аналитическое хранилище: данные туда попадали через CDC-поток и хранились в денормализованном слое с полями имени и e-mail.
- Дополнительно. Ежедневная выгрузка отчётов содержала исторические срезы, поэтому данные присутствовали и в файлах отчётов на общем диске.
- Действия. (а) Расширили процедуру удаления на аналитический слой; (б) в CDC-потоке заменили идентифицирующие поля на псевдонимы до записи в хранилище; (в) очистили накопленные файлы отчётов и ограничили доступ к каталогу; (г) добавили проверку, что в аналитическом слое нет полей из реестра персональных данных.
- Проверка. Повторили сценарий на фиктивном субъекте: после удаления поиск по всем системам, включая хранилище и файлы отчётов, не находит значений.
- Профилактика. В процесс добавили правило: новый потребитель CDC-потока проходит проверку на наличие персональных полей до подключения.
Вывод: запрос на удаление выявляет реальную карту данных, которая почти всегда шире документации. Пока процедура не протестирована на всех системах, утверждать об исполнении нельзя.
FAQ
Можно ли ответить отказом на запрос об удалении? Да, если есть законное основание для хранения: налоговые сроки, незавершённый договор, судебный спор. Отказ должен быть обоснованным и сообщён субъекту; данные при этом не используются для других целей.
Обязательно ли удалять данные из резервных копий немедленно? Как правило, достаточно обеспечить, чтобы данные не восстанавливались и не использовались, а копии уничтожались по истечении своего срока. Ключевое — отсутствие практической возможности вернуть данные в обработку.
Что делать с данными в очередях и потоках событий? События, уже обработанные потребителями, нужно учитывать как места хранения. Практика: не класть персональные данные в тело события, передавать только идентификатор, а данные читать из источника, где удаление выполняется централизованно.
Как доказать, что удаление выполнено? Внутренним отчётом процедуры: какие системы затронуты, сколько записей удалено или анонимизировано, когда и кем. Отчёт хранится в журнале и не содержит самих удалённых данных.
Источники: GDPR Article 17 (right to erasure), Article 12 (процедура ответа), PostgreSQL docs — ссылки в шапке.