# Workflow обращений субъектов ПДн (`pd_subject_requests`) — v8.2, Приложение Д

**Версия:** 8.2 от 04.05.2026 (правки после интервью с заказчиком).

## Что нового в v8.2 относительно v8.1

- ✅ **OPEN-Д-1 закрыт.** В таблицу `pd_subject_requests` добавляется новое поле `processing_restricted BOOLEAN NOT NULL DEFAULT FALSE` — флаг полной остановки обработки ПДн субъекта по требованию (ст.21 152-ФЗ, право на ограничение обработки). При установке этого флага все последующие операции с ПДн данного субъекта в системе должны проверять флаг и отказывать. Имплементация: `if (subject.processing_restricted) throw new ProcessingRestrictedException()` в сервисном слое + RLS-политика на чтение в БД-слое (опционально, для defense-in-depth).
- ✅ **OPEN-Д-5 закрыт.** Создаётся таблица **`incidents_log`** для журнала инцидентов (объединена с OPEN-И-1). DDL:

```sql
CREATE TABLE incidents_log (
    id                            BIGSERIAL PRIMARY KEY,
    type                          VARCHAR(50) NOT NULL, -- 'rls_leak', 'pd_breach', 'webhook_storm', 'gateway_outage', 'cron_silence', 'manual'
    severity                      VARCHAR(20) NOT NULL, -- 'low', 'medium', 'high', 'critical'
    started_at                    TIMESTAMPTZ NOT NULL,
    detected_at                   TIMESTAMPTZ NOT NULL,
    resolved_at                   TIMESTAMPTZ,
    summary                       TEXT NOT NULL,
    root_cause                    TEXT,
    postmortem_url                VARCHAR(500),
    related_pd_subject_request_ids BIGINT[],            -- если инцидент связан с ПДн-обращениями
    created_by_admin_id           BIGINT REFERENCES saas_admin_users(id),
    created_at                    TIMESTAMPTZ DEFAULT NOW(),
    CHECK (severity IN ('low','medium','high','critical')),
    CHECK (resolved_at IS NULL OR resolved_at >= started_at)
);
CREATE INDEX idx_incidents_started ON incidents_log(started_at DESC);
CREATE INDEX idx_incidents_severity_unresolved ON incidents_log(severity) WHERE resolved_at IS NULL;
```

Используется в Прил. Д (раздел 7 — связь с обращениями субъектов) и в Прил. И (раздел 5 — журнал runbook).

**Назначение документа:** закрыть пробел 🟠 №7 из конспекта анализа v8.0 — «детали 152-ФЗ для Роскомнадзора неполные, нет workflow для `pd_subject_requests`». Документ — **развёртка** раздела 22.9.5 главного файла v8.1: добавлены детальный жизненный цикл, шаблоны писем, временна́я раскадровка внутри 30-дневного дедлайна, процедура проверки личности заявителя и фаза «уведомление вторичных операторов» в трёхзвенной цепочке ПДн.

**Статус:** драфт для согласования с юристом. Юридические формулировки в шаблонах писем — рабочие, **подлежат финальной редактуре юристом** в рамках Ю-5. Архитектурные и процедурные решения, требующие подтверждения заказчиком, помечены `[?]`. Открытые вопросы — в разделе 9 в конце.

**Базовые ссылки на v8.1:**

- 1.5–1.6 — реселлерская модель и трёхзвенная цепочка ПДн (Ю-2)
- 22.9 — общий блок 152-ФЗ
- 22.9.1 — три типа согласий (`tenant_consents`)

- 22.9.2 — удаление по запросу самого тенанта (отличать от обращений физлиц-лидов!)
- 22.9.3 — журнал обработки `pd_processing_log`
- 22.9.5 — таблица `pd_subject_requests` (определение)
- 22.9.6 — impersonation (Ю-1)
- Приложение А (`schema.sql`) — DDL `pd_subject_requests`, индексы, CHECK-constraints
- Приложение Г (`Админка_SaaS_v8_1_драфт.md`) — экран «152-ФЗ / Compliance», роль `compliance`

**Юридический контекст:** ФЗ-152 «О персональных данных», глава 3 (права субъекта ПДн), ст. 14 (право на доступ), ст. 21 (обязанности оператора при удалении), ст. 22 (уведомление Роскомнадзора). Срок ответа на обращение — **не более 30 дней** с момента получения (ч. 4 ст. 20 ФЗ-152, плюс возможное продление до 30 рабочих дней при сложных запросах — мы по умолчанию работаем в 30 календарных).

---

## 0. Содержание

1. Зачем отдельный документ
2. Кто такие «субъекты ПДн» в нашей трёхзвенной модели
3. Жизненный цикл обращения (state machine)
4. Временна́я раскадровка внутри 30 дней
5. Процедура проверки личности заявителя
6. Уведомление вторичных операторов (особый шаг v8.1)
7. Шаблоны писем
8. UI / экраны в админке SaaS
9. Открытые вопросы

---

## 1. Зачем отдельный документ

В v8.1 раздел 22.9.5 определяет таблицу `pd_subject_requests` и обозначает требование к workflow, но прямо помечает: «Полный workflow с шаблонами писем, сроками внутри 30-дневного дедлайна, проверкой личности заявителя — отдельный артефакт (готовится при необходимости)». Этот документ закрывает указанный пробел.

Ключевые отличия от обработки запроса **самого тенанта** (раздел 22.9.2):

| Параметр | Тенант → свои данные (22.9.2) | Физлицо-лид → свои данные (этот документ) |
|---|---|---|
| Кто заявитель | Зарегистрированный пользователь | Внешнее физлицо, у нас аккаунта нет |
| Идентификация | Через активную сессию + email-подтверждение | **Не очевидна** — нужна отдельная процедура (раздел 5) |
| Канал обращения | UI `/account` | Email, форма на сайте, бумажное письмо |
| Объём данных | Только то, что собрано про самого тенанта | Лиды по разным тенантам, может быть в нескольких записях |
| Срок | 30 дней (мягкий, реально — несколько минут) | 30 дней (жёсткий по 152-ФЗ) |
| Уведомление третьих лиц | Не нужно (тенант — конечная точка) | **Обязательно** — crm.bp-gr.ru вверх и тенанты вниз (раздел 6) |
| Архитектурный объект | `tenants.deleted_at` + cron `tenants:purge-deleted` | `pd_subject_requests` + ручной workflow |
| Кто исполняет | Автоматический cron | Админ роли `compliance` (Приложение Г) |

