3f4c7f0f68
Часть эпика рефакторинга рендер-пайплайна (#34). Один bleach-конфиг на весь проект, один санитайз на пост, ноль thread-hop'ов в циклах (раньше конфиг был скопирован трижды и разъехался; RSS-путь делал to_thread + новый CSSSanitizer + вложенную функцию НА КАЖДЫЙ пост, хотя _render_pipeline уже в worker-треде). Новый sanitizer.py — единственная bleach-конфигурация: ALLOWED_TAGS (union трёх старых копий, вкл. s/del), ALLOWED_PROTOCOLS=['http','https','tg'], sanitize_html() зовёт bleach.clean(..., protocols=..., strip=True) (оба не-дефолт), fail-CLOSED (html.escape при любом исключении), единое имя лога html_sanitization_error + log_context. _render_pipeline санитайзит каждый пост после рендера (в своём worker-треде); rss_generator −71 строка. Реестр §3: - §3.1 s/del теперь в фидах (раньше выживали только в одиночном посте); - §3.2 fail-open → fail-closed (вкл. single-post/JSON путь); - §3.3 <hr class="post-divider"> реально виден (join ПОСЛЕ санитайза; hr не в whitelist, поэтому раньше вырезался strip=True); - §3.4 несбалансированный фрагмент нормализуется в границах своего поста; - §3.5 гранулярный fail-closed HTML-фида (падает один пост, не весь фид); - §3.16 три имени санитайз-логов объединены в html_sanitization_error+log_context. Golden-эталоны обновлены: КАЖДЫЙ изменённый байт привязан к пункту §3 (net-diff тегов: только +<s>/§3.1 и +<hr>/§3.3; <div> сбалансирован +/- = §3.4; после снятия этих токенов + нормализатора все 6 голденов побайтово old==new). Оракул этапа 0 зелёный. Полный сюит 346 passed (+14 sanitizer-тестов). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>