11 KiB
Актуальный технический аудит 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.yamlintentionally contains local demo defaults; onlycompose.production.yamlhas 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
- 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).
- 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.
- Waterbody data: process the remaining 18 detail snapshots under the shared cooldown, then complete W03–W08 without assigning unreviewed media roles.
- Source governance: attach durable primary permission evidence and image rights before expanding public catalog coverage (Q01).
- 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.mdare the current decision context.