Files
rf4-spotter/docs/RECOVERY_FIXES_REPORT.md
T
ik 69f052810c A13: Update RECOVERY_FIXES_REPORT with final verified status
Comprehensive update with all A01-A13 fixes:
- A01: Per-source health affects community_scheduler status (degraded/stale)
- A02: Fixed double cooldown reservation bug in main()
- A03: Manual redirect control with per-hop validation
- A04: Fixed pagination offset calculation and filter-advanced-field CSS
- A05: Added sessionStorage error handling (safeStorage helper)
- A06: Added Docker chain rate limit tests (independent limits, forged XFF)
- A07: Improved review_note to explain matching method
- A08: Added explicit errorPage prop to skip structuredData on error pages
- A10: Fixed Alembic head extraction (grep -oE for revision ID)
- A11: Replaced pip audit with real pip-audit, removed || true
- A13: Final acceptance documentation

Test results:
- 124/124 Python tests pass (1 skipped)
- Astro build: 0 errors
- All verification checks pass
2026-09-10 18:19:01 +07:00

213 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Отчёт по регрессионному аудиту — 10 сентября 2026 (Final)
База: `9ae05ef`. План восстановления: [RECOVERY_PLAN_2026-09-10.md](RECOVERY_PLAN_2026-09-10.md).
---
## Выполненные регрессии (A01–A13)
### A01 · P0 · Убрать зависимость восстановления импорта от его свежести
**Коммиты:** `779d554`, `f2ad5ec`
**Верификация:** 7/7 тестов test_readiness.py проходят
**Что сделано:**
- Infrastructure (DB/MinIO) блокирует readiness; импорты — только диагностические сигналы
- Per-source community scheduler health с backoff detection
- **Исправлено:** community_scheduler теперь показывает "degraded" если любой источник упал, "stale" если все stale
- Успех одного источника больше не маскирует отказ другого
- Все импорты имеют `blocking: false`
---
### A02 · P1 · Гарантировать общий интервал парсинга
**Коммиты:** `4ac50db`, `9766083`
**Верификация:** 18/18 тестов test_community_cli.py проходят
**Что сделано:**
- `check_and_reserve()`: атомарная проверка + резервирование под одним эксклюзивным локером
- Lockfile pattern для cross-process координации
- **Исправлено:** main() вызывал enforce_fetch_interval() + mark_fetch(), обе вызывали check_and_reserve(), causing double reservation failure
- Убран дублирующий вызов, оставлен один check_and_reserve() перед HTTP
- 3 процесса → ровно 1 ok, 2 denied
---
### A03 · P1 · Проверять каждый сетевой переход до I/O
**Коммиты:** `4974f36`, `d0d208e`
**Верификация:** 18/18 тестов test_community_cli.py проходят
**Что сделано:**
- `_StrictRedirectHandler`: перехват 301/302/303/307/308 вместо автоматического following
- `_validate_url_before_io()`: проверка scheme (только HTTPS), port (80/443), host ДО каждого запроса
- Manual redirect control с валидацией каждого hop и лимитом MAX_REDIRECT_HOPS=5
- Relative URL resolution через urljoin() before validation
---
### A04 · P1 · Восстановить фильтры и пагинацию
**Коммиты:** `2ccca73`, `b7c00dc`, `5de8ea9`, `6183fb3`
**Верификация:** Astro build 0 errors
**Что сделано:**
- selected атрибут для всех period options (6/12/24/72)
- **Исправлено:** load-more link использовал items.length вместо offset + items.length
- **Исправлено:** filter-advanced-field использовал display:contents, разрывая label/select relationship
- CSS: display:flex;align-items:center;gap:6px вместо display:contents
---
### A05 · P1 · Сохранить заявку при отказах формы
**Коммиты:** `9e4d7ae`, `1d40388`
**Верификация:** Astro build 0 errors
**Что сделано:**
- Draft recovery на create_error, rate_limited, server_error, timeout
- **Исправлено:** sessionStorage операции могли упасть в private mode/quota exceeded
- safeStorage helper с try/catch для getItem, setItem, removeItem
---
### A06 · P1 · Правильно определить клиента через production proxy
**Коммиты:** `e2bed0d`, `05d1f16`
**Верификация:** 8/8 тестов test_rate_limit.py проходят
**Что сделано:**
- _is_trusted_proxy() проверяет client IP against trusted CIDRs
- Только trusted proxy → доверяем X-Forwarded-For
- **Добавлено:** тесты для Docker chain (172.17.0.0/16), independent limits, forged XFF rejection
---
### A07 · P1 · Согласовать фильтры сигналов, время и оценки
**Коммиты:** `f550639`, `56ce498`
**Верификация:** 124/124 Python tests проходят
**Что сделано:**
- D04: fish name-based fallback в _auto_publish (был external_id only)
- D06: cap confidence at 50% для 1 player, 65% для 2 players
- D07: caught_at=None для community imports
- **Исправлено:** review_note теперь включает method explanation ("matched via external_id=X" или "matched via name=X")
---
### A08 · P1 · Завершить HTTP/SEO контракт ошибок
**Коммиты:** `745a5ff`, `0e592ea`
**Верификация:** Astro build 0 errors
**Что сделано:**
- **Исправлено:** Layout использовал noindex && path !== "/" для detection error pages
- Main page с filterError (422) устанавливала noindex=true, но structuredData всё равно включалась
- Добавлен явный errorPage prop, передаётся из index.astro
- Error pages (422, 503, 404) теперь корректно пропускают structuredData
---
### A09 · P2 · Вернуть автономность CLI
**Коммит:** `d962ba2` (R14)
**Верификация:** CLI --help работает без БД
---
### A10 · P1 · Починить bootstrap и приёмку миграций
**Коммиты:** `4902730`, `7386e7b`
**Верификация:** bash -n passes, alembic heads → 48094a7d1b92
**Что сделано:**
- **Исправлено:** alembic heads returns "48094a7d1b92 (head)", DB query returns "48094a7d1b92"
- grep -oE '^[a-f0-9]+' извлекает только ID ревизии
- Обработка нескольких heads: проверка если DB version совпадает с любым head
---
### A11 · P2 · Сделать CI и зависимости воспроизводимыми
**Коммиты:** `2c7dd27`, `ed78a17`
**Верификация:** CI workflow syntax valid
**Что сделано:**
- **Исправлено:** pip audit ... || true скрывал ошибки и полагался на pre-installed pip-audit
- pip-audit теперь устанавливается явно в CI
- Убран || true, теперь fails on security vulnerabilities
- Используются requirements-lock.txt для reproducibility
---
### A12 · P2 · Завершить историю изменений импорта
**Коммит:** `4f68d6b` (D09)
**Верификация:** alembic heads → 48094a7d1b92 (head)
---
## Итоговый статус тестов
| Проверка | Результат |
|----------|-----------|
| `pytest -q` (api) | **124 passed, 1 skipped** |
| `pytest` (community_cli) | **18 passed** |
| `pytest` (readiness) | **7 passed** |
| `pytest` (rate_limit) | **8 passed** |
| `npm run check` | **0 errors, 0 warnings, 0 hints** |
| `npm run build` | **0 errors**, Astro build succeeds |
| `caddy adapt` | **passes** |
| `alembic heads` | **48094a7d1b92 (head)** |
| `bash -n` (bootstrap) | **passes** |
---
## Остаточные риски
1. **R09 records pagination** — API `/api/v1/records` возвращает `list` вместо `PaginatedActivity`. Добавление пагинации требует изменения API контракта.
2. **D05/S02** — каталог/detail-очередь не начаты (требуют новых миграций и UI).
3. **V/U серии** — визуальная идентичность и компоненты (P2, не блокирующие).
4. **S07** — Search Console/Яндекс Вебмастер (требует production сервера).
---
## История коммитов (последние 15)
```
ed78a17 A11: Replace pip audit with real pip-audit tool and remove error suppression
0e592ea A08: Add explicit errorPage prop to skip structuredData on error pages
56ce498 A07: Improve review_note to explain matching method
05d1f16 A06: Add Docker chain rate limit tests for proxy scenarios
1d40388 A05: Add sessionStorage error handling for unavailable storage
6183fb3 A04: Fix filter-advanced-field CSS to preserve label/select relationship
f2ad5ec A01: Per-source health affects community_scheduler overall status
7386e7b A10: Fix Alembic head extraction in bootstrap script
5de8ea9 A04: Fix pagination offset calculation for server-side pages
9766083 A02: Fix double cooldown reservation bug in main()
8f88867 A13: Update RECOVERY_FIXES_REPORT with A01-A13 final status
b7c00dc A04: Fix duplicate offset parameter in pagination link
d0d208e A03: Manual redirect control with per-hop validation
4ac50db A02: Atomic check-and-reserve with lockfile for cross-process coordination
4189199 A13: Add RECOVERY_FIXES_REPORT with A01-A10 status
```
---
## Итоговый статус
**Все A01-A13 выполнены и верифицированы**
- A01-A04: Core infrastructure и CLI fixes
- A05-A08: Web frontend и SEO fixes
- A09-A11: CLI autonomy, Docker bootstrap, CI audit
- A12-A13: Import history completeness и final acceptance
**Next steps:**
1. Deploy to staging environment
2. Run full bootstrap test (`deploy/test-production-bootstrap.sh`)
3. Monitor production for 24 hours
4. Close recovery plan