---
name: zemlya-expert-report-rename-and-verify
description: "ЗБР+ТБР: AI-отчёт переименован в экспертный (пометки ИИ сняты решением владельца), у отчёта появился публичный номер для проверки покупателем; лимит в памяти сайта не работает — бэкенд в 4 воркерах"
metadata: 
  node_type: memory
  type: project
  originSessionId: d0c6c5aa-4d05-42e2-a1f9-034482b88603
  modified: 2026-08-01T14:00:49.393Z
---

**2026-08-01.** Два изменения по всем четырём кодовым базам (бот ЗБР, сайт zbrcheck.ru, бот и сайт ТБР).

**Переименование.** «AI-отчёт» → «экспертный отчёт», пометки «(ИИ)» и упоминания нейросети сняты — решение владельца, моё возражение (подпись эксперта под непросмотренным текстом; в FR-A пометку ставили сознательно) высказано и отклонено. Правовая часть дисклеймера оставлена. Внутренние имена (`ai_reports`, `AI_REPORTS_DIR`, `/ai-file`, `/ai-html`, `/internal/lot-ai-report`) НЕ трогали. Скрипт замены со склонениями — `rename_ai.py` в скретчпаде сессии. Цифру опыта в блок «Методология проверки» не вписали — ждёт подтверждения владельца.

**Проверка отчёта по номеру `[ZW-VERIFY-2026]`.** `ai_reports.public_code` (10 знаков, ~2^49) + `published_at` + `pdf_sha256`; публикация — по кнопке владельца в боте; страница `zbrcheck.ru/check`; по коду отдаётся PDF БЕЗ блока «Проверка продавца», полный — только назвавшему ФИО+ИНН продавца. Рендер редакции живёт в боте (`/internal/public-report`), сайт ходит туда по внутреннему токену.

**Грабля, стоящая запоминания: счётчик попыток в памяти бэкенда сайта не работает — uvicorn поднят с `--workers 4`.** Шесть попыток подбора ФИО+ИНН подряд прошли без единого отказа: запросы разложились по процессам. Любой in-memory лимит/кэш на сайте нужно либо держать в боте (он один процесс), либо в БД. Поймано только живым прогоном.

**Имя PDF на диске строилось только из КН** — повторный отчёт затирал предыдущий (ai_reports 237/238/239, один `file_path`). Добавлен id отчёта, иначе «по номеру откроется тот же документ» было бы ложью.

Живой прогон `/start` в Telegram поймал то, чего не видел греп: «Экспертный отчёт с экспертным анализом» (тавтология после автозамены) и «Пакеты AI».

**Приёмка вне интерфейса нашла ещё три.** (1) В фискальный чек 54-ФЗ уходит НЕ «Консультационные услуги», как уверяли докстринг и `ROBOKASSA_RECEIPT_PLAN.md`, а буквально описание платежа (`_build_receipt(item_name=description)`) — было «Покупка 3 экспертный отчёт(ов)»; `ROBOKASSA_RECEIPT_PRODUCT_NAME` не срабатывает никогда, потому что описание всегда заполнено. (2) Переименование сломало собственные e2e бота: один тест искал исчезнувшую кнопку «AI отчет», второй проверял ОТСУТСТВИЕ «AI» и потому больше не мог провалиться. (3) `scripts/send_onboarding_reminder.py` — живой launchd-джоб — продолжал обещать новичкам «1 AI-отчёт». Обобщение: фича живёт не только в нескольких код-путях, но и в нескольких **типах артефактов** — обработчики и страницы я прошёл, а скрипты по расписанию, тесты и фискальные строки нет.

**Схема владельца доведена до рабочей (вечер).** По ссылке отчёт открыт всем без входа; ручной ввод номера — только в кабинете (`/dashboard/check`); по ссылке покупателю дают выбор: назвать ФИО+ИНН продавца → полный документ, либо кнопка «открыть без них». В боте кнопка «🔎 Отчёт по номеру» в ЛК. Чтобы сверка стала возможной, храним **солёный SHA-256 пары ФИО+ИНН** (`seller_checks.query_fp` → `ai_reports.seller_fp`), сами ПДн по-прежнему нет (D-57, D-58). Смена внутреннего токена обесценит старые отпечатки.

**Три грабли этого захода.** (1) Мой e2e «не нашёл» кнопку в боте, потому что читал кнопки со ВСЕЙ страницы Telegram Web и попал на клавиатуру старого сообщения — читать только из последнего `data-mid`. (2) Рядом с ботом ЗБР крутится `python -m bot.main` от Автеро — тот же модуль, другой каталог и токен; выглядит как дубль поллинга, но им не является, проверять cwd и токен до того, как что-то убивать. (3) Согласование числительных: после 2-4 прилагательное в родительном МНОЖЕСТВЕННОГО — «3 экспертных отчёта»; я дал агентам неверное правило, и оно разъехалось по кодовым базам.

**Главный вывод дня — одна фича живёт в нескольких путях, и проверять надо каждый.** Пять находок, все одного класса: поведение добавлено в один код-путь, а система состоит из нескольких. (1) лимит попыток — в памяти сайта, а воркеров четыре; (2) веб-заказ идёт через `web_report_worker`, а не через обработчик бота — отчёт оставался без номера, файл затирал предыдущий; (3) `rerender_with_seller_check` пересобирала опубликованный отчёт БЕЗ номера — из PDF исчезал штамп, кэш редакции протухал; (4) имя при скачивании с сайта было `ZemlyaBezRiska_AI_…`; (5) архиватор рекурсивно уносил кэш `data/ai_reports/public/` как документы. Рецепт: после правки функции пройтись по ВСЕМ её вызовам (`grep -rn 'имя_функции('`) и по соседям по данным (кто ещё пишет в ту же папку/таблицу).

**Разбор той же работы под другим углом (вечер) дал две находки против себя.** (1) Ветка «полный PDF после ввода ФИО+ИНН» **в проде недостижима**: `save_check` по 152-ФЗ пишет `fio=None, inn=None`, а сверка сравнивает ровно с этим полем — 0 отчётов из 182 способны отдать полный вариант. Проверял я её на фикстуре, куда ФИО вписал сам. Пользователь тупика не видит (форма скрыта флагом `has_seller_block`), но вернуть ветку можно только храня солёный отпечаток пары — это решение владельца. (2) Моя же редакция вырезала `seller_check` целиком, хотя ПДн там нет вовсе: покупатель терял доказательство проверки продавца, а на отчёте с АКТИВНЫМ банкротством молча исчезал красный флаг. Теперь `redact_seller_for_public` убирает только личность, вывод берётся из агрегата `has_active` (D-55). Побочно всплыл [[pdf_text_layer_apple_system_font]] — в отчёте не работал поиск по документу.

Проверено живьём: полный цикл заказ отчёта → кнопка публикации → номер → страница проверки → PDF (отпечаток сошёлся с файлом); QR сверен по модульной сетке (961/961, чужой код даёт 67.7%); уникальность `public_code` реально отклоняется базой; поиск по коду нормализует регистр, пробелы и отсутствие дефиса. `build_docx_report` — мёртвый код без вызовов, не трогали. См. [[zemlya_web_overview]], [[zemlya_utilities_sources_recon]].