То есть это **разные процессы**, и важно их не путать. Текущий документ — про второй случай.

---

## 2. Кто такие «субъекты ПДн» в нашей трёхзвенной модели

В реселлерской модели v8.1 (Ю-2) ПДн физлица проходит цепочку:

```
физлицо (источник) → crm.bp-gr.ru → мы (SaaS) → тенант (наш клиент)
                          оператор-1     оператор-2   оператор-3
```

Каждое звено — **самостоятельный оператор**. Это значит:

- Физлицо-лид имеет право обратиться **в любое из трёх** звеньев независимо.
- Если обращение пришло к нам — мы обязаны ответить в части **наших** данных, не уклоняясь под предлогом «обратитесь к первоисточнику».
- При удалении мы обязаны уведомить других операторов (раздел 6), но **не** обязаны добиваться, чтобы они тоже удалили — это уже их зона ответственности.

**Какие данные физлица у нас есть:**

| Таблица | Поля с ПДн физлица |
|---|---|
| `deals` | `phone`, `contact_name`, `comment` (может содержать ПДн) |
| `webhook_log` | `raw_payload` JSONB — копия webhook от crm.bp-gr.ru, в т.ч. ПДн |
| `pd_processing_log` | `subject_type='lead'`, `subject_id` — ссылка на `deals.id` |
| `supplier_lead_costs` | только `deal_id` — без ПДн напрямую (но связано через FK) |
| Файлы (S3) | экспорты с лидами, если тенант их выгружал |

**Какие действия мы можем выполнить по запросу:**

| Тип запроса (`request_type`) | Что делаем |
|---|---|
| `access` (право на доступ, ст. 14) | Выдаём выписку: где и когда мы получили данные, кому передавали (FK на тенанта), сроки хранения, основание обработки |
| `deletion` (право на забвение, ст. 21) | Анонимизируем `deals`, удаляем `webhook_log.raw_payload`, удаляем S3-экспорты, уведомляем вторичных операторов |
| `correction` (исправление, ст. 21) | Меняем `deals.contact_name` / `deals.phone` на корректные значения, фиксируем в `pd_processing_log` |
| `restriction` (ограничение обработки) | Помечаем сделку флагом `processing_restricted` `[?]` — `[OPEN-Д-1]` нужен такой флаг или достаточно удаления |

> **Замечание:** в v8.1 поля `processing_restricted` в `deals` нет. Если решим внедрять — это +миграция в v8.2. До того момента «ограничение обработки» в нашем случае схлопывается в «удаление».

---

## 3. Жизненный цикл обращения (state machine)

Поле `pd_subject_requests.status` принимает значения:

```
received → identity_verification → identity_verified → processing → completed
    ↓              ↓                       ↓                ↓
    └──────────────┴───────────────────────┴────────────────┴──→ rejected
```

**Состояния:**

| Статус | Что означает | Кто переводит | Дедлайн от `received_at` |
|---|---|---|---|
| `received` | Запрос принят, сохранён, ему присвоен `id`, заявителю отправлено письмо-подтверждение №1 | Автомат при создании записи | — |
| `identity_verification` | Заявителю отправлен запрос на подтверждение личности (письмо №2), ждём ответа | Админ `compliance` | до 3 дней |
| `identity_verified` | Личность подтверждена, начинаем поиск данных и подготовку ответа | Админ `compliance` | до 7 дней |
| `processing` | Идёт работа: формируется выписка / выполняется удаление / корректировка; параллельно идут уведомления вторичных операторов (для `deletion`) | Админ `compliance` | до 25 дней |
| `completed` | Запрос выполнен, заявителю отправлено финальное письмо №4, запись закрыта | Админ `compliance` | до 30 дней (жёстко) |
| `rejected` | Запрос отклонён (личность не подтверждена / данных у нас нет / запрос вне нашей компетенции). Заявителю отправлено письмо №5 с обоснованием | Админ `compliance` | до 30 дней (жёстко) |

**Невалидные переходы** (контролируются CHECK-constraint в `schema.sql` v8.2 `[OPEN-Д-2]`):

- `completed → *` — финальный статус, нельзя «переоткрыть» (если нужно — создаётся новый `pd_subject_requests`).
- `rejected → completed` — нельзя реабилитировать через смену статуса, только новой записью.
- `received → completed` напрямую — обязательно через `identity_verified` (защита от случая «админ забыл проверить личность»).

**Поля состояния**, которые заполняются автоматически при переходах:

| Переход | Что выставляется |
|---|---|
| `→ received` | `received_at = NOW()`, `deadline_at = NOW() + INTERVAL '30 days'` |
| `→ identity_verification` | `identity_request_sent_at = NOW()` `[?]` (нужно добавить поле в v8.2) |
| `→ identity_verified` | `identity_verified_at = NOW()`, `identity_verification_method` (раздел 5) |
| `→ processing` | `processing_started_at = NOW()`, `assigned_admin_id` (если ещё не задан — назначается на текущего) |
| `→ completed` | `completed_at = NOW()`, заполняется `result_summary` (свободный текст: что именно сделано) |
| `→ rejected` | `completed_at = NOW()`, `rejection_reason VARCHAR(50)` (см. enum ниже) |

**Enum `rejection_reason`** `[OPEN-Д-3]` (предлагаю фиксировать в v8.2):

- `identity_not_confirmed` — заявитель не подтвердил личность за 3 дня или подтверждение не прошло;
- `no_data_found` — мы искали, в наших таблицах данных по этому контакту нет;
- `out_of_scope` — запрос на действия, которые мы не можем выполнить (например, «удалите меня из всех CRM в России»);
- `duplicate` — это повторное обращение от того же лица по тому же поводу, ранее уже закрытое;
- `legal_hold` — на данные наложен legal hold (например, идёт судебное разбирательство, требующее их сохранения).

