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

171 lines
11 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.
# Актуальный технический аудит 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 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 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.