docs: хвост Р118 — контрольный лист аудита 152-ФЗ помечен, приписка в отчёт о бое

Р118. Лист велел проверить защиту, которой нет. Мест там два пункта, а не один:
кроме самого флага лжёт и пункт про индекс. Имён несуществующих охранников два —
ProcessingRestrictedException и ProcessingRestrictionGuard, оба проверены
и отсутствуют. Пометок три: одна отдельным пунктом ПЕРЕД лживыми, чтобы её
не пропустил идущий по коробочкам сверху вниз, и две внутри самих пунктов.

Три чужих давних слова в том же листе разрешены указанием для сторожа внутри
самого файла, а не правкой общего словаря. Прибор проверен на подставной ошибке:
разрешённые слова замолчали, бессмыслица поймана.

Р119. Отчёт о готовности к бою получил приписку про тот же флаг. Слова в словарь
дописаны прежним коммитом.

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

Ноль удалённых строк по каждому файлу.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-08-06 19:06:05 +03:00
parent 1ed7a0128b
commit fdbff6e2d4
3 changed files with 166 additions and 0 deletions
@@ -1,5 +1,10 @@
# ПДн 152-ФЗ — чек-лист аудита Лидерры
<!-- Три слова ниже жили в этом файле задолго до правки Р118 и сторожу правописания
неизвестны. Разрешены здесь, а не в общем словаре: слова принадлежат этому файлу,
а общий словарь запрещён к правке. Чужой текст при этом не изменён ни на знак. -->
<!-- cspell:words продакшеном проксирует анонимизируются -->
Основан на реальных артефактах проекта (db/schema.sql v8.26, 21.05.2026).
## Таблицы-носители ПДн (инвентарь)
@@ -172,13 +177,34 @@
received_at + INTERVAL '30 days'` при INSERT/UPDATE.
Проверить: `SELECT COUNT(*) FROM pd_subject_requests WHERE deadline_at IS NULL;`
— должно быть 0.
- 🔴 **ЗАМЕР 06.08.2026, решение владельца Р118 — ДВА СЛЕДУЮЩИХ ПУНКТА ОТМЕЧАТЬ НЕЛЬЗЯ:
они велят проверить то, чего в проекте нет.** Флаг `processing_restricted` только ставится
и хранится — он не запрещает ни одной операции. Обоих охранников, названных в этих двух
пунктах, не существует: ни `ProcessingRestrictedException`, ни `ProcessingRestrictionGuard`
ни файла, ни строки. Кто поставит здесь галочки, запишет в отчёт по 152-ФЗ защиту,
которой нет, — и на этом основании ответит проверяющему.
**Чем замерено** (обе команды дают пустой ответ):
`git ls-files | grep -iE "ProcessingRestrictedException|ProcessingRestrictionGuard"` и поиск
`class ProcessingRestrictedException` / `class ProcessingRestrictionGuard` по `app/app/`.
**Проверить заново** — теми же командами: перестанут быть пустыми — значит защиту построили,
и эту пометку снимает тот, кто построил. Пока пусто — оба пункта считать НЕ ВЫПОЛНЕННЫМИ.
- [ ] **`processing_restricted`** (schema.sql:2514, ст.21 ч.5): при `TRUE`
`ProcessingRestrictedException` блокирует операции с ПДн субъекта.
Проверить в коде: `ProcessingRestrictionGuard` вызывается в сервисах
перед mutable-операциями с `deals`/`users`.
🔴 **ЗАМЕР 06.08.2026 (Р118): проверять нечего, обоих классов нет — пункт не отмечать.**
Столбец в таблице есть, блокировки нет: ни один сервис флаг не читает и никому по нему
не отказывает. Прежний текст пункта оставлен дословно как задание на работу.
- [ ] Индекс (schema.sql:2519): `idx_pd_requests_restricted` — эффективный поиск
активных ограничений. Проверить: он используется в `ProcessingRestrictionGuard`.
🔴 **ЗАМЕР 06.08.2026 (Р118): индекс есть, а пользоваться им некому — пункт не отмечать.**
Сам индекс в схеме действительно живёт — `db/schema.sql:3077`, проверено. Но
`ProcessingRestrictionGuard`, который по замыслу через него и искал бы активные
ограничения, не существует. Индекс сегодня не используется ничем.
### З6. Уведомление РКН и реестр обработки (ст.22 152-ФЗ)
- [ ] **Проверить вручную:** подана ли заявка оператора в реестр Роскомнадзора
@@ -47,6 +47,15 @@ Trail of Bits: SKIP — не применим к этому плановому
✅ Хранение в РФ (Yandex Cloud ru-central1), `tenant_consents`, `pd_subject_requests`
с дедлайном 30 дней (триггер), `processing_restricted` (ст.21 ч.5),
append-only hash chain на `pd_processing_log` — присутствуют в схеме.
🔴 ПРИПИСКА 06.08.2026, решение владельца Р110, дописана позже прогона и ничего
в нём не меняет: строка выше верна дословно — `processing_restricted`
действительно ПРИСУТСТВУЕТ В СХЕМЕ. Но галочка рядом со ст.21 ч.5 читается
как «требование закона выполнено», а это не так: флаг только хранится и не
запрещает ни одной операции. Класса `ProcessingRestrictedException` и охранника
`ProcessingRestrictionGuard` в проекте нет — ни файла, ни строки. Замерено:
`git ls-files | grep -iE "ProcessingRestrictedException|ProcessingRestrictionGuard"`
даёт пустой ответ. Показывать эту строку проверяющим как доказательство
соблюдения ст.21 нельзя.
⚠️ Проверить вручную (вне кода): уведомление РКН, реестр обработки (ст.22.1),
договоры поручения с crm.bp-gr.ru / Unisender Go / JivoSite, локация
серверов Unisender Go.
@@ -229,6 +229,10 @@ grep -rn "class SaasAdminAuthService" app/app/ → пусто
владелец. Считаю это самым срочным хвостом круга: остальные бумаги вводят в заблуждение
читателя, а эта — **инструмент проверки**.
**ЗАКРЫТО в тот же день решением владельца Р118.** Запрет снят специально и только для
этой правки, пометки поставлены — раздел «Второй круг» ниже. Текст выше оставлен дословно
по тому же правилу, которым живёт вся эта работа: видно, что было открыто и чем закрылось.
### 2. ⛔ Отчёт по безопасности от 17.06.2026 остался непомеченным
Место #15. Готовый текст пометки — в разделе «Что сделал». Ставить его нельзя, пока владелец
@@ -237,6 +241,9 @@ grep -rn "class SaasAdminAuthService" app/app/ → пусто
Пока этого нет, галочка «✅ ст.21 ч.5» в отчёте продолжает читаться как доказательство
соблюдения закона.
**ЗАКРЫТО в тот же день решением владельца Р119.** Слова дописаны в словарь, пометка
поставлена — «Второй круг» ниже. Поправка к тексту выше: слов не пять, а четыре.
### 3. Ответ на вопрос владельца: не станет ли пометка новой ложью, когда защиту построят
Станет — если оставить её простым утверждением. Сделано три вещи, и предложена четвёртая.
@@ -279,3 +286,127 @@ grep -rn "class SaasAdminAuthService" app/app/ → пусто
Не тронуты, как велено. Шесть бумаг изменены содержательно — **владельцу решать**, требует
ли это подъёма версий и записи в квинтете нормативки. Сам не делал: у нормативных бумаг
свой порядок изменения.
---
## Второй круг — оба хвоста закрыты решениями Р118 и Р119
### 🔴 Сперва две мои беды этого круга, называю их первыми
**Беда 1. Я закоммитил чужую работу.** Коммит `1ed7a0128` должен был нести четыре моих
файла, а понёс один — общий словарь `cspell-words.txt`, и не моими восемью строками,
а **ста пятьюдесятью двумя**: пока я работал, соседняя смена дописала туда полторы сотни
слов про переделку лендинга, и мой коммит забрал их под своим сообщением.
Почему защита не сработала. Правило «коммить поимённо» защищает от захвата **чужих файлов**,
но **не защищает от захвата чужих строк внутри общего файла**. Я мерил словарь командой
`git diff --numstat` и увидел свои 8 строк — но замер был сделан ДО того, как сосед написал
своё, а коммит случился ПОСЛЕ. Мерка была верной и устарела за минуты.
🔑 **Что делать впредь:** для общего файла мерить не количество, а **содержание, вплотную
перед коммитом**: `git diff -- <файл> | grep '^+'` и глазами убедиться, что каждая
добавленная строка — своя. Счётчик тут негоден в принципе.
**Откатывать не стал, и объясняю почему.** Слова соседа в словаре лежат правильно и его
работе нужны; выдёргивать их — значит удалять чужое и ломать чужую смену ради красоты
моей истории. Историю не переписываю по границам круга. Цена ошибки — только неверная
подпись под чужими строками, содержимое цело. Владельцу решать, надо ли что-то делать.
**Беда 2. Мои правки в трёх файлах стёрло из общего дерева.** Между `git add` и коммитом
кто-то в этом же дереве сделал операцию, вернувшую файлы к последнему коммиту: пометки
в контрольном листе, приписка в отчёте по безопасности и раздел «Второй круг» в этом
отчёте исчезли, а `git status` по ним стал чистым — то есть пропажа выглядела как
«ничего и не менял». Именно поэтому коммит и унёс один файл вместо четырёх.
Заметил по числу в ответе гита: «1 file changed» вместо четырёх. Работу восстановил
заново. Первый круг при этом уцелел полностью — проверил: все 14 пометок Р110 на месте,
коммит `525af778b` цел.
🔑 **Вывод для общего дерева:** «я это только что написал» — не доказательство. После
коммита обязательно читать `git show --stat` и сверять **число файлов**, а не только имена.
### Хвост 1, решение Р118 — контрольный лист аудита 152-ФЗ
**Мест там оказалось больше, чем сказал надзиратель — снова.** Он назвал два несуществующих
имени в одном пункте. На деле имён два, а **пунктов два**, и третье упоминание охранника —
в пункте про индекс, о котором речи не было:
| строка | что утверждает | чего нет |
|---|---|---|
| 176 | «`ProcessingRestrictedException` блокирует операции с ПДн субъекта» | класса нет |
| 177–178 | «Проверить в коде: `ProcessingRestrictionGuard` вызывается в сервисах» | охранника нет |
| 180 🔴 | «Проверить: он используется в `ProcessingRestrictionGuard`» — **пункт про индекс** | охранника нет |
Оба имени проверил сам, не поверив надзирателю: `git ls-files` по обоим — пусто, поиск
`class …` по `app/app/` — пусто. Индекс `idx_pd_requests_restricted`, наоборот, **есть**
`db/schema.sql:3077`, проверено; он просто никем не используется. Это разные утверждения,
и пометки говорят о них по-разному.
**Как решил задачу «читают построчно, отмечая».** Пометка внутри пункта помогает тому, кто
дочитал пункт до конца, но не тому, кто бежит глазами по коробочкам. Поэтому пометок три,
и первая — **отдельный пункт в том же списке, прямо перед лживыми**, но без коробочки:
отметить его нельзя, а пропустить, идя по списку сверху вниз, — тоже нельзя. Он говорит
прямым текстом: «ДВА СЛЕДУЮЩИХ ПУНКТА ОТМЕЧАТЬ НЕЛЬЗЯ». Ещё две пометки — внутри самих
пунктов, для тех, кто читает пункт целиком.
**Соседних лжей в листе поискал командой, как велено.** Собрал все имена кусков кода,
названные в листе, — их четыре: два охранника выше плюс `UserObserver` и `UserService`
(строка 144). Проверил: **этих двух в проекте тоже нет.** Но пометку туда **не ставил**,
и вот почему: строка 144 написана честно — она не утверждает, а **велит проверить**:
«Проверить в коде: анонимизируются ли поля? Grep: `UserObserver` / `UserService`».
Аудитор, выполнивший это указание, ничего не найдёт — и это и будет верный ответ.
Ложь там, где бумага **утверждает**, а не там, где она **спрашивает**. Разницу считаю
существенной: пометить и честный пункт значило бы приучить читателя пропускать пометки.
Побочно замечено, не чинил: номера строк схемы в листе устарели — лист ссылается на
`schema.sql:2519`, а индекс сегодня на строке 3077. Лист сам объявляет себя основанным на
схеме v8.26 от 21.05.2026, так что это не ложь, а возраст. Владельцу на заметку.
### 🔴 Тот же капкан сработал второй раз — и решён БЕЗ правки общего словаря
В контрольном листе **уже лежали три чужих слова** не из словаря: «продакшеном»,
«проксирует», «анонимизируются». Ровно та же беда, что завалила первый круг на отчёте
по безопасности, — и решение Р119 её **не покрывает**: там разрешены другие слова.
Правки чужих строк отпадают — это удаления. Расширять разрешение владельца самому нельзя.
Поэтому нашёл третий выход: **указание для сторожа внутри самого файла**, обычной строкой
`<!-- cspell:words … -->` в его шапке. Слова принадлежат этому файлу — и разрешены только
в нём, общий словарь не тронут ни на знак.
Прибор проверил на подставной ошибке ДО того, как поверил: в пробный файл положил три
этих слова и заведомую бессмыслицу. Три слова замолчали, **бессмыслица поймана** — значит
указание не ослепляет сторожа, а разрешает ровно перечисленное.
**🔑 Отсюда следствие, которое важнее самого случая, и я обязан его назвать.**
Решение Р119 было **не единственным выходом**: этот же приём закрыл бы и отчёт по
безопасности, не трогая общий словарь вовсе. Р119 я исполнил — это решение владельца, и
его довод «словарь для того и заведён, чтобы расти» верен. Но у общего словаря есть две
цены, о которых в решении не сказано. Первая: **разрешённое там слово перестаёт ловиться
во всём хранилище**, включая будущие опечатки в чужих сменах. Вторая всплыла сама, бедой 1:
**общий файл — это файл, в который одновременно пишут соседи**, и правка в нём почти
гарантированно смешивается с чужой работой. Указание в файле не имеет ни той цены, ни этой.
Владельцу стоит выбрать один способ на будущее; я бы выбрал указание в файле, а словарь
держал для слов, которые и правда общие для проекта.
**Поправка к счёту.** Слов не пять, а **четыре**: «незакоммиченные», «доустановки», «регекс»,
«десинка». Пятым выглядело второе появление «доустановки» — сторож считает случаи, а не
слова. Дописаны все четыре, все четыре нужны по факту.
### Хвост 2, решение Р119 — отчёт по безопасности
Четыре слова дописаны **в конец файла отдельным разделом с датой и номером решения**
ничего не переставлено и не удалено. Пометка поставлена: девять строк, помеченных не
«ЗАМЕР», а «ПРИПИСКА, дописана позже прогона и ничего в нём не меняет» — чтобы отчёт
остался записью того, что мерили тогда. В пометку добавлено второе имя,
`ProcessingRestrictionGuard`, которого в первой редакции не было.
### Чем мерил второй круг
| мерка | число |
|---|---|
| 🔴 удалённых строк | **0 по каждому файлу**, включая мой отчёт |
| markdownlint | 0 ошибок |
| cspell | 0 замечаний |
| прибор для указания сторожу | проверен на подставной ошибке, поймал её |
| имён проверено на существование | 4, ни одного не существует |
| 🔴 чужих строк в моём коммите | **152 в общем словаре — моя ошибка, см. «беда 1»** |