---

## 4. Временна́я раскадровка внутри 30 дней

30-дневный дедлайн ФЗ-152 — **жёсткий**. Раскадровка ниже — **внутренние SLA**, дающие запас на форс-мажоры.

### 4.1. Стандартный сценарий — `deletion`

| День | Действие | Ответственный | Артефакт |
|---|---|---|---|
| **0** (момент `received_at`) | Запрос автоматически создан в `pd_subject_requests`, статус `received`. Письмо №1 заявителю — подтверждение получения с `request_id` и сроком ответа | Автомат | Письмо №1 (раздел 7.1) |
| **0–1** | Админ `compliance` берёт запрос в работу, проверяет полноту данных заявителя (раздел 5.1), переводит в `identity_verification`, отправляет письмо №2 | Админ `compliance` | Письмо №2 (раздел 7.2) |
| **1–3** | Заявитель отвечает на письмо №2, подтверждает личность. Админ переводит в `identity_verified` | Админ `compliance` | Запись в `pd_processing_log` |
| **3–7** | Поиск всех записей по `subject_email` / `subject_phone` в `deals`, `webhook_log`, S3. Подготовка списка тенантов, которым надо уведомить (раздел 6) | Админ `compliance` | Внутренний отчёт по запросу `[?]` — `[OPEN-Д-4]` нужно ли поле `data_inventory_json` для аудита |
| **7** | Переход в `processing`. Параллельно стартуют (а) удаление наших данных, (б) уведомление crm.bp-gr.ru, (в) уведомление тенантов-получателей | Админ `compliance` | Письма №6, №7 (раздел 7) |
| **7–25** | Процесс удаления выполнен в нашей системе (анонимизация `deals`, удаление `webhook_log.raw_payload`, удаление S3-экспортов). Вторичные операторы получили уведомления, у них есть **18 дней** на свои действия — мы их не ждём, но фиксируем факт уведомления | Автомат + админ | Записи в `pd_processing_log` с `action='deleted'`, `purpose='subject_request_X'` |
| **25** | Финальная проверка: всё ли удалено в наших системах. Подготовка финального письма заявителю | Админ `compliance` | Письмо №4 (раздел 7.4) |
| **30** | **Жёсткий дедлайн.** Статус → `completed`, письмо №4 отправлено. Если до этого момента не успели — это нарушение 152-ФЗ, фиксируется как инцидент в `incidents_log` `[?]` — `[OPEN-Д-5]` есть такая таблица или нужна | Админ `compliance` | Алерт `compliance` в админке за 25, 28, 30 день |

### 4.2. Сценарий `access` (право на доступ)

То же расписание до дня 7, но вместо удаления — **формирование выписки**:

- Список всех `deals.id` с этим телефоном/email;
- Для каждого: когда получили (через какой webhook), какому тенанту передали, текущий статус;
- Список действий из `pd_processing_log` (когда смотрели, экспортировали, передавали);
- Текущая правовая основа обработки (договор с crm.bp-gr.ru + согласие физлица, собранное на стороне crm.bp-gr.ru).

Выписка — PDF, отправляется на проверенный email заявителя. **Не отправляется по неподтверждённому каналу** (защита от подмены).

### 4.3. Сценарий `correction`

Аналогично `access`: ищем записи, проверяем что заявитель действительно тот, чьи данные исправляем (это критично — здесь высокий риск злоупотребления), вносим правки, фиксируем в `pd_processing_log` с `action='updated'`, `purpose='subject_request_correction_<id>'`.

### 4.4. Алерты

В админке SaaS (роль `compliance`, см. Приложение Г §4) выводится лента:

- **Зелёный:** `received_at < NOW() - 7 days`, статус ещё `received` или `identity_verification` — ничего страшного, в графике.
- **Жёлтый:** `deadline_at - NOW() < 5 days`, статус не `completed`/`rejected` — пора заканчивать.
- **Красный:** `deadline_at < NOW()`, статус не `completed`/`rejected` — **нарушение 152-ФЗ**, требуется немедленный разбор и фиксация инцидента.

Cron `compliance:check-pd-deadlines` (каждые 6 часов) расставляет приоритеты в очереди и шлёт email-уведомления админам `compliance` и `super_admin`.

---

## 5. Процедура проверки личности заявителя

**Проблема:** в отличие от тенанта (у которого есть аккаунт), физлицо-лид нам неизвестно. Нужно убедиться, что (а) заявитель действительно тот человек, чьи данные он просит, и (б) данные действительно у нас есть. Без этого — **отказ** (`rejection_reason='identity_not_confirmed'`).

**Принцип:** заявитель должен подтвердить контроль над тем каналом связи (email/телефон), который у нас числится в `deals` как принадлежащий ему.

### 5.1. Что должно прийти в первичном обращении

Заявитель пишет нам (email на `privacy@<домен>`, через форму на сайте, или бумажно). Чтобы запрос вообще можно было обработать, нужны:

| Поле | Обязательность | Зачем |
|---|---|---|
| ФИО | Обязательно | Сравнение с `deals.contact_name` |
| Контакт для связи (email или телефон) | Обязательно | Через него ведём переписку |
| **Тот контакт, который мог использоваться при оставлении заявки** (телефон, email) | Обязательно | По этому полю ищем в `deals.phone` / связанных полях |
| Тип запроса | Обязательно | `access` / `deletion` / `correction` / `restriction` |
| Конкретика для `correction` | При `request_type='correction'` | Что именно неверно и что записать вместо |
| Период (примерно когда оставлял заявку) | Желательно | Сужает поиск |
| Тематика заявки (на что подавал) | Желательно | Помогает идентифицировать тенанта-получателя |

Если в первичном обращении не хватает данных — отправляем письмо №3 (раздел 7.3) с просьбой дополнить.

### 5.2. Способы подтверждения личности

Один из (в порядке надёжности):

**Способ А — подтверждение через канал из `deals`** *(базовый случай).*

