Одна галочка не решает всё: почему я разделил согласия и cookie-баннер в Django

Когда на сайте появляется первая форма обратной связи, задача кажется простой: добавить ссылку на политику, поставить галочку «Согласен на обработку персональных данных» и показать уведомление о файлах cookie.

Но затем возникают вопросы, которые одной галочкой уже не закрыть.

Как доказать, какую именно редакцию документа видел пользователь? Что делать, когда изменилась цель обработки или состав собираемых полей? Как пользователю отозвать согласие? Как не запускать счётчики и внешние сценарии до выбора посетителя? И почему закрытие cookie-баннера не должно автоматически считаться согласием?

Я разбирался с этой задачей для Django-проектов и в итоге сделал не один большой модуль «на все случаи», а два полностью независимых пакета:

  • django-consent-152fz — для жизненного цикла согласий на обработку персональных данных;
  • django-cookies-152fz — для работы с файлами cookie, баннером, категориями и запуском сценариев по выбору пользователя.

Это не юридическая консультация и не обещание автоматического соответствия требованиям закона. Это попытка превратить типовую юридико-техническую задачу в прозрачную архитектуру, которую можно внедрять, проверять и развивать.

С чего обычно начинается проблема

На старте у большинства сайтов есть примерно такой набор:

  • форма заявки;
  • регистрация;
  • ссылка на политику обработки персональных данных;
  • одна или несколько галочек;
  • баннер о файлах cookie;
  • подключённая аналитика, карты, виджеты или внешние сервисы.

Пока проект небольшой, всё выглядит рабочим. Но сайт развивается: появляются новые формы, личный кабинет, рассылки, интеграции, дополнительные поля в анкете, разные категории файлов cookie.

И в какой-то момент выясняется, что нужно ответить не только на вопрос «есть ли галочка», но и на более важные:

  • кто дал согласие;
  • на какую цель;
  • на какой документ и его редакцию;
  • когда именно это произошло;
  • было ли согласие отозвано;
  • какие действия совершались после отзыва;
  • какие файлы cookie и внешние сценарии были разрешены посетителем.

Согласие — это не элемент интерфейса. Это состояние, история и подтверждаемые сведения.

Согласие на персональные данные и cookie — похожи только внешне

Пользователь действительно видит похожие элементы: чекбокс, кнопку «Принять», ссылку на документ. Но технически это два разных процесса.

Согласие на обработку персональных данныхВыбор по файлам cookieПривязано к конкретной цели обработки и документуПривязано к категориям cookie, политике и подключаемым сценариямОбычно относится к пользователю или заявителюМожет существовать у анонимного посетителя до входа на сайтТребует хранения редакции документа и записи о согласииТребует хранения выбранных категорий и истории решенийМожет быть отозвано пользователемМожет быть изменено в настройках баннераИзменение документа может потребовать повторного согласияИзменение политики и изменение текста баннера — разные событияПосле отзыва нужен отдельный порядок действий в продуктеПосле отказа нельзя загружать сценарии, относящиеся к отклонённой категории

Главная архитектурная ошибка — сделать одну универсальную таблицу Consent, в которой вперемешку хранятся и согласия на обработку персональных данных, и выбор файлов cookie.

На первый взгляд это экономит время. На практике создаёт путаницу.

Например, дизайнер поменял текст или положение cookie-баннера. Это не должно автоматически превращать согласие на обработку персональных данных в недействительное.

Или посетитель закрыл баннер, не выбирая категории. Это не означает, что он согласился на аналитические или рекламные сценарии.

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

Баннер файлов cookie: посетитель выбирает, какие категории разрешить.
Баннер файлов cookie: посетитель выбирает, какие категории разрешить.
Блок согласия в форме записи на курс: это уже отдельный процесс, связанный с документом и целью обработки.
Блок согласия в форме записи на курс: это уже отдельный процесс, связанный с документом и целью обработки.

Что хранит модуль согласий

django-consent-152fz построен вокруг жизненного цикла согласия.

В нём есть:

  • документы и их редакции;
  • цели обработки;
  • записи о согласиях;
  • журнал операций;
  • возможность отзыва;
  • страница самообслуживания пользователя;
  • административная проверка записей;
  • необязательный контур подтверждённых и бумажных согласий;
  • прикладной программный интерфейс для интеграции с внешними частями проекта.

Вместо абстрактного «пользователь поставил галочку» система хранит контекст: к какому документу относилось согласие, какая редакция действовала на тот момент, для какой цели оно было получено и в каком состоянии находится сейчас.

Это важно и для пользователя, и для команды проекта.

Пользователь должен иметь понятный способ посмотреть свои согласия и отозвать их. Команда должна видеть историю и понимать, почему конкретная функция доступна или заблокирована.

Раздел самообслуживания: пользователь видит свои согласия и их состояние.
Раздел самообслуживания: пользователь видит свои согласия и их состояние.
Проверка записей о согласиях в административной панели Django.
Проверка записей о согласиях в административной панели Django.

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

Но техническая система должна хотя бы не потерять сам факт отзыва и передать его в прикладную логику: заблокировать услугу, ограничить сценарий, поставить задачу на удаление либо выполнить другой предусмотренный порядок.

Почему редакции документов важнее самой галочки

Допустим, в форме регистрации изначально собираются имя и электронная почта. Позже в форму добавляют номер телефона, дату рождения или дополнительные сведения.

