# Актуальный технический аудит RF4 Spotter — 20 сентября 2026 База аудита: ветка `main`, commit `d438c40`, рабочая копия проверена 20.09.2026. Изменения до аудита уже существовали в рабочем дереве только в `README.md` и `docs/ROADMAP.md`; они сохранены и не смешаны с результатами аудита. Цель — отделить фактически проверенное локально от исторических результатов, которые требуют повторного Docker/browser/production-прогона. ## Итог Проект представляет собой функциональный single-owner alpha MVP на Astro SSR, FastAPI, PostgreSQL, MinIO и Caddy. Кодовая база сейчас проходит локальные quality gates: Python — `190 passed, 1 skipped`, Astro check — `0 errors / 0 warnings / 0 hints`, production build — успешен, web unit — `1 passed`, media audit — без issues и orphan-файлов. Production Compose файл корректно интерполируется с безопасными временными значениями, а Alembic graph имеет единственную голову `0020`. Открытая альфа ещё не готова к объявлению production-ready. Не подтверждены в этой сессии: запуск чистого полного Compose stack, фактический `alembic current` против PostgreSQL, внешний DNS/TLS/backup/restore, browser acceptance тем, административных сценариев и B25 media. Это инфраструктурные и приёмочные ограничения, а не обнаруженная ошибка сборки. ## Архитектура и границы ответственности | Слой | Текущее состояние | Оценка | |---|---|---| | Caddy | Production proxy, TLS/Basic Auth для `/admin`, API routing, headers, CSP | готово локально; внешний TLS не проверен | | Astro | SSR Node adapter, public/admin pages, server-side form/API bridges | сборка и check проходят | | FastAPI | роутеры activity/catalog/media/public/admin/submissions, health/readiness | API contract и тесты проходят | | PostgreSQL | SQLAlchemy 2, Alembic, persistent rate-limit/import history | миграционный graph проверен, живая БД не запущена | | MinIO/S3 | отдельный app user/policy, Git media proxy и provenance | offline media audit проходит | | Scheduler/import | opt-in Compose profiles, общий cooldown/backoff контур | запуск источников намеренно не включён по умолчанию | Архитектурное решение Astro + FastAPI + PostgreSQL сохраняется. API уже разделён на роутеры, поэтому старое замечание о монолитном `main.py` из аудита 10 сентября больше не актуально. `main.py` оставляет composition root, middleware, health/readiness и регистрацию роутеров. ## Проверки и доказательства | Проверка | Результат | Комментарий | |---|---:|---| | `.venv/bin/pytest -q` | `190 passed, 1 skipped` | 72 deprecation warnings FastAPI/`asyncio.iscoroutinefunction`; skip — PostgreSQL integration | | `npm --prefix apps/web run check` | 0/0/0 | 61 Astro files inspected | | `npm --prefix apps/web run build` | passed | SSR Node production build | | `npm --prefix apps/web run test:unit` | `1 passed` | Node unit suite | | `media_cli --audit` | 704 entries, 0 issues | 466 approved, 226 superseded, 1 duplicate, 11 invalid; no orphans | | `media_cli --quality-report` | 253 fish published | 252 are 1024×1024 WebP; one 48×48 fallback remains | | `docker compose -f compose.production.yaml config --quiet` | passed | checked with temporary non-secret values only | | dev `docker compose up --build --wait` | passed | PostgreSQL, MinIO, API and web healthy; migration service exited 0 | | live `/health`, `/ready`, public routes | passed | health/readiness and public `/`, `/waterbodies/`, `/records/` returned expected responses from container network | | Alembic `heads` / live `current` | `0020 (head)` | both repository graph and running PostgreSQL verified | | waterbody catalog import/audit | `19/19`, 0 failures | canonical snapshot applied; no missing, duplicate or provenance issues | | OpenAPI | passed after Q16 fix | `apps/api/export_openapi.py --check` passes with `36 paths`; artifact regenerated from FastAPI, not manually edited | | Browser acceptance | not confirmed | in-app browser backend unavailable in the current session | The dev stack was stopped after the checks without removing its named volumes. This is a local integration gate, not a production deployment or external browser acceptance. ## Backend and data layer ### Strengths - API endpoints are separated into focused routers and have a tracked OpenAPI generator/artifact; Q16 was closed by regenerating the artifact and passing the deterministic check. - Alembic migrations are linear through `0020`; latest migrations cover waterbody provenance, coordinate precision, fish counts and detail fields. - Official/community import paths preserve old data on incomplete or failed responses, use provenance, and keep network fetching opt-in. - Admin media publish/rollback keeps fallback assets and provenance; public media is content-addressed and served locally rather than hotlinked. - Rate limiting uses a persistent, privacy-preserving HMAC client hash and trusted-proxy handling. ### Remaining risks - The single-owner admin model still uses a shared Bearer token and proxy Basic Auth. A05 (personal accounts, roles, revocation and operator IDs) is correctly deferred until the pilot has more than one operator. - Public cache is process-local; shared invalidation/Redis is explicitly a post-pilot decision and should not be added before measured need. - Production query p95 and real data growth are not measured in this workspace. The existing query-plan gate is a local fixture gate, not a production SLO. - The waterbody canonical index has 19 verified entries, but detail snapshots currently cover only the first waterbody. W02–W08 remain open. ## Frontend, accessibility and visual system Astro SSR pages include public catalogs, fish/waterbody/spot detail, official records, reports, status, media and admin screens. The current implementation has semantic light/dark tokens, system/manual theme selection, forced-colors rules, nonce-based JSON-LD CSP, noindex/no-store handling for admin/error surfaces, responsive pagination and reduced-motion styles. Automated structural and browser checks pass, but visual acceptance is not equivalent to `astro check`. The local visual matrix now covers 13 routes × 4 viewports × 3 theme modes (156 combinations) without document overflow, with matching SSR theme, `main` and `h1`; accessibility E2E covers axe 9/9, keyboard/focus, print and forced-colors. B25, D05/D07 and A06 remain open only for retained reference screenshots and manual review of long data, empty/error states, shadows and gradients. ## Security and operations ### Confirmed in code/config - Production settings reject demo/short admin, rate-limit and S3 credentials. - Production CORS requires explicit HTTPS origins; demo seeding is forbidden. - Caddy and API set HSTS, `nosniff`, restrictive referrer/permissions policy, anti-framing headers and CSP; Astro uses a per-response nonce for JSON-LD. - Production MinIO app credentials are separated from root credentials and limited to one bucket's list/location/get/put/delete operations. - CI contains locked dependency installation, pip-audit, clean migration, Compose E2E and scheduled production-bootstrap drill definitions. ### Not yet proven for release - No production server, DNS, TLS certificate, real secrets or external backup restore were exercised here. - `compose.yaml` intentionally contains local demo defaults; only `compose.production.yaml` has fail-fast production secret requirements. - The scheduled bootstrap workflow exists, but its latest successful run is a repository history fact, not a fresh verification in this workspace. - The Docker operator account remains a high-privilege operational boundary; SSH/firewall/VPN restrictions belong to deployment hardening. ## Media and provenance snapshot The manifest contains 704 records: 466 approved, 226 superseded, one provenance-only duplicate and 11 invalid records. Fish quality-upgrade processing completed for 226 alternatives; 253 fish assets are published, 252 with 1024×1024 WebP and one explicit low-resolution fallback. Offline media audit reports no checksum/dimension/MIME/provenance/orphan problems. Browser checks now cover broken images, responsive overflow, light/dark presentation and source links on the media/admin paths; the visual matrix also confirms route-level overflow and SSR theme consistency. This does not close B25 because retained reference screenshots and manual visual review are still required. It also does not grant new source permissions; Q01 remains the source-rights gate. ## Prioritized action plan reflected in ROADMAP 1. **Release blockers:** repeat the clean production Compose/bootstrap gate; verify readiness, migration current, proxy routing, backup/restore and production secret/preflight checks (A07 and open-alpha gate). 2. **Browser gates:** retain reference screenshots and finish the remaining manual visual review for B25, A06 and D07; the Chromium matrix and accessibility regression gates are already green locally. 3. **Waterbody data:** process the remaining 18 detail snapshots under the shared cooldown, then complete W03–W08 without assigning unreviewed media roles. 4. **Source governance:** attach durable primary permission evidence and image rights before expanding public catalog coverage (Q01). 5. **After pilot:** personal admin identities (A05/M06), shared cache only after measurement, production p95 and external search/analytics integrations. ## Scope decisions - No Next.js/Vinext migration, Redis addition, broad CSS rewrite or unrelated refactor is justified by this audit. - No external source was fetched during this audit. - No media was downloaded, replaced or automatically promoted. - Historical audits remain historical; this document and `ROADMAP.md` are the current decision context.