1. Находим запись по `deals.phone` или `deals.contact_name`.
2. На номер телефона из `deals.phone` отправляем SMS с кодом `[?]` — `[OPEN-Д-6]` нужен SMS-провайдер для этого, у нас в v8.1 SMS не использовался; альтернатива — звонок робота.
3. Заявитель называет код.
4. Если совпало — `identity_verification_method = 'sms_to_known_phone'`, переход в `identity_verified`.

Альтернатива на email: если в `deals` есть email-поле `[?]` — `[OPEN-Д-7]` в v8.1 у нас в `deals` email физлица не записывается (только `phone` и `contact_name`); если решим расширять — это поле в v8.2.

**Способ Б — нотариальное заявление.** Если телефон/email сменился, заявитель присылает скан нотариально заверенного заявления о том, что номер/email N был его, и он просит выполнить действия по этим данным. `identity_verification_method = 'notarized_statement'`. Хранится в S3 с TTL, ссылка в `identity_evidence_url` `[?]` — `[OPEN-Д-8]` нужно поле.

**Способ В — личная явка.** В офис заказчика с паспортом — для крупных случаев или когда юрист настаивает. `identity_verification_method = 'in_person_with_passport'`. Скан паспорта **не сохраняем** — фиксируем только серию-номер в `identity_evidence_text` (free-form), и факт явки.

**Способ Г — Госуслуги** `[?]` — `[OPEN-Д-9]` не на MVP, но как опция в v8.x: подтверждение через ЕСИА.

### 5.3. Что делаем при невозможности подтвердить

Через 3 дня после отправки письма №2 — повторное напоминание (письмо №2bis). Через 7 дней без ответа — переход в `rejected` с `rejection_reason='identity_not_confirmed'`, отправка письма №5 с указанием права повторного обращения с подтверждённой личностью.

**Важно:** факт обращения и его отклонение **сохраняем** (анонимизировав сам контакт, если требуется по запросу самого заявителя). Это нужно для случая когда тот же человек обратится снова — мы должны видеть историю.

### 5.4. Антифрод

Чтобы конкурент или злоумышленник не смог через `correction` исказить данные лидов в нашей системе — **жёстко**:

- Любой `correction` требует Способ Б, В или Г (не А).
- Любой `deletion` массового масштаба (более 5 записей за раз по одному заявителю) — требует подтверждения через юриста заказчика.
- Запрос с IP/email из чёрного списка (после ранее подтверждённого фрода) автоматически отклоняется с `rejection_reason='out_of_scope'` и алертом `compliance` + `security` (новая роль? `[OPEN-Д-10]`).

---

## 6. Уведомление вторичных операторов (особый шаг v8.1)

**Контекст** (Ю-2): мы — звено №2 в цепочке `физлицо → crm.bp-gr.ru → мы → тенант`. По 152-ФЗ ст. 21 ч. 4: «оператор обязан в течение 7 рабочих дней с даты обнаружения уведомить субъекта об устранении нарушений или удалении персональных данных». Если мы передавали данные дальше — мы обязаны уведомить тех, кому передавали.

**Это касается только `request_type='deletion'` и `request_type='correction'`.** Для `access` уведомлять никого не надо.

### 6.1. Уведомление crm.bp-gr.ru (вверх по цепочке)

**Зачем:** crm.bp-gr.ru — первоисточник. Если физлицо хочет полного забвения, оно должно обратиться и туда тоже. Но мы по 152-ФЗ обязаны уведомить их о факте обращения к нам, чтобы они синхронизировали свои данные.

**Канал:** официальное письмо на адрес поддержки crm.bp-gr.ru (закреплён в договоре, см. Б-1 от заказчика). Дублируется email-ом ответственному лицу.

**Содержание** (письмо №6, раздел 7.6): идентификатор лида в их системе (если у нас есть `webhook_log.external_id`), дата получения, факт удаления у нас, рекомендация рассмотреть удаление у себя, ссылка на наш `request_id`.

**Не передаём** в этом письме сами ПДн физлица — только идентификаторы и сам факт. Письмо хранится в `pd_processing_log` со ссылкой на `request_id`.

**Срок:** в течение 7 календарных дней после перехода запроса в `processing` (то есть около дня 14 от `received_at` в худшем случае). `[?]` — `[OPEN-Д-11]` уточнить с юристом, считаем «рабочие» или «календарные».

### 6.2. Уведомление тенантов-получателей (вниз по цепочке)

**Зачем:** мы передали лида тенанту через интерфейс/webhook/email (раздел 1.5 v8.1). У тенанта эти данные сейчас в его CRM-системе. Тенант — самостоятельный оператор, отвечает за свои действия, но мы как передающее звено обязаны уведомить.

**Как находим тенантов:** все `deals` с подходящим `phone`/`contact_name` имеют `tenant_id`. Список тенантов = `SELECT DISTINCT tenant_id FROM deals WHERE phone = $1 OR contact_name = $2`.

**Канал:** email на `tenants.contact_email`, дублируется в личном кабинете тенанта на странице `/notifications` (новый раздел? `[OPEN-Д-12]` — есть ли такая страница в v8.1).

**Содержание** (письмо №7, раздел 7.7): идентификатор сделки в нашей системе (`deals.id`), дата получения, факт обращения субъекта, требование тенанта удалить эти данные у себя в течение **разумного срока** (не более 30 дней с момента получения уведомления — это **их** дедлайн по 152-ФЗ как оператора), напоминание о пункте оферты Ю-8 (зеркальные гарантии).

**Не передаём** в этом письме повторно сами ПДн — у тенанта они уже есть, упоминаем только `deals.id`. Это снижает повторную циркуляцию ПДн.

**Срок:** в течение 7 календарных дней после перехода запроса в `processing`. Рассылка автоматическая через очередь `pd-notifications` `[?]` — `[OPEN-Д-13]` нужна отдельная очередь или хватит общего mailer.

### 6.3. Что делать, если тенант не ответил / не удалил

**Это не наша проблема юридически** — мы выполнили обязанность уведомить. Дальше тенант — самостоятельный оператор, отвечает перед Роскомнадзором сам.

