4 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a8fa7364ae |
merge(tradein/payments): влить main в feat/tradein-payments-perimeter-hardening
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m56s
Слияние main принесло собственные Sentry-скрубберы (redact_telegram_bot_token + stabilize_retry_error_fingerprint) в app/main.py и app/scheduler_main.py — конфликт разрешён композицией, а не выбором стороны: обработчик перед отправкой в GlitchTip теперь прогоняет событие через всю цепочку в указанном порядке: scrub_payment_request_body → scrub_pii_event → redact_telegram_bot_token → stabilize_retry_error_fingerprint (main.py), и без redact_telegram_bot_token в scheduler_main.py (тот процесс не держит TelegramClient) — оба канала, before_send и before_send_transaction, используют один и тот же обработчик. tests/test_sentry_scrub.py: тесты обеих сторон объединены без потерь — PR-D2 платёжный composed-тест (body-wipe + PII-scrub + token-redaction) и весь блок RetryError fingerprint-стабилизации из main сосуществуют в одном файле. |
||
|
|
c6243b166f |
feat(mera): оферта, политика возврата и утверждённая политика ПДн + реквизиты
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 56s
Юридический блокер публичного B2C-запуска (G6 в mera-b2c-paid-flow-decision.md: `LEGAL_ENTITY == null` → нет реквизитов, нет продажи) и входное требование модерации эквайера: оферты не было вообще, а privacy-страница в собственной шапке писала, что она НЕ утверждённая политика по ст. 18.1 152-ФЗ. Что сделано: - content.ts: `LEGAL_ENTITY` заполнен (ООО «ПРОЕКТ ФЛЭТ», ИНН/КПП/ОГРН, адреса, директор, банковские реквизиты), добавлены `SUPPORT_EMAIL`, `SERVICE_PRICE_RUB`, пути и короткие публичные URL документов. Единый источник — подвал, оферта, возврат и ПДн рендерят эти поля, а не повторяют строки. ОГРН сверен с открытыми данными ЕГРЮЛ (в исходном сообщении владельца был с опечаткой …028028, верный …028281). - Новые страницы /mera-public/oferta и /mera-public/refund — редакции владельца от 13.08.2026 дословно, плейсхолдер `[адрес электронной почты]` заменён на support@meraocenka.ru. - privacy/page.tsx переписана на утверждённую редакцию с оператором и реквизитами приказа. Сохранены оба инварианта честности: раздел про страницу ввода адреса условен по `PUBLIC_ESTIMATE_ENABLED` (п. 5.4 — пока публичный расчёт выключен, адрес не покидает браузер), срок хранения оплаченного отчёта рендерится из `PAID_REPORT_RETENTION_MONTHS`, а не числом в тексте (test_paid_retention_text_consistency.py). - Caddyfile: короткие адреса /oferta, /refund, /privacy → rewrite на поддерево лэндинга. Именно они напечатаны внутри документов и уйдут в заявку эквайеру. Пути перечислены поимённо — allowlist-by-default периметра не ослаблен. - smoke-mera-perimeter.sh: три новые проверки на короткие адреса. Публикация оферты НЕ включает приём оплаты: платёжного контура в коде нет, `PUBLIC_ESTIMATE_ENABLED` по-прежнему false. Оферта публикуется раньше кнопки намеренно — без неё эквайер не примет заявку. Проверено локально: tsc, next lint, vitest (29), isolation guard, next build (три страницы пререндерены), pytest test_paid_retention_text_consistency (3), caddy validate + adapt (rewrite на месте), рендер всех трёх страниц через next start — реквизиты, почта и цена на месте. |
||
|
|
1f85ef7d4e |
fix(tradein/payments): тело нотификации не течёт в мониторинг и аудит, повторы банка не отбиваются лимитом
All checks were successful
CI / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Successful in 3m50s
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
PR-D2 платёжного контура МЕРЫ — закрывает утечки до открытия публичных путей (PR-D3/D4), сам ничего не открывает: _PUBLIC_PATHS (rbac.py), Caddyfile, roles.yaml, auth_session.py не тронуты. - sentry_scrub.py: новая scrub_payment_request_body — вырезает event.request.data целиком для /api/v1/trade-in/payments/* (sentry_sdk 2.64 кладёт полное тело запроса в request.data, send_default_pii=False это НЕ гейтит — тот флаг управляет только куками). Плюс расширен _PII_KEYS: customer_email/customer_phone/pan/expdate/cardid/rebillid/token/terminalkey. - main.py, scheduler_main.py, tgbot_main.py (все 3 точки инициализации sentry_sdk.init в проекте) — тот же обработчик проведён в ОБА канала, before_send и before_send_transaction. Мотивирующий инцидент: на соседнем продукте вчера закрыли только error-канал, transaction остался без обработчика вообще. - ratelimit.py: точный путь notify — свой щедрый SlidingWindowLimiter (3000/60с per-IP, идиома support.py) вместо общего лимитера, но НЕ полное отключение — backstop против шторма запросов остаётся, подпись проверяется уже после разбора тела (PR-D3). Только notify, не checkout (тот с сессией). - request_audit.py: notify — в audit skip-набор (defense-in-depth: middleware внешний относительно rbac_guard и читает сырой X-Authenticated-User — спуфнутый заголовок иначе писал бы фальшивые события с атрибуцией admin). - smoke-mera-perimeter.sh: негативные проверки-канарейки — notify/checkout сейчас закрыты 404 (meraocenka.ru, Caddy не проксирует) и 401 (gendsgn.ru, rbac ещё не открыл) с обеих сторон периметра. Тесты: scrub на произвольной глубине + payment-path body-wipe, AST-разбор (не substring — комментарии в этих же файлах сами упоминают before_send_transaction) на проводку обоих каналов во всех точках инициализации, 400 запросов notify без единого 429 + контроль что общий лимитер по-прежнему активен на других путях, notify вне user_events даже со спуфнутым X-Authenticated-User: admin. |
||
| 55254b43e4 |
feat(mera/b2c): публичный периметр на отдельном домене meraocenka.ru — этап 1 из 8 (#2545)
Открывает публичный site-блок meraocenka.ru с allowlist-by-default: разрешены только корень лэндинга, его поддерево и _next/static, всё остальное 404. B2B-контур gendsgn.ru не затронут. DNS A-записи для всех трёх доменов на 46.173.16.127 подтверждены до мержа. |