Files
evening_detective_server/docs/COMPLIANCE.md
T
2026-08-19 23:31:37 +07:00

124 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ЧЕК-ЛИСТ 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`, пути `/api/terms`, `/api/privacy`, `/api/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. Вставить в тексты документов реальные домены (`/api/terms`, `/api/privacy`, `/api/consent`); вставить чекбоксы акцепта, подтверждение отчуждения прав при публикации сценария и кнопку «Удалить аккаунт» во фронтенд.
3. Подать уведомление в Роскомнадзор (п. 4.2) до начала обработки.
4. Проверить локализацию: БД, S3, SMTP — в РФ.
5. Прогнать `goose up` на staging; добавить интеграционный тест (п. 8.3) — включая сценарий: публикация → удаление запрещено; удаление аккаунта → сценарий остаётся с `author: null`.
6. Решить задачу удаления файлов из S3 (п. 3.5) и «изменить email/ник» (п. 7.2) — по остаточному принципу после запуска.