Но **репутационно** это наша проблема, и есть риск, что Роскомнадзор посмотрит цепочку и предъявит претензии всем. Поэтому:

- В оферте (Ю-5, Ю-8) фиксируется обязанность тенанта реагировать на такие уведомления в течение 30 дней под угрозой блокировки аккаунта.
- В админке `compliance` есть отчёт «Тенанты с открытыми pd-уведомлениями старше 30 дней» — основание для разговора с тенантом.
- Если тенант системно игнорирует — `super_admin` блокирует тенанта (`tenants.status='suspended'`) с обоснованием в `saas_admin_audit_log`.

### 6.4. Логирование уведомлений

Каждое отправленное уведомление вторичным операторам пишется в `pd_processing_log`:

```
INSERT INTO pd_processing_log (
    tenant_id,           -- кому уведомили (или NULL если crm.bp-gr.ru)
    subject_type,        -- 'lead'
    subject_id,          -- deals.id
    action,              -- 'notified_secondary_operator'
    purpose,             -- 'subject_request_<id>_deletion'
    actor_admin_user_id, -- кто запустил
    ...
)
```

Это даёт возможность на любой момент собрать отчёт «кому и когда мы сказали об удалении лида X». `[?]` — `[OPEN-Д-14]` нужно ли отдельное поле `notification_channel` (email / api / postal).

---

## 7. Шаблоны писем

> **Юридический статус:** все шаблоны — рабочие черновики, требующие финальной редактуры юристом в рамках Ю-5. Переменные в `{{двойных фигурных скобках}}` — подставляются автоматически. Формулировки про правовые основания (152-ФЗ ст. X) проверены по структуре закона, но точные ссылки и обороты — **на юриста**.

**Общие переменные шаблонов:**

| Переменная | Источник |
|---|---|
| `{{operator_name}}` | `legal_entities` (наше юрлицо) — полное наименование |
| `{{operator_short_name}}` | `legal_entities` — краткое наименование |
| `{{operator_inn}}` | `legal_entities.inn` |
| `{{operator_address}}` | `legal_entities` — юридический адрес |
| `{{privacy_email}}` | `system_settings.privacy_contact_email` `[?]` — `[OPEN-Д-15]` нужен такой ключ |
| `{{request_id}}` | `pd_subject_requests.id` |
| `{{received_at_human}}` | `pd_subject_requests.received_at` в формате «дд.мм.гггг» |
| `{{deadline_at_human}}` | `pd_subject_requests.deadline_at` в формате «дд.мм.гггг» |
| `{{request_type_human}}` | Локализованное название (`access` → «доступ к данным», `deletion` → «удаление данных», и т.д.) |
| `{{subject_email_or_phone}}` | `subject_email` или маскированный `subject_phone` |
| `{{admin_signature}}` | Имя админа `compliance`, обработавшего запрос |

### 7.1. Письмо №1 — подтверждение получения

**Триггер:** автоматически при `INSERT INTO pd_subject_requests`. Канал: email на `subject_email`, если есть; иначе SMS на `subject_phone` `[?]` — `[OPEN-Д-6]`.

**Тема:** `Подтверждение получения вашего обращения №{{request_id}}`

**Тело:**

> Здравствуйте,
>
> Мы получили ваше обращение от {{received_at_human}} с запросом «{{request_type_human}}». Обращению присвоен номер **№{{request_id}}** — пожалуйста, указывайте его в дальнейшей переписке.
>
> В соответствии с Федеральным законом от 27.07.2006 №152-ФЗ «О персональных данных» мы обязаны рассмотреть ваше обращение и предоставить ответ в срок до **{{deadline_at_human}}** (30 дней с момента получения).
>
> Для обработки запроса нам потребуется подтвердить вашу личность. В ближайшее время вам поступит отдельное письмо с инструкциями.
>
> Если вы не направляли нам обращение и получили это письмо ошибочно — пожалуйста, сообщите нам по адресу {{privacy_email}}.
>
> С уважением,
> {{operator_short_name}}
> {{privacy_email}}

### 7.2. Письмо №2 — запрос подтверждения личности

**Триггер:** ручной, админ `compliance` после первичной проверки данных в обращении (раздел 5.1). Переход `received → identity_verification`.

**Тема:** `Обращение №{{request_id}} — подтверждение личности`

**Тело:**

> Здравствуйте,
>
> По вашему обращению №{{request_id}} от {{received_at_human}} нам необходимо подтвердить вашу личность, прежде чем мы сможем выполнить запрошенные действия с персональными данными. Это требование Федерального закона №152-ФЗ — мы должны быть уверены, что обращение поступило именно от того лица, чьи данные у нас обрабатываются.
>
> Возможные способы подтверждения:
>
> 1. **SMS-код на номер**, который вы указывали при оставлении заявки. Если этот номер у вас под контролем — ответьте на это письмо словом «SMS», и мы пришлём код на этот номер.  *(Способ подходит, если номер не сменился.)*
> 2. **Нотариально заверенное заявление** о том, что номер/email N принадлежал вам и вы просите выполнить действия по этим данным. Скан можно прислать в ответ на это письмо. *(Способ подходит, если номер сменился.)*
> 3. **Личная явка** в офис по адресу {{operator_address}} с паспортом. Просим заранее согласовать время.
>
> Просим выбрать удобный способ и ответить **в течение 7 дней** от даты этого письма. По истечении 7 дней без ответа обращение будет отклонено, и вам потребуется направить новое.
>
> С уважением,
> {{admin_signature}}
> {{operator_short_name}}
> {{privacy_email}}

### 7.3. Письмо №3 — запрос дополнительной информации

**Триггер:** ручной, админ `compliance`, если в первичном обращении не хватает данных для поиска (нет ни email, ни телефона из `deals`).

**Тема:** `Обращение №{{request_id}} — нужна дополнительная информация`

**Тело:**

