From d430ac5f0a74f1e0c77b991be6b6f86ba91707aa Mon Sep 17 00:00:00 2001 From: erjemin Date: Mon, 17 Aug 2026 23:42:38 +0300 Subject: [PATCH] =?UTF-8?q?mod:=20=D0=BF=D1=80=D0=B8=D0=BD=D1=86=D0=B8?= =?UTF-8?q?=D0=BF=D1=8B=20=D0=BF=D1=80=D0=B8=D0=B2=D0=B0=D1=82=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _blueprint/plan-draft.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/_blueprint/plan-draft.md b/_blueprint/plan-draft.md index eb2f213..d625793 100644 --- a/_blueprint/plan-draft.md +++ b/_blueprint/plan-draft.md @@ -329,12 +329,15 @@ HTMX: форма с `hx-post`, `hx-encoding="multipart/form-data"` → SVG вс ### 4. Политика хранения, приватность и модели -#### 4.1. Принципы приватности и Zero-PII (Без регистрации) +#### 4.1. Принципы приватности, Zero-PII и учет голосов - **Полное отсутствие регистрации для посетителей:** Пользователи не создают аккаунты, не вводят email, пароли или личные данные. Единственный пользователь в `auth.User` — администратор сайта для входа в Django Admin. - **Исходные растровые изображения (JPG/PNG/WEBP):** Обрабатываются исключительно в оперативной памяти (через буфер `BytesIO`) и **не сохраняются на диск сервера вообще**. +- **Куки-согласие и идентификация устройства (Cookie-токен):** + - При согласии с правилами («Подчиниться Гипножабе!» в `allow-tracking.html`) клиенту выставляется долгоживущая анонимная кука устройства `hypn0_vid` со случайным UUID (`Max-Age=2 года`, `SameSite=Lax`, `HttpOnly`). + - **Голосование доступно только при наличии согласия на куки:** Если посетитель не принял соглашение (кука отсутствует), голосование заблокировано интерфейсом и отклоняется бэкендом (с требованием подчиниться Гипножабе). - **Лайки и учет голосов:** - - **Бэкенд:** Голоса учитываются анонимно через связку `(item_id, fingerprint)`. Поле `fingerprint` формируется как необратимый SHA-256 хэш: `sha256(IP + User-Agent + SECRET_KEY)`. Это защищает от примитивной накрутки через очистку кук или инкогнито и не сохраняет персональные данные (Zero-PII). - - **Фронтенд:** Для исключения переполнения cookies и сетевого оверхеда список лайкнутых картин хранится локально на клиенте в **`localStorage`** (до 5–10 МБ). На базе Alpine.js выполняется мгновенная индикация проголосованных работ. + - **Бэкенд:** Голоса учитываются анонимно через связку `(item_id, fingerprint)`. Поле `fingerprint` формируется как необратимый хэш: `sha256(visitor_uuid + SECRET_KEY)`. Это надежно разделяет разные компьютеры в одной корпоративной сети/NAT и не содержит открытых ПДн (Zero-PII). + - **Фронтенд:** Для быстродействия UI и исключения лишней нагрузки список лайкнутых картин дублируется локально на клиенте в **`localStorage`** (`hypn0_votes`). На базе Alpine.js выполняется мгновенная индикация проголосованных работ. - **Соответствие GDPR / 152-ФЗ:** Персональные данные не собираются и не хранятся. #### 4.2. Генерация названий (AI & Fallback Title) @@ -402,7 +405,7 @@ class HalftoneVote(models.Model): fingerprint = models.CharField( max_length=64, db_index=True, - help_text="SHA256(IP + User-Agent + SECRET_KEY) для базовой защиты от накрутки" + help_text="SHA256(visitor_uuid + SECRET_KEY) для защиты от накрутки и разделения устройств" ) created_at = models.DateTimeField(auto_now_add=True)