Files
rf4-spotter/docs/PROJECT_AUDIT_2026-09-20.md
T

10 KiB
Raw Blame History

Актуальный технический аудит 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. W02W08 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 checks pass, but visual acceptance is not equivalent to astro check. B25, D05/D07 and A06 remain open for desktop/mobile light/dark, forced-colors, focus order, long data, empty/error states and screenshots.

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.

This does not close B25: browser checks for broken images, responsive overflow, light/dark presentation and source links 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: complete B25 media, A06 admin/accessibility and D07 full visual matrix when a Chromium/browser backend is available.
  3. Waterbody data: process the remaining 18 detail snapshots under the shared cooldown, then complete W03W08 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.