This commit is contained in:
2026-08-19 02:15:57 +07:00
parent 72605a3cd4
commit 204a20c814
25 changed files with 2892 additions and 500 deletions
+123
View File
@@ -0,0 +1,123 @@
# ЧЕК-ЛИСТ COMPLIANCE: ПРИВЕДЕНИЕ СЕРВИСА В СООТВЕТСТВИЕ С ДОКУМЕНТАМИ
Сервис «Вечерний детектив» · Обновлено: 18.08.2026
Сопутствующие документы: `docs/TERMS.md` (Пользовательское соглашение), `docs/PRIVACY.md` (Политика конфиденциальности), `docs/CONSENT.md` (Согласие на обработку ПДн).
Легенда: ✅ — реализовано, 🟡 — частично / требует решения владельца, ⬜ — осталось сделать.
---
## 1. Юридические документы
| № | Задача | Статус | Примечание |
|---|---|---|---|
| 1.1 | Пользовательское соглашение (оферта) | ✅ | `docs/TERMS.md` — заполнить плейсхолдеры, утвердить у юриста |
| 1.2 | Политика конфиденциальности (152-ФЗ) | ✅ | `docs/PRIVACY.md` — заполнить плейсхолдеры, утвердить у юриста |
| 1.3 | Текст согласия на обработку ПДн | ✅ | `docs/CONSENT.md` — встроить в форму регистрации |
| 1.4 | Публикация документов на сайте по постоянным URL | ✅ | RPC `GetTerms`/`GetPrivacy`/`GetConsent` (`api/main.proto`, пути `/terms`, `/privacy`, `/consent`); текст встраивается из `docs/embed.go`; подставить реальные домены в тексты документов |
## 2. Акцепт соглашений при регистрации (ст. 428 ГК РФ, ст. 9 152-ФЗ)
| № | Задача | Статус | Где |
|---|---|---|---|
| 2.1 | Поля `accept_terms` / `accept_privacy` в запросе регистрации | ✅ | `api/main.proto` (`SignupReq`), перегенерирован `proto/` |
| 2.2 | Серверная проверка: регистрация без акцепта отклоняется (`ErrTermsNotAccepted`) | ✅ | `internal/services/users_service/service.go``AddUser`; `internal/app/server.go``Signup` |
| 2.3 | Таблица `user_agreements` (user_id, тип, версия, дата, IP, user-agent) | ✅ | `migrations/20260818231943_create_user_agreements_table.sql` |
| 2.4 | Фиксация акцепта при регистрации (terms + privacy), атомарно с созданием пользователя | ✅ | `users_repo.AddUserWithAgreements` (одна транзакция: пользователь не существует без записей о согласиях) |
| 2.5 | Версии документов как константы (`termsVersion`, `privacyVersion`) | ✅ | `users_service/service.go` — при новой редакции документов поднять версию |
| 2.6 | Чекбоксы в форме регистрации (не предустановленные!) + блокировка отправки | ⬜ | Фронтенд (репозиторий фронта) |
| 2.7 | Возраст 18+ (текст + проверка) | 🟡 | В документах и коде — запрет; проверить, что форма запрашивает подтверждение возраста |
| 2.8 | Фиксация IP и user-agent клиента при акцепте (ст. 9 ч. 3 152-ФЗ) | ✅ | `clientInfoFromContext`: `X-Real-IP` от доверенного прокси (матчер в `cmd/evening_detective_server/main.go`), иначе последний элемент `X-Forwarded-For`; UA — `grpcgateway-user-agent` |
## 3. Удаление аккаунта и данных (ст. 14, 21 152-ФЗ)
| № | Задача | Статус | Где |
|---|---|---|---|
| 3.1 | Эндпоинт `DELETE /api/auth/delete-account` (авторизован JWT) | ✅ | `api/main.proto` (`DeleteAccount`), `internal/app/server.go` |
| 3.2 | Удаление аккаунта: ПДн удаляются (refresh-токены, учётная запись); записи об акцептах СОХРАНЯЮТСЯ обезличенными (факт/версия/время; `user_id` отвязывается через FK `ON DELETE SET NULL`, `ip`/`user_agent` обнуляются — бремя доказывания согласия на операторе, ст. 9 ч. 4 152-ФЗ) | ✅ | `internal/repos/users_repo/repo.go``DeleteUser` (транзакция); миграции `20260818231943_create_user_agreements_table.sql`, `20260818232725_keep_content_on_user_delete.sql` |
| 3.2а | Подтверждение паролем при удалении аккаунта (защита от удаления чужим обладателем украденного access-токена) | ✅ | HTTP-заголовок `X-Password` (матчер в `cmd/evening_detective_server/main.go`) → `users_service.DeleteAccount` (bcrypt-сверка); пароль не попадает в URL/query |
| 3.3 | Судьба контента при удалении аккаунта | ✅ | Выбран вариант «отчуждение исключительного права на опубликованные Сценарии»: контент сохраняется, автор не вправе требовать удаления (п. 7.2, 7.6, 7.8 TERMS; ст. 1234, 1269 ГК РФ) |
| 3.4 | NULL-safe чтение сценариев с обезличенным автором | ✅ | `scenarios_repo` (scan через указатели), `mapUser` возвращает nil → `author: null` в API (клиент показывает «Автор удалён») |
| 3.5 | Удаление файлов из S3 при удалении аккаунта | ⬜ | Сейчас удаляются только записи в БД; файлы пользователя в S3 (`file_service`) остаются — добавить вызов `fileStorage.Delete` для файлов автора |
| 3.6 | UI-кнопка «Удалить аккаунт» + подтверждение | ⬜ | Фронтенд |
| 3.7 | Отзыв согласия без удаления аккаунта (ст. 9 ч. 2, 152-ФЗ) | ⬜ | Опционально: отдельный эндпоинт «отозвать согласие» → прекращение обработки, блокировка аккаунта |
| 3.8 | Инвалидация выданных access-токенов после удаления аккаунта | 🟡 | JWT без revoke-листа: refresh-токен удаляется сразу, access-токен действует до истечения TTL (3 ч, `processor_jwt`); запросы с устаревшим токеном после удаления получат ошибку FK/«Пользователь не найден». Защита: короткий TTL; при необходимости — версия токена/чёрный список |
**Примечание по акцептам (п. 3.2):** решение владельца — хранить записи об акцептах обезличенными после удаления аккаунта (факт/версия/время без `user_id`/`ip`/`user_agent`): ст. 9 ч. 4 152-ФЗ возлагает на оператора бремя доказывания получения согласия. Альтернатива, если позже решат уничтожать и их (ст. 21 152-ФЗ): вернуть FK `ON DELETE CASCADE` в миграции `20260818231943` и `DELETE FROM user_agreements WHERE user_id = $1` в `DeleteUser`.
## 3а. Отчуждение исключительных прав на сценарии (ст. 1234, 1269 ГК РФ)
| № | Задача | Статус | Где |
|---|---|---|---|
| 3а.1 | Пункт TERMS об отчуждении исключительного права при публикации (безвозмездно, в полном объёме) | ✅ | `docs/TERMS.md` п. 7.27.4 |
| 3а.2 | Запрет автору удалять / снимать с публикации опубликованный сценарий (`ErrScenarioPublished`); ПРАВКА КОНТЕНТА опубликованного сценария РАЗРЕШЕНА владельцу (решение владельца продукта) | ✅ | `internal/services/scenarios_service/service.go`; админ — исключение; guard в SQL от гонки «чтение → запись» для status/delete |
| 3а.3 | Проверка владельца сценария при всех изменениях (public/draft/delete/update/места) (`ErrScenarioNotOwner`) | ✅ | `internal/services/scenarios_service/service.go``getScenarioForChange` |
| 3а.4 | Право на отзыв ограничено моментом обнародования (ст. 1269 ГК РФ) | ✅ | `docs/TERMS.md` п. 7.6 |
| 3а.5 | Отдельный чекбокс «передаю исключительные права» при первой публикации + серверная проверка | ⬜ | Фронтенд + бэкенд (сейчас публикация доступна владельцу без доп. подтверждения; добавить `confirm_transfer` в `PublicScenarioReq` при необходимости) |
| 3а.6 | Проверка владельца при редактировании сценария (UpdateScenario, AddScenarioPlace и др.) | ✅ | `getScenarioForChange` в `internal/services/scenarios_service/service.go`; правка опубликованного разрешена (решение владельца, см. 3а.2) |
| 3а.7 | Оценка рисков ЗоЗПП (ст. 16) для безвозмездного отчуждения в договоре присоединения | 🟡 | См. «Риски» ниже; при запуске для широкой аудитории — консультация юриста и судебная практика |
**Риски отчуждения прав в договоре присоединения:**
- **ЗоЗПП, ст. 16**: безвозмездное отчуждение исключительного права на пользовательский контент в оферте для потребителя может быть оспорено как условие, ущемляющее права потребителя. Снижение риска: отдельное явное подтверждение при публикации, возможность отозвать Сценарий до публикации (черновики не отчуждаются), прозрачное выделение условия.
- **Личные неимущественные права** (ст. 1265 ГК РФ) не отчуждаются: автор сохраняет право авторства и может требовать его признания — отчуждается только имущественное (исключительное) право.
- **Право на отзыв** (ст. 1269 ГК РФ) действует только до обнародования — после публикации требования автора об удалении не подлежат удовлетворению (кроме случаев, предусмотренных законом, напр. признание сценария нарушающим права третьих лиц).
- **Коммерческие организации**: п. 3.1 ст. 1234 ГК РФ запрещает безвозмездное отчуждение исключительного права между коммерческими организациями — не применяется, т.к. пользователи — физические лица.
## 4. Регистрация в Роскомнадзоре (ст. 22 152-ФЗ)
| № | Задача | Статус | Примечание |
|---|---|---|---|
| 4.1 | Оценить необходимость уведомления РКН о начале обработки ПДн | 🟡 | Интернет-сервис с автоматизированной обработкой обычно требует уведомления; исключения ч. 2 ст. 22 вряд ли применимы. Подать до запуска в прод |
| 4.2 | Подать уведомление (портал РКН, форма «оператор ПДн») | ⬜ | Внешняя процедура; оператор — физлицо |
| 4.3 | Получить и хранить номер уведомления / решение | ⬜ | Приложить к документации |
## 5. Локализация баз данных (ст. 18 ч. 5 152-ФЗ)
| № | Задача | Статус | Где |
|---|---|---|---|
| 5.1 | PostgreSQL в РФ | ✅ | `docker-compose-db.yml` / прод-конфигурация — проверить, что БД в РФ |
| 5.2 | S3 (RustFS) — файлы пользователей | 🟡 | Проверить, где физически находится `S3_HOST` в проде |
| 5.3 | SMTP-логи переписки | 🟡 | Проверить, не сохраняются ли письма/логи за пределами РФ |
## 6. Безопасность (ст. 19 152-ФЗ)
| № | Задача | Статус | Где |
|---|---|---|---|
| 6.1 | Хеширование паролей (bcrypt) | ✅ | `users_service/service.go` |
| 6.2 | JWT access (3 ч) + refresh (7 дн) с ротацией | ✅ | `processor_jwt` |
| 6.3 | HTTPS на проде | 🟡 | Через обратный прокси (не в репозитории) |
| 6.4 | Назначить ответственного за обработку ПДн (ст. 22.1) | ⬜ | Организационный шаг (для физлица-оператора — сам владелец) |
| 6.5 | Внутренний документ: сроки хранения логов, порядок реагирования на утечки (ст. 21 ч. 3.1 — уведомление РКН за 24 ч) | ⬜ | Организационный шаг |
| 6.6 | Gateway только за доверенным обратным прокси, перезаписывающим `X-Real-IP` (иначе клиент спуфит IP при акцепте; значения валидируются `netip.ParseAddr`) | 🟡 | Требование к прод-развёртыванию: nginx/Caddy перед `:8090`; настройка не в репозитории |
## 7. Права субъекта (ст. 14, 17, 20 152-ФЗ)
| № | Задача | Статус | Где |
|---|---|---|---|
| 7.1 | Эндпоинт «получить свои данные» (GDPR-стиль / ст. 14) | 🟡 | Частично есть `GET /api/users/me`; полная выгрузка ПДн (все таблицы) — добавить |
| 7.2 | Эндпоинт «изменить email/ник» | ⬜ | Сейчас нет; без него нельзя исполнить «уточнение ПДн» |
| 7.3 | Эндпоинт «удалить аккаунт» | ✅ | П. 3.1 |
| 7.4 | Процедура ответа на запросы (10 раб. дней, ст. 20) | ⬜ | Организационный шаг + адрес `[email]` из документов |
## 8. Прочее
| № | Задача | Статус | Примечание |
|---|---|---|---|
| 8.1 | Обновление swagger (`cmd/evening_detective_server/main.swagger.json`) | ✅ | Перегенерирован `make generate` |
| 8.2 | Прогон миграции на реальной БД (`goose up`) | ⬜ | Выполнить на staging перед продом |
| 8.3 | Интеграционный тест: signup без акцепта → ошибка; delete-account → данные удалены | ⬜ | `go test` (сейчас тестов нет) |
| 8.4 | Обновить README: новые эндпоинты, документы | ⬜ | — |
| 8.5 | GDPR (если появятся пользователи из ЕС) | ⬜ | Политика + DPA + механизмы прав субъекта — отдельный этап |
---
## Порядок действий перед запуском в прод
1. Заполнить плейсхолдеры в `docs/TERMS.md`, `docs/PRIVACY.md`, `docs/CONSENT.md` и утвердить у юриста.
2. Вставить в тексты документов реальные домены (`/terms`, `/privacy`, `/consent`); вставить чекбоксы акцепта, подтверждение отчуждения прав при публикации сценария и кнопку «Удалить аккаунт» во фронтенд.
3. Подать уведомление в Роскомнадзор (п. 4.2) до начала обработки.
4. Проверить локализацию: БД, S3, SMTP — в РФ.
5. Прогнать `goose up` на staging; добавить интеграционный тест (п. 8.3) — включая сценарий: публикация → удаление запрещено; удаление аккаунта → сценарий остаётся с `author: null`.
6. Решить задачу удаления файлов из S3 (п. 3.5) и «изменить email/ник» (п. 7.2) — по остаточному принципу после запуска.