> Здравствуйте,
>
> Мы получили ваше обращение №{{request_id}} от {{received_at_human}}, но для его обработки нам не хватает данных, чтобы найти соответствующие записи в наших системах.
>
> Просим уточнить:
>
> - {{missing_fields}}  *(подставляется списком: «телефон, по которому подавалась заявка», «примерная дата обращения», и т.п.)*
>
> Без этих данных мы не сможем гарантировать корректность исполнения вашего запроса. Просим ответить на это письмо в течение 14 дней.
>
> С уважением,
> {{admin_signature}}
> {{operator_short_name}}

### 7.4. Письмо №4 — выполнено

**Триггер:** ручной, админ `compliance`, переход `processing → completed`.

**Тема:** `Обращение №{{request_id}} — выполнено`

**Тело — для `deletion`:**

> Здравствуйте,
>
> По вашему обращению №{{request_id}} от {{received_at_human}} мы выполнили следующие действия:
>
> - Найденные в наших системах записи о ваших персональных данных **удалены/обезличены** {{processing_completed_at_human}}.
> - В соответствии с требованиями 152-ФЗ мы уведомили {{count_secondary}} вторичных операторов о вашем обращении: первоначальный источник данных (crm.bp-gr.ru) и {{count_tenants}} получателей. Каждый из них является самостоятельным оператором и обязан рассмотреть обращение в свои сроки.
> - Отправлять им повторное обращение не обязательно: уведомление с нашей стороны они получили. Если хотите убедиться, что они выполнили удаление у себя, вы вправе обратиться к ним напрямую.
>
> Подробный список вторичных операторов и контакты для прямых обращений — в приложении к этому письму.
>
> С уважением,
> {{admin_signature}}
> {{operator_short_name}}

**Тело — для `access`:**

> Здравствуйте,
>
> По вашему обращению №{{request_id}} от {{received_at_human}} мы подготовили выписку о персональных данных, обрабатываемых нами в отношении вас, во вложении к этому письму (PDF, {{filesize}}).
>
> Выписка содержит:
>
> - перечень собранных нами данных,
> - дату и источник получения,
> - правовое основание обработки,
> - перечень получателей (тенантов), которым данные передавались,
> - историю действий с данными.
>
> С уважением,
> {{admin_signature}}
> {{operator_short_name}}

**Тело — для `correction`:** аналогично, с указанием конкретных полей до/после.

### 7.5. Письмо №5 — отклонено

**Триггер:** ручной, переход `* → rejected`.

**Тема:** `Обращение №{{request_id}} — отказ в обработке`

**Тело:**

> Здравствуйте,
>
> По вашему обращению №{{request_id}} от {{received_at_human}} мы вынуждены отказать в обработке по следующей причине:
>
> {{rejection_reason_human}}
>
> *(подставляется развёрнутая формулировка, например: «Личность заявителя не была подтверждена в установленный срок», «По указанным контактным данным записей в наших системах не обнаружено», «Запрашиваемые действия выходят за рамки наших возможностей как оператора», «На данные наложено ограничение в связи с {{legal_hold_reason}}».)*
>
> Если вы считаете отказ необоснованным, вы вправе:
>
> - направить новое обращение, устранив указанные препятствия;
> - подать жалобу в Роскомнадзор по адресу: rkn.gov.ru.
>
> С уважением,
> {{admin_signature}}
> {{operator_short_name}}

### 7.6. Письмо №6 — уведомление crm.bp-gr.ru

**Триггер:** автоматически при переходе запроса `deletion`/`correction` в `processing`. Канал: email на адрес из договора + дублирующий канал, согласованный в Б-1.

**Тема:** `Уведомление об обращении субъекта ПДн — сделка {{external_lead_id}}`

**Тело:**

> Уважаемые коллеги,
>
> В рамках исполнения требований Федерального закона №152-ФЗ настоящим уведомляем, что от субъекта персональных данных, чьи данные были переданы нам через ваш сервис, получено обращение с запросом «{{request_type_human}}».
>
> Идентификатор сделки в нашей системе: {{deals_id}}
> Идентификатор лида в вашей системе (если есть в payload webhook): {{external_lead_id}}
> Дата получения данных от вас: {{webhook_received_at}}
> Наш внутренний номер обращения: {{request_id}}
>
> Со своей стороны мы выполнили запрошенные действия в наших системах. В соответствии со ст. 21 ч. 4 ФЗ-152 рекомендуем вам рассмотреть аналогичные действия как оператору-первоисточнику данных.
>
> Сами персональные данные субъекта в это уведомление не включены — в случае, если они потребуются для идентификации записи на вашей стороне, просим запрашивать их через защищённый канал, согласованный нашим договором.
>
> С уважением,
> {{operator_short_name}}, оператор персональных данных
> {{operator_inn}}, {{operator_address}}
> {{privacy_email}}

### 7.7. Письмо №7 — уведомление тенанта

**Триггер:** автоматически, по списку `tenant_id` найденных в `deals`. Канал: email на `tenants.contact_email` + уведомление в личном кабинете.

**Тема:** `Получено обращение субъекта ПДн по сделке №{{deals_id}}`

**Тело:**

> Здравствуйте,
>
> В рамках исполнения требований Федерального закона №152-ФЗ настоящим уведомляем, что мы получили обращение от субъекта персональных данных по лиду, который был передан вам через нашу платформу.
>
> Сделка в вашем интерфейсе: №{{deals_id}}
> Дата передачи: {{deal_transferred_at}}
> Тип обращения субъекта: {{request_type_human}}
> Наш внутренний номер обращения: {{request_id}}
>
> **Ваши действия:** в соответствии с пунктом {{oferta_clause}} вашего договора с нами и требованиями ФЗ-152 как самостоятельного оператора, вы обязаны:
>
> - рассмотреть обращение и выполнить аналогичные действия с указанной сделкой в **вашей** CRM-системе и любых производных копиях/выгрузках;
> - сделать это в срок не более **30 дней с даты получения этого уведомления**;
> - при необходимости — связаться с субъектом самостоятельно по контактам, имеющимся у вас.
>
> Сами персональные данные субъекта в это уведомление не включены — у вас они уже есть в записи сделки.
>
> Подтвердить выполнение вы можете в личном кабинете на странице «{{notifications_url}}» отметкой «Обработано». Невыполнение в срок может стать основанием для блокировки аккаунта в соответствии с офертой и для самостоятельной ответственности перед Роскомнадзором.
>
> С уважением,
> {{operator_short_name}}, оператор персональных данных
> {{privacy_email}}

---

## 8. UI / экраны в админке SaaS

> Этот раздел дополняет Приложение Г (`Админка_SaaS_v8_1_драфт.md`), §4 — экраны раздела «152-ФЗ / Compliance».

### 8.1. Экран «Обращения субъектов ПДн» (список)

**Доступ:** роли `compliance`, `super_admin`. Read-only для `support`. Полностью недоступен для `finance`.

**Колонки таблицы:**

| Колонка | Источник |
|---|---|
| ID | `pd_subject_requests.id` |
| Получено | `received_at` |
| Тип | `request_type` (с иконкой) |
| Заявитель | `subject_email` или маскированный `subject_phone` |
| Статус | `status` (цветной чип) |
| Дедлайн | `deadline_at` (с цветовой индикацией: зелёный/жёлтый/красный — раздел 4.4) |
| Ответственный | `assigned_admin_id` (имя из `saas_admin_users`) |
| Тенанты-получатели | количество найденных тенантов (для `deletion`) |

**Фильтры:** статус, тип, период `received_at`, ответственный, «приближаются к дедлайну».

**Сортировка по умолчанию:** `deadline_at ASC` — приоритет тем, что горят.

**Действия (bulk):** массовая переуступка ответственного, экспорт списка в CSV.

### 8.2. Экран «Обращение №X» (карточка)

**Блоки:**

1. **Шапка:** ID, статус, дедлайн с обратным отсчётом, кнопки переходов между статусами (только разрешённые из текущего, см. раздел 3).
2. **Заявитель:** все поля из `pd_subject_requests` + история переходов статусов с временем и автором.
3. **Найденные данные:** таблица `deals.id` / `tenant_id` / дата получения / источник; для `webhook_log` и S3 — список с количеством записей. Кнопка «Поиск повторно» (если данные могли появиться после первичного поиска).
4. **Связанные тенанты:** список тенантов с количеством их сделок, статусом уведомления (отправлено / не отправлено / подтверждено).
5. **Уведомления вторичных операторов:** статус по crm.bp-gr.ru и каждому тенанту: отправлено когда, через какой канал, есть ли подтверждение.
6. **Журнал переписки с заявителем:** все отправленные шаблоны (№1-5) с датами, статус доставки. Кнопка «Отправить новое письмо» с выбором шаблона.
7. **Действия:** «Перевести в `processing`» (запускает рассылку №6, №7), «Завершить» (`processing → completed`), «Отклонить» (с выбором `rejection_reason`).
8. **Доказательства подтверждения личности:** загруженные сканы (нотариальное заявление), запись о SMS / личной явке. Каждый файл — со ссылкой на S3 и TTL.

### 8.3. Виджет на главной админки (для роли `compliance`)

- Счётчик: открытых запросов всего / горящих (жёлтых) / просроченных (красных).
- Лента «Последние действия» с записями из `pd_processing_log` по `purpose LIKE 'subject_request_%'`.

### 8.4. Отчёт «Обращения за период»

Для отчётности перед Роскомнадзором (если запросят). Таблица: за выбранный период — сколько обращений получено, по каким типам, какой % обработан в срок, причины отказов. Экспорт в PDF / CSV. Доступ: `super_admin`.

---

## 9. Открытые вопросы

| ID | Вопрос | Кому | Приоритет | Влияние если не решить |
|---|---|---|---|---|
| **OPEN-Д-1** | Нужно ли поле `processing_restricted` в `deals` для `request_type='restriction'`, или схлопывать в `deletion`? | CTO + юрист | P2 | Без флага `restriction` фактически = `deletion`; для MVP приемлемо |
| **OPEN-Д-2** | CHECK-constraint на разрешённые переходы статусов `pd_subject_requests` — добавить в schema v8.2? | CTO | P1 | Без CHECK можно обойти процесс программной ошибкой |
| **OPEN-Д-3** | Зафиксировать enum `rejection_reason` (5 значений предложено в разделе 3) | CTO + юрист | P1 | Без enum — свободный текст, плохо для отчётности |
| **OPEN-Д-4** | Нужно ли поле `data_inventory_json` для аудита того, что было найдено? | CTO + compliance | P2 | Без поля аудит делается через `pd_processing_log` — менее удобно, но возможно |
| **OPEN-Д-5** | Есть ли таблица `incidents_log` для фиксации нарушений сроков 152-ФЗ? | CTO | P1 | Нужна для аудита Роскомнадзора |
| **OPEN-Д-6** | SMS-провайдер для подтверждения личности: какой выбираем? Бюджет? | DevOps + бизнес | P1 | Без SMS остаются только нотариус и личная явка — высокий порог |
| **OPEN-Д-7** | Добавлять ли `email` физлица в `deals` как опциональное поле? | CTO + юрист | P2 | Сейчас единственный «канал к физлицу» — телефон, для подтверждения через email недостаточно |
| **OPEN-Д-8** | Поле `identity_evidence_url` (S3-ссылка на сканы) и `identity_verification_method` enum в `pd_subject_requests` | CTO | P1 | Без этих полей доказательства нигде не фиксируются |
| **OPEN-Д-9** | Подключение к Госуслугам (ЕСИА) для подтверждения личности — в какой версии? | бизнес | P3 | Желательно, но не критично; даёт сильное упрощение UX |
| **OPEN-Д-10** | Заводить ли отдельную роль `security` помимо `compliance`? | CTO + бизнес | P2 | Сейчас `compliance` совмещает обе функции, на старте приемлемо |
| **OPEN-Д-11** | «Календарные» или «рабочие» дни в сроке уведомления вторичных операторов (7 дней по ст. 21 ч. 4)? | юрист | P1 | Влияет на SLA; берём календарные как более жёсткие до уточнения |
| **OPEN-Д-12** | Есть ли в личном кабинете тенанта страница `/notifications` для уведомлений о pd-запросах? | CTO + дизайн | P1 | Без страницы — только email-канал, может быть пропущен |
| **OPEN-Д-13** | Отдельная очередь `pd-notifications` или общий mailer? | CTO | P2 | Для MVP общий mailer ок; отдельная очередь даст приоритизацию |
| **OPEN-Д-14** | Поле `notification_channel` в `pd_processing_log`? | CTO | P2 | Для аудита полезно знать канал (email/api/postal); без поля — выводится из контекста |
| **OPEN-Д-15** | Ключ `system_settings.privacy_contact_email` | CTO | P1 | Нужен для подстановки `{{privacy_email}}` в шаблоны; +1 строка миграции |
| **OPEN-Д-16** | Где публикуется адрес `privacy_email` для физлиц? Отдельная страница на сайте? Раздел в Политике конфиденциальности? | бизнес + юрист | P1 | Без публикации физлицо не знает, как обратиться — критично для соблюдения 152-ФЗ |
| **OPEN-Д-17** | Бумажные обращения: кто и как их регистрирует в `pd_subject_requests`? | бизнес | P2 | Если адрес заказчика принимает бумажную почту — нужен процесс приёмки и оцифровки |
| **OPEN-Д-18** | Срок хранения записей `pd_subject_requests` после `completed`/`rejected`. По 152-ФЗ — 5 лет? Дольше? | юрист | P1 | Нужно для cron'а ретеншена |
| **OPEN-Д-19** | Уведомление тенанта о повторном обращении того же физлица — нужно ли? | юрист | P3 | Если тот же субъект обращается снова, тенант мог уже удалить; зависит от практики |
| **OPEN-Д-20** | Стоимость нотариального заявления — компенсируется заявителю или нет? | юрист + бизнес | P3 | Юридически не обязаны, но влияет на репутацию |

