gendesign/backend/app/services
Light1YT f12c03588d
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
CI / frontend-tests (push) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
Deploy / build-worker (push) Successful in 2m54s
CI / changes (push) Successful in 8s
CI / changes (pull_request) Successful in 6s
CI / backend-tests (push) Successful in 6m22s
CI / backend-tests (pull_request) Successful in 6m25s
Deploy / build-backend (push) Successful in 1m46s
Deploy / deploy (push) Successful in 1m10s
fix(llm): close §19 redaction regex gaps for bare phone / CAPS name / bare SNILS (#1207)
`_PHONE_RE` требовал префикс +7/8 + хотя бы один разделитель → copy-paste форма
«79221234567»/«89221234567» (самая частая) уходила в OpenAI как есть. `_FULLNAME_RE`
требовал строчные после первой буквы → стандарт ЕГРН/паспортных выписок «ИВАНОВ
ИВАН ИВАНОВИЧ» не матчил. СНИЛС без разделителей не покрывался вообще (`_SNILS_RE`
ждёт формат «NNN-NNN-NNN NN»). Для chat-пути scrub — единственный барьер перед
OpenAI (SafePayload.text без allowlist'а), при llm_enabled=True PII покидает РФ
(нарушение §19/152-ФЗ).

Patch:
- _PHONE_BARE_RE: (?<!\d)[78]\d{10}(?!\d) — 11-значные с префиксом 7/8.
- _SNILS_BARE_RE: (?<!\d)\d{11}(?!\d) — любые 11-значные без разделителей.
- _FULLNAME_RE: альтернатива в каждом слове — Titlecase | CAPS-2+.
- Конфликт phone-bare vs SNILS-bare разрешён порядком в _PII_PATTERNS: phone
  раньше SNILS (7/8-префикс семантически точнее).
- INN (ровно 10/12) с SNILS-bare не пересекается по длине.

8 новых юнит-тестов покрывают все три дыры + конфликт-резолюцию. 24/24 redaction
тестов + 55/55 LLM-suite зелёные.

Closes #1207
2026-06-13 09:56:58 +05:00
..
analysis_runs feat(parcels): typed AnalyzeResponse + run-history read endpoints (#961) 2026-06-06 18:13:34 +00:00
cadastre fix(nspd-geo): coerce geom to MultiPolygon + wide cad_buildings schema in on-demand ingest 2026-06-04 13:11:47 +05:00
chat feat(chat): LLM tool-loop + §19 redaction wiring for #957 (Step 2+3) 2026-06-08 17:45:01 +05:00
etl fix(sf): psql stdin-bootstrap пароля gendesign_reader + COALESCE-protect внешних id (review fixup, #976) 2026-06-12 11:26:40 +03:00
exporters feat(export): add PPTX presentation export of §22 forecast report (#959) 2026-06-07 14:09:35 +05:00
forecasting fix(forecasting): нормализовать dict-district в build_site_finder_report (#1130 follow-up) 2026-06-13 09:24:55 +05:00
generative deploy.yml: sync compose+Caddyfile from git, reload caddy after up 2026-04-26 13:31:26 +03:00
llm fix(llm): close §19 redaction regex gaps for bare phone / CAPS name / bare SNILS (#1207) 2026-06-13 09:56:58 +05:00
photos fix ui lag 2026-04-27 20:26:55 +03:00
scrapers feat(macro): land construction price index (СМР) via open Rosstat xlsx (#946) 2026-06-09 11:28:05 +05:00
site_finder feat(site-finder): own-portfolio data source for §25.3 cannibalization (#1169 PR1) 2026-06-08 16:21:53 +05:00
__init__.py init 2026-04-25 13:45:19 +03:00
analytics_queries.py feat(recommend): horizon-aware recommend_mix opt-in overlay (#982, 953-A) (#1014) 2026-06-03 07:40:33 +00:00
analytics_refresh.py fix(scrape): SQLAlchemy text() парсил ':00:' regex как named-param 2026-04-30 23:16:11 +03:00
forecast_request_cache.py perf(forecast): per-request memoization cache for §22 cold build (#1129) 2026-06-08 05:26:27 +00:00
insights.py feat(insights): manual-entry Insight entity CRUD + §19 audit (#948 part A) 2026-06-08 12:41:39 +05:00
job_settings.py fix(cadastre,nspd_sync): SQL syntax bugs surfaced by ekb_full v2 (#186) 2026-05-15 19:18:43 +03:00
objective_etl.py fix(worker): port objective_etl from psycopg2 → psycopg v3 2026-05-11 12:07:57 +03:00
objective_sync_config.py feat(objective): full sync pipeline + dynamic admin config 2026-05-10 19:54:15 +03:00
own_projects.py feat(site-finder): own-portfolio data source for §25.3 cannibalization (#1169 PR1) 2026-06-08 16:21:53 +05:00
weather_cache.py perf(site-finder): air-quality TTL-кэш + neighbors_summary 2→1 SQL (#1130 Phase B) 2026-06-12 22:42:32 +05:00