С точки зрения разработки это может выглядеть как небольшое изменение формы. Но с точки зрения согласия меняются состав данных, цель или условия обработки.

Поэтому в модуле есть редакции документов и механизм актуальности согласий. При изменении значимых условий проект может запросить новое согласие и до его получения ограничить функцию, которая зависит от этого согласия.

При этом решение о том, когда именно требуется новая редакция и повторное согласие, остаётся за оператором и его юристами. Модуль не подменяет эту оценку, а даёт технический механизм для её реализации.

Что делает отдельный модуль cookie

django-cookies-152fz отвечает за другую часть задачи:

  • отображение баннера;
  • выбор категорий файлов cookie;
  • редакции политики cookie;
  • отдельные редакции текста и оформления баннера;
  • серверное хранение решений;
  • работу с анонимным посетителем через токен;
  • привязку истории к пользователю после входа;
  • реестр подключённых файлов cookie и сценариев;
  • запрет запуска сценариев до получения нужного выбора;
  • журнал событий и выгрузку данных.

Здесь есть важное правило: состояние отображения баннера и состояние решения пользователя — не одно и то же.

Посетитель мог закрыть баннер, но не выбрать категории. Поэтому действие dismiss не создаёт согласие и не отзывает его. Оно влияет только на отображение интерфейса.

Ещё один важный момент — источником истины является серверная база данных, а не только значение в браузере. Для анонимного посетителя используется токен. После входа на сайт записи при необходимости могут быть связаны с учётной записью.

Такой подход помогает не терять историю при смене устройства, очистке браузера или переходе пользователя от анонимного сценария к личному кабинету.

Реестр файлов cookie и подключённых интеграций в административной панели.
Реестр файлов cookie и подключённых интеграций в административной панели.
Записи о решениях посетителей по категориям cookie.
Записи о решениях посетителей по категориям cookie.

Отдельно о политике и баннере

Я сознательно разделил редакцию политики cookie и редакцию баннера.

Политика описывает, какие файлы cookie и сценарии используются, для чего нужны категории и какие правила действуют.

Баннер — это интерфейс: его текст, положение, внешний вид, кнопки и способ показа.

Можно изменить оформление баннера, не меняя политику. И наоборот: изменить политику, сохранив привычный интерфейс.

Если смешать эти две сущности, обычное изменение кнопки или цвета может неожиданно повлиять на состояние решений пользователей. В техническом контуре это лишняя связанность, которую лучше не создавать.

Как это подключается к Django

Модули можно устанавливать по отдельности.

Только согласия:

pip install django-consent-152fz

Только файлы cookie:

pip install django-cookies-152fz

Оба модуля:

pip install django-consent-152fz django-cookies-152fz

Минимальное включение модуля согласий:

INSTALLED_APPS = [ # ... "django_consent_152fz", ] DJANGO_CONSENT_152FZ = { "enable_core": True, }

Минимальное включение модуля cookie:

INSTALLED_APPS = [ # ... "django_cookies_152fz", ] DJANGO_COOKIES_152FZ = { "enable_cookies": True, }

В базовый шаблон добавляется отображение баннера:

{% load cookies_tags %} {% render_cookie_banner %}

Дальше начинается уже не механическая установка, а нормальная работа над проектом: определить формы, цели, документы, категории cookie, подключаемые внешние сценарии и порядок действий после отзыва согласия.

Модуль не должен самовольно добавлять одинаковую галочку во все формы. Разработчик явно связывает конкретную форму с нужной целью и документом.

Что я намеренно не пытаюсь автоматизировать

Есть соблазн назвать подобный пакет «решением для соответствия 152-ФЗ» и пообещать, что после установки сайт будет полностью защищён.

Это было бы неправдой.

Пакет не:

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

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

Что хочу развивать дальше

Отдельное направление — подтверждённые согласия.

В модуле уже предусмотрены сценарии, где согласие фиксируется не только через веб-форму, но и, например, подтверждается сотрудником на основании бумажного документа. Для таких случаев особенно важны история, прикреплённые материалы и проверяемость действий.

Следующий сложный этап — интеграция с «Госключом» и электронной подписью. Это не просто задача «подключить ещё один внешний сервис». Нужно корректно выстроить весь процесс: идентификацию пользователя, подписание конкретной редакции документа, хранение подтверждений и дальнейшую проверку.

Пока это направление прорабатывается отдельно и не позиционируется как готовая функция текущего выпуска.

Зачем проект опубликован с открытым исходным кодом

Я выбрал MIT-лицензию, потому что хочу получить обратную связь от людей, которые реально поддерживают Django-проекты: интернет-магазины, образовательные платформы, личные кабинеты, сервисы записи, корпоративные сайты и внутренние системы.

Особенно интересны реальные сценарии:

  • как у вас устроены повторные согласия после изменения документов;
  • где пользователи чаще всего отзывают согласия;
  • какие внешние сценарии и счётчики нужно удобно связывать с категориями cookie;
  • какие интеграции с Django-проектами и CMS были бы наиболее полезны;
  • какие отчёты и выгрузки действительно нужны команде проекта или юристам.

Исходный код, документация, примеры и демонстрационный сайт доступны в репозитории django-consent-152fz. Пакеты опубликованы отдельно: django-consent-152fz и django-cookies-152fz.

Буду рад замечаниям к архитектуре, сценариям использования и предложениям по доработке.

11