---

## 10. Что добавить в schema v8.2

Сводный список миграций к таблице `pd_subject_requests`, чтобы реализовать workflow в полном объёме:

```sql
-- v8.2 миграция: расширение pd_subject_requests до полного workflow

ALTER TABLE pd_subject_requests
    ADD COLUMN identity_request_sent_at      TIMESTAMPTZ,
    ADD COLUMN identity_verified_at          TIMESTAMPTZ,
    ADD COLUMN identity_verification_method  VARCHAR(50),  -- enum: sms_to_known_phone | notarized_statement | in_person_with_passport | esia
    ADD COLUMN identity_evidence_url         TEXT,         -- S3 ссылка на скан (для notarized)
    ADD COLUMN identity_evidence_text        TEXT,         -- free-form (для in_person)
    ADD COLUMN processing_started_at         TIMESTAMPTZ,
    ADD COLUMN result_summary                TEXT,         -- что именно сделали (для completed)
    ADD COLUMN rejection_reason              VARCHAR(50),  -- enum: см. раздел 3
    ADD COLUMN data_inventory_json           JSONB,        -- что нашли (опционально, [OPEN-Д-4])
    ADD CONSTRAINT chk_pd_request_status_transitions CHECK (
        -- черновик ограничения, точная форма — на момент миграции
        (status IN ('received','identity_verification','identity_verified','processing','completed','rejected'))
    ),
    ADD CONSTRAINT chk_pd_request_completion CHECK (
        (status NOT IN ('completed','rejected')) OR (completed_at IS NOT NULL)
    ),
    ADD CONSTRAINT chk_pd_request_rejection CHECK (
        (status <> 'rejected') OR (rejection_reason IS NOT NULL)
    );

CREATE INDEX idx_pd_requests_deadline ON pd_subject_requests(deadline_at) WHERE status NOT IN ('completed','rejected');
CREATE INDEX idx_pd_requests_assigned ON pd_subject_requests(assigned_admin_id) WHERE status NOT IN ('completed','rejected');
CREATE INDEX idx_pd_requests_subject_phone ON pd_subject_requests(subject_phone);
CREATE INDEX idx_pd_requests_subject_email ON pd_subject_requests(subject_email);

-- system_settings — новый ключ
INSERT INTO system_settings (key, value_text, description) VALUES
    ('privacy_contact_email', '<заполняется заказчиком>', 'Email для приёма обращений субъектов ПДн (152-ФЗ ст. 14)');

-- Возможно, в зависимости от OPEN-Д-5
-- CREATE TABLE incidents_log (...) — для фиксации нарушений сроков
```

> Точная форма миграции — после ответов на P1-вопросы из раздела 9 (особенно OPEN-Д-3, Д-5, Д-15).

---

## 11. Что обновить в смежных документах

При выпуске v8.2:

| Документ | Что меняется |
|---|---|
| `CRM_bp-gr_Инструкция_v8_1.md` 22.9.5 | Заменить ремарку «отдельный артефакт (готовится при необходимости)» на ссылку на это Приложение Д |
| `CRM_bp-gr_Инструкция_v8_1.md` раздел 28 | Добавить шифр Д = `Workflow_pd_subject_requests_v8_1.md` |
| `schema.sql` | Применить миграцию из раздела 10 (после ответов на P1 OPEN-Д) |
| `Админка_SaaS_v8_1_драфт.md` §4 | Раскрыть §4 «152-ФЗ / Compliance» по образцу раздела 8 этого документа |
| `Открытые_вопросы_v8_1.md` | Добавить блок «Адресат: compliance / юрист — OPEN-Д-1..20» |
| `CRM_bp-gr_Инструкция_v8_1.md` 27.2 | Добавить пункт «privacy_contact_email» в чек-лист от заказчика, и пункт «SMS-провайдер» (OPEN-Д-6) |
| Шаблон оферты (Ю-5) | Включить пункт о соблюдении тенантом 30-дневного дедлайна по pd-уведомлениям (раздел 6.3, 7.7) — `oferta_clause` для подстановки в письмо №7 |

---

*Драфт v0.1 от 04.05.2026. Готовится в рамках сессии 03–04.05.2026 как Приложение Д к v8.1.*
