fix(ptica): скраб ПДн перед отправкой в мониторинг + честная подпись НДС в отчётах (#2457) #2749

Merged
lekss361 merged 2 commits from fix/ptica-pii-scrub-and-vat-label into main 2026-08-06 18:47:35 +00:00
Owner

Волна 0 инвентаризации техдолга. Две независимые правки в backend «Птицы».

1. Персональные данные уходили в мониторинг незачищенными

У МЕРЫ скраб персональных данных перед отправкой события есть, у Птицы его не было вовсе — присутствовала только очистка секретов из URL. Механизм портирован один в один, чтобы дальше сопровождать одинаково: рекурсивная очистка по именам ключей в request.data, extra, contexts, регистронезависимо.

Проверено, что это не гипотетические поля: backend/app/api/v1/pilot.py:27-58 отправляет name, phone, email при записи заявки пилота. Имена с префиксом client_ в коде Птицы не встречаются — набор ключей выверен по факту, а не скопирован вслепую.

Более серьёзная дыра нашлась попутно: в workers/celery_app.py обработчик before_send отсутствовал полностью — то есть фоновый обработчик слал ошибки в мониторинг вообще без какой-либо очистки. Теперь оба места (main.py и Celery) используют композицию: сначала скраб персональных данных, затем очистка URL.

Восемь тестов, зеркалящих покрытие у МЕРЫ — минус специфичные для телеграм-бота, которого у Птицы нет.

2. Подпись в отчётах занижала состав суммы (#2457)

НДС (паркинг)НДС (паркинг + коммерция) в экспорте DOCX и HTML.

Подтверждено перед правкой: services/generative/financial.py:743-751 считает НДС как сумму по паркингу и нежилым помещениям; докстринг модуля прямо это описывает. То есть подпись систематически называла лишь часть того, что входит в число.

Третье место найдено, но не тронуто: frontend/src/components/concept/ConceptVariantsResult.tsx:659 — та же подпись во фронтенде. Вне объёма backend-правки, нужен отдельный заход.

Проверка

ruff check и ruff format --check чисто. Полный набор тестов: 4549 passed, 52 skipped, 0 failed.

Отдельно локализован предсуществующий дефект окружения, не связанный с этим PR: семь файлов в tests/api/v1/ шлют запрос без подмены отправки задачи в очередь, из-за чего в этом Windows-окружении происходит реальное обращение к Redis и зависание на разрешении имени. Проверено откатом правок на чистый main — воспроизводится идентично до и после, регрессом не является. В CI не проявляется: там отказ в соединении приходит сразу.

Волна 0 инвентаризации техдолга. Две независимые правки в backend «Птицы». ## 1. Персональные данные уходили в мониторинг незачищенными У МЕРЫ скраб персональных данных перед отправкой события есть, у Птицы его **не было вовсе** — присутствовала только очистка секретов из URL. Механизм портирован один в один, чтобы дальше сопровождать одинаково: рекурсивная очистка по именам ключей в `request.data`, `extra`, `contexts`, регистронезависимо. **Проверено, что это не гипотетические поля:** `backend/app/api/v1/pilot.py:27-58` отправляет `name`, `phone`, `email` при записи заявки пилота. Имена с префиксом `client_` в коде Птицы не встречаются — набор ключей выверен по факту, а не скопирован вслепую. **Более серьёзная дыра нашлась попутно:** в `workers/celery_app.py` обработчик `before_send` отсутствовал полностью — то есть фоновый обработчик слал ошибки в мониторинг вообще без какой-либо очистки. Теперь оба места (`main.py` и Celery) используют композицию: сначала скраб персональных данных, затем очистка URL. Восемь тестов, зеркалящих покрытие у МЕРЫ — минус специфичные для телеграм-бота, которого у Птицы нет. ## 2. Подпись в отчётах занижала состав суммы (#2457) `НДС (паркинг)` → `НДС (паркинг + коммерция)` в экспорте DOCX и HTML. **Подтверждено перед правкой:** `services/generative/financial.py:743-751` считает НДС как сумму по паркингу **и** нежилым помещениям; докстринг модуля прямо это описывает. То есть подпись систематически называла лишь часть того, что входит в число. **Третье место найдено, но не тронуто:** `frontend/src/components/concept/ConceptVariantsResult.tsx:659` — та же подпись во фронтенде. Вне объёма backend-правки, нужен отдельный заход. ## Проверка `ruff check` и `ruff format --check` чисто. Полный набор тестов: **4549 passed, 52 skipped, 0 failed**. Отдельно локализован **предсуществующий дефект окружения, не связанный с этим PR**: семь файлов в `tests/api/v1/` шлют запрос без подмены отправки задачи в очередь, из-за чего в этом Windows-окружении происходит реальное обращение к Redis и зависание на разрешении имени. Проверено откатом правок на чистый `main` — воспроизводится идентично до и после, регрессом не является. В CI не проявляется: там отказ в соединении приходит сразу.
lekss361 added 1 commit 2026-08-06 17:51:31 +00:00
fix(ptica): скраб ПДн перед отправкой в мониторинг + честная подпись НДС в отчётах (#2457)
All checks were successful
CI / changes (pull_request) Successful in 9s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m49s
CI / backend-tests (pull_request) Successful in 15m6s
d7ccf48000
Портирован PII-scrub механизм МЕРЫ (scrub_pii_event, ключи client_name/
phone/email/name) в backend/app/observability/sentry_scrub.py и подключен
как before_send в app/main.py и app/workers/celery_app.py — раньше worker
вообще не скрабил error-события, только transaction-spans (URL-secrets).
send_default_pii=False эти поля не закрывает (проверено на sentry-sdk 2.58).

full_report_docx.py / full_report_html.py: "НДС (паркинг)" -> "НДС (паркинг
+ коммерция)" — vat_rub системно включает office_value_added (коммерция),
подпись занижала состав суммы (#2457).
bot-backend added 1 commit 2026-08-06 18:23:10 +00:00
fix(ptica): скраб ПДн на transaction-канале + company/message ключи (review #2749)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m15s
CI / backend-tests (pull_request) Successful in 15m14s
cf7e7ec8c8
before_send_transaction в main.py/celery_app.py оставался на голом
scrub_sensitive_query (только URL) — Starlette-интеграция кладёт request.data
на transaction-scope так же, как на error-scope, поэтому PII продолжало течь
через transaction-канал при glitchtip_traces_sample_rate > 0 (0.05 по
умолчанию, config.py:19). Оба канала теперь на едином composed-хендлере
scrub_event (PII-scrub + URL-secret redact), вынесенном в sentry_scrub.py.

_PII_KEYS расширен до полного набора МЕРЫ (client_name/client_phone/
client_email/phone/email/name, #396) + company/message — PilotRequestInput
(app/api/v1/pilot.py) несёт оба свободнотекстовых поля, куда чаще всего
прилетают телефоны/имена/адреса.

scrub_event обёрнут в try/except (возвращает event при сбое скраба) —
sentry_sdk capture_internal_exceptions иначе только логирует и ДРОПАЕТ event
целиком, если before_send бросает исключение. Убрана мёртвая ветка
"if scrubbed is None: return None" — scrub_pii_event никогда не возвращает
None.

Тесты: новые ключи (company/message/client_phone/client_email), scrub_event
composition + exception-safety, source-grep wiring-гейт на саму строку
before_send_transaction=scrub_event в main.py/celery_app.py.
lekss361 merged commit ac870b0c58 into main 2026-08-06 18:47:35 +00:00
lekss361 deleted branch fix/ptica-pii-scrub-and-vat-label 2026-08-06 18:47:36 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2749
No description provided.