Initial commit: site monorepo with API, web, and infra.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+220
@@ -0,0 +1,220 @@
|
||||
# Структура и архитектура
|
||||
|
||||
Monorepo-lite: статический лендинг + React SPA + FastAPI + PostgreSQL + Redis + MinIO.
|
||||
Если вы искали микросервисы на Kubernetes — это другой коридор.
|
||||
|
||||
## Стек
|
||||
|
||||
| Слой | Технологии |
|
||||
|------|------------|
|
||||
| Frontend | React 19, TS, Vite, React Router, TanStack Query, Zustand, RHF+Zod, Ant Design |
|
||||
| Backend | FastAPI, SQLAlchemy 2, Alembic, Pydantic v2 |
|
||||
| Данные | PostgreSQL 16, Redis 7, MinIO |
|
||||
| Инфра | Docker Compose, Nginx, GitHub Actions |
|
||||
| Качество | Vitest, Playwright, pytest (≥90% / ≥85% cov) |
|
||||
|
||||
## Дерево репозитория
|
||||
|
||||
```
|
||||
site/
|
||||
├── apps/
|
||||
│ ├── api/ # Backend
|
||||
│ │ ├── app/
|
||||
│ │ │ ├── core/ # crypto, jwt_denylist, redis, install_secrets…
|
||||
│ │ │ ├── db/ # models, seed, migrations helpers
|
||||
│ │ │ └── modules/ # auth, users, content, admin, media, test
|
||||
│ │ ├── migrations/ # Alembic
|
||||
│ │ ├── scripts/ # bootstrap_install.py, docker_entrypoint.py
|
||||
│ │ ├── tests/
|
||||
│ │ └── data/
|
||||
│ │ ├── secrets/ # install.env (gitignore!)
|
||||
│ │ └── logs/ # server.log, admin-audit.jsonl (gitignore)
|
||||
│ └── web/
|
||||
│ ├── index.html # лендинг /
|
||||
│ ├── app.html # SPA entry
|
||||
│ ├── main/ # статика лендинга (CSS/JS/video)
|
||||
│ ├── src/
|
||||
│ │ ├── app/ # router, guards
|
||||
│ │ ├── modules/ # auth, profile, admin, content, landing
|
||||
│ │ ├── pages/
|
||||
│ │ └── shared/ # api client, ui
|
||||
│ └── e2e/ # Playwright
|
||||
├── packages/ # eslint-config, shared-types (target)
|
||||
├── infra/
|
||||
│ ├── docker/ # staging/prod compose, deploy.sh
|
||||
│ ├── nginx/ # default.conf, default.tls.conf
|
||||
│ ├── k6/ # load test §17.2
|
||||
│ └── scripts/ # backup, health, smoke
|
||||
├── docs/ # вы здесь
|
||||
├── docker-compose.yml # dev
|
||||
└── docker-compose.test.yml # CI / E2E
|
||||
```
|
||||
|
||||
## Runtime
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph browser [Браузер]
|
||||
L[index.html /]
|
||||
S[app.html SPA]
|
||||
end
|
||||
subgraph edge [Nginx :80/:443]
|
||||
N[TLS + headers]
|
||||
end
|
||||
subgraph internal [Docker internal]
|
||||
W[web]
|
||||
A[api]
|
||||
PG[(PostgreSQL)]
|
||||
R[(Redis)]
|
||||
M[(MinIO)]
|
||||
end
|
||||
L --> N
|
||||
S --> N
|
||||
N --> W
|
||||
N --> A
|
||||
A --> PG
|
||||
A --> R
|
||||
A --> M
|
||||
```
|
||||
|
||||
**Prod/staging:** наружу только nginx. Postgres, Redis, MinIO — без host-портов.
|
||||
|
||||
## Frontend
|
||||
|
||||
### Два входа (dual-entry)
|
||||
|
||||
| Entry | URL | Содержимое |
|
||||
|-------|-----|------------|
|
||||
| `index.html` | `/` | Маркетинговый лендинг (`main/`) |
|
||||
| `app.html` | `/login`, `/admin`, … | React SPA |
|
||||
|
||||
Vite переписывает SPA-пути на `app.html` (`vite.main-static.ts`).
|
||||
|
||||
### Маршруты
|
||||
|
||||
| Путь | Guard | Кто |
|
||||
|------|-------|-----|
|
||||
| `/` | — | все |
|
||||
| `/login`, `/register`, `/forgot-password`, `/reset-password` | GuestGuard | гости |
|
||||
| `/verify`, `/pages/:slug` | — | публично |
|
||||
| `/profile` | AuthGuard | user |
|
||||
| `/admin` | AdminGuard | admin |
|
||||
|
||||
**Auth UX:**
|
||||
- Access JWT — только в памяти (Zustand), не localStorage
|
||||
- Refresh — HttpOnly cookie, `Path=/api/v1/auth`
|
||||
- После login: admin → `/admin`, user → `/profile`
|
||||
- Кнопка «На сайт» в админке — **полный** переход на `/` (не React Router)
|
||||
|
||||
### Админка (WESP-style)
|
||||
|
||||
| Раздел | Кому | Что |
|
||||
|--------|------|-----|
|
||||
| Users | admin | CRUD пользователей |
|
||||
| Content | admin | CMS |
|
||||
| Security | superuser | runtime settings, Install Secrets |
|
||||
| Diagnostics | superuser | health checks |
|
||||
| Activity | admin | audit feed, server log |
|
||||
|
||||
Тема Light/Dark — `localStorage.wespAdminTheme`. Auth-страницы — zootech-карточки (`#48816d`).
|
||||
|
||||
## Backend API
|
||||
|
||||
База: `/api/v1`
|
||||
|
||||
| Модуль | Эндпоинты (основное) |
|
||||
|--------|----------------------|
|
||||
| health | `GET /health` |
|
||||
| auth | register, login, logout, refresh, verify, forgot/reset password |
|
||||
| users | `GET/PATCH /me`, password, avatar |
|
||||
| content | публичные pages + admin CRUD |
|
||||
| admin | users, stats, settings, diagnostics, secrets, activity |
|
||||
| media | подписанные URL файлов |
|
||||
| test | `/test/emails/latest-token` — **только** E2E |
|
||||
|
||||
### Core (`apps/api/app/core/`)
|
||||
|
||||
| Модуль | Зачем |
|
||||
|--------|-------|
|
||||
| `crypto.py` | bcrypt, JWT, HMAC, token hash — одна точка |
|
||||
| `jwt_denylist.py` | мгновенный revoke access JWT |
|
||||
| `install_secrets.py` | bootstrap + lock |
|
||||
| `dependencies.py` | `get_current_user` |
|
||||
| `redis.py` | rate limit + JWT revoke |
|
||||
| `storage.py` | MinIO / memory |
|
||||
|
||||
## База данных
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o| user_profiles : has
|
||||
users ||--o{ refresh_tokens : owns
|
||||
users ||--o{ password_reset_tokens : owns
|
||||
users ||--o{ email_verification_tokens : owns
|
||||
```
|
||||
|
||||
Таблицы: `users`, `user_profiles`, `refresh_tokens`, `password_reset_tokens`, `email_verification_tokens`, `content_pages`.
|
||||
|
||||
```bash
|
||||
cd apps/api && alembic upgrade head
|
||||
```
|
||||
|
||||
CHECK constraints на `role`, `status`; superuser только при `role=admin`. Cleanup expired tokens при старте API.
|
||||
|
||||
### Seed: стандартные логины (dev)
|
||||
|
||||
| Email | Пароль | Env |
|
||||
|-------|--------|-----|
|
||||
| admin@compton.example | Admin1234 | `ADMIN_INITIAL_PASSWORD` |
|
||||
| ops@compton.example | OpsAdmin1234 | `DEMO_OPS_PASSWORD` |
|
||||
| user@compton.example | User1234 | `DEMO_USER_PASSWORD` |
|
||||
|
||||
CMS: `about`, `privacy`, `terms`. Подробнее — [deploy.md § логины](./deploy.md#стандартные-логины-dev).
|
||||
|
||||
## Переменные окружения (ключевые)
|
||||
|
||||
| Переменная | Где | Назначение |
|
||||
|------------|-----|------------|
|
||||
| `DATABASE_URL` | api | PostgreSQL |
|
||||
| `APP_ENV` | api | development / staging / production |
|
||||
| `JWT_ACCESS_SECRET`, `JWT_REFRESH_PEPPER` | api | токены |
|
||||
| `REDIS_URL` | api | rate limit + JWT revoke (prod обязателен) |
|
||||
| `SEED_DEMO_USERS` | api | `false` на staging/prod |
|
||||
| `ADMIN_INITIAL_PASSWORD` | api | пароль admin при seed (default `Admin1234`) |
|
||||
| `DEMO_USER_PASSWORD`, `DEMO_OPS_PASSWORD` | api | demo user/ops (только dev) |
|
||||
| `ENABLE_DOCS` | api | `false` на prod |
|
||||
| `ENABLE_TEST_ROUTES` | api | `true` только E2E |
|
||||
| `EMAIL_DELIVERY_MODE` | api | `memory` (dev) / `smtp` (prod) |
|
||||
| `STORAGE_MODE` | api | `s3` / `memory` |
|
||||
| `VITE_API_URL` | web | `http://api:8000` в Docker |
|
||||
| `VITE_USE_API_PROXY` | web | `true` в dev |
|
||||
|
||||
Полные примеры: `apps/api/.env.example`, `apps/api/.env.production.example`.
|
||||
|
||||
### Runtime settings
|
||||
|
||||
`apps/api/data/compton_settings.json` — toggles без секретов. Superuser: `GET/PATCH /admin/settings`. Env с тем же ключом = **lock** (нельзя менять из UI).
|
||||
|
||||
## Docker Compose
|
||||
|
||||
| Файл | Когда |
|
||||
|------|-------|
|
||||
| `docker-compose.yml` | локальная разработка |
|
||||
| `docker-compose.dev-ports.yml` | PG/Redis/MinIO на хост (DBeaver) |
|
||||
| `docker-compose.test.yml` | CI, Playwright |
|
||||
| `infra/docker/docker-compose.staging.yml` | staging VPS |
|
||||
| `infra/docker/docker-compose.prod.yml` | production VPS |
|
||||
|
||||
## CI
|
||||
|
||||
`.github/workflows/ci.yml`: lint → types → mypy → tests → audit → Bandit → gitleaks → E2E.
|
||||
|
||||
## Тесты
|
||||
|
||||
```bash
|
||||
pnpm --filter web test:ci
|
||||
cd apps/api && python -m pytest --cov=app --cov-fail-under=90
|
||||
pnpm --filter web e2e
|
||||
```
|
||||
|
||||
E2E поднимает API `:8001` + Vite `:5175`. Против staging: `E2E_BASE_URL=… E2E_START_API=false`.
|
||||
Reference in New Issue
Block a user