setup.sh now waits for Redis PONG and PgBouncer pg_isready before running Prisma migrations. CLAUDE.md gets mandatory post-change checklist ensuring setup.sh, README.md, PROMPT.md, .env.example stay in sync after every change. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
199 lines
9.1 KiB
Markdown
199 lines
9.1 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Project Overview
|
||
|
||
**LiveServer-M1** — образовательная видеоконференц-платформа на базе LiveKit.
|
||
|
||
Ключевые фичи:
|
||
- AI-ассистент: авто-подключение к комнатам, real-time транскрипция (Deepgram), суммаризация лекций (OpenAI GPT)
|
||
- Защита от Zoom-bombing: lobby/waiting room, PIN-коды, kick/ban по session fingerprint, panic button
|
||
- Пост-лекционная панель: чат, файлы, транскрипт, AI-саммари, экспорт в PDF/Google Drive
|
||
|
||
Полная спецификация: **`PROMPT.md`**
|
||
|
||
## Tech Stack
|
||
|
||
| Слой | Технологии |
|
||
|------|-----------|
|
||
| Frontend | Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS v4 |
|
||
| Video | LiveKit Cloud → self-hosted, `@livekit/components-react` |
|
||
| Backend | Next.js Route Handlers, `livekit-server-sdk` |
|
||
| Auth | `better-auth` + Prisma adapter |
|
||
| AI Agent | Python, `livekit-agents`, `livekit-plugins-deepgram` (STT), `livekit-plugins-openai` (LLM) |
|
||
| DB | PostgreSQL + Prisma 7 ORM + PgBouncer (connection pooling) |
|
||
| Cache/PubSub | Redis 7 (rate limiting, lobby pub/sub, chat real-time, caching) |
|
||
| Storage | MinIO (S3-compatible) |
|
||
| Proxy | Traefik v3 + Let's Encrypt (prod only) |
|
||
|
||
## Architecture
|
||
|
||
```
|
||
├── src/
|
||
│ ├── app/
|
||
│ │ ├── api/ # 15 API route handlers
|
||
│ │ │ ├── auth/[...all]/ # better-auth catch-all
|
||
│ │ │ ├── rooms/ # CRUD, by-code lookup
|
||
│ │ │ ├── rooms/[roomId]/ # join, lobby, lobby/stream (SSE), chat, files, moderate, hand-raise, start, end
|
||
│ │ │ └── livekit/ # token generation, webhook receiver
|
||
│ │ ├── (dashboard)/ # Host/Admin pages
|
||
│ │ ├── join/[code]/ # Guest entry
|
||
│ │ ├── room/[code]/ # Video room (LiveKit)
|
||
│ │ ├── login/ & register/ # Auth pages
|
||
│ │ └── page.tsx # Landing
|
||
│ ├── components/
|
||
│ │ ├── room/ # ChatPanel, ModerationPanel
|
||
│ │ └── lobby/ # WaitingRoom, LobbyManager
|
||
│ ├── lib/ # prisma, auth, auth-helpers, livekit, redis, rate-limit, lobby-pubsub, chat-pubsub
|
||
│ ├── middleware.ts # Dev protection (DEV_ACCESS_KEY, ALLOWED_IPS)
|
||
│ └── types/
|
||
├── ai-agent/ # Python LiveKit Agent
|
||
├── prisma/schema.prisma # 9 models, 3 enums
|
||
├── docker-compose.yml # Base: postgres, minio, redis, pgbouncer, ai-agent, app
|
||
├── docker-compose.override.yml # Local dev: direct ports, no SSL
|
||
├── docker-compose.prod.yml # Traefik + Let's Encrypt
|
||
└── Dockerfile # Multi-stage Next.js standalone build
|
||
```
|
||
|
||
### Key Data Flows
|
||
|
||
1. **Guest join (with lobby):**
|
||
Guest → POST `/api/rooms/[id]/join` → LobbyEntry(PENDING) → SSE via Redis pub/sub → Host approves → LiveKit token → connect
|
||
|
||
2. **Real-time chat:**
|
||
POST message → DB + Redis PUBLISH → SSE `/api/rooms/[id]/chat/stream` → instant delivery to all participants
|
||
|
||
3. **Real-time transcription:**
|
||
Audio tracks → AI Agent (Deepgram STT) → DataChannel → Live captions
|
||
|
||
4. **Post-lecture (`room_finished` webhook):**
|
||
Transcript → OpenAI GPT → LectureArtifact → `/lectures/[id]`
|
||
|
||
### User Roles
|
||
|
||
- **ADMIN** — global panel, all rooms monitoring
|
||
- **HOST** — room creation, moderation, security
|
||
- **GUEST** — join by link, no registration required
|
||
|
||
### Security Layers
|
||
|
||
- `sessionFingerprint` (required) for bans — IP is secondary only
|
||
- PIN hashed with bcrypt, rate-limited (5 attempts/min per IP)
|
||
- Chat/files auth: verified via ParticipantHistory
|
||
- SSE lobby: verified against existing LobbyEntry
|
||
- Token generation: only room owner can get LiveKit token
|
||
- `DEV_ACCESS_KEY` middleware: protects local dev from network access
|
||
- LiveKit webhook: signature verification via `WebhookReceiver`
|
||
|
||
## Performance Architecture
|
||
|
||
```
|
||
Clients → Traefik (LB) → Next.js (x2 replicas) → PgBouncer (pool 25, max 500) → PostgreSQL
|
||
→ Redis (pub/sub, cache, rate limit)
|
||
→ LiveKit (video/audio SFU)
|
||
```
|
||
|
||
- **Redis pub/sub** replaces DB polling for lobby SSE and chat — instant delivery (<10ms)
|
||
- **PgBouncer** multiplexes 500 client connections into 25 real PostgreSQL connections
|
||
- **Chat SSE** via Redis pub/sub + optimistic UI on client — messages appear before server confirms
|
||
- **Rate limiting** via Redis INCR+EXPIRE — works across multiple app replicas
|
||
- **Chat cache** in Redis (10s TTL) — reduces DB reads during active rooms
|
||
- **Prisma select** — only fetch needed columns, not full rows
|
||
|
||
## Commands
|
||
|
||
```bash
|
||
# Dev
|
||
npm run dev # Next.js dev server (localhost:3000)
|
||
docker compose up -d postgres minio redis # DB + Storage + Redis
|
||
npm run lint # TypeScript type-check (tsc --noEmit)
|
||
|
||
# Database
|
||
npx prisma migrate dev # Create + apply migration
|
||
npx prisma db push # Quick schema sync (no migration)
|
||
npx prisma studio # DB GUI
|
||
npx prisma generate # Regenerate Prisma Client
|
||
|
||
# Build
|
||
npm run build -- --webpack # Production build (Webpack, not Turbopack — WASM limitation on Windows)
|
||
|
||
# Docker (full stack)
|
||
docker compose up -d --build # Local
|
||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build # Prod (with Traefik)
|
||
|
||
# AI Agent
|
||
cd ai-agent && python main.py start
|
||
```
|
||
|
||
## Environment Variables
|
||
|
||
See `.env.example` for all variables. Key ones:
|
||
|
||
```env
|
||
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/liveserver
|
||
LIVEKIT_URL=wss://...
|
||
LIVEKIT_API_KEY=...
|
||
LIVEKIT_API_SECRET=...
|
||
BETTER_AUTH_SECRET=...
|
||
|
||
# Local dev protection (when DOMAIN is not set)
|
||
DEV_ACCESS_KEY=mySecretKey123
|
||
# ALLOWED_IPS=192.168.1.10,192.168.1.11
|
||
|
||
# Production
|
||
# DOMAIN=live.example.com
|
||
# ACME_EMAIL=admin@example.com
|
||
```
|
||
|
||
## Deployment Modes
|
||
|
||
| Mode | Command | Description |
|
||
|------|---------|-------------|
|
||
| **Local dev** | `docker compose up -d` | Direct ports (3000, 5432, 9000). `docker-compose.override.yml` auto-applied |
|
||
| **Production** | `docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d` | Traefik reverse proxy, auto SSL via Let's Encrypt |
|
||
|
||
## Prisma 7 Notes
|
||
|
||
- `prisma.config.ts` in project root (required by Prisma 7)
|
||
- `datasourceUrl` passed via PrismaClient constructor, not in schema
|
||
- Schema has no `url` in datasource block — only `provider`
|
||
- Use `-- --webpack` flag for `next build` on Windows (Turbopack WASM issue)
|
||
|
||
## Agent Orchestration
|
||
|
||
| Task | Agent |
|
||
|------|-------|
|
||
| API routes, backend logic | `backend-architect` |
|
||
| React components, LiveKit UI | `frontend-developer` |
|
||
| DB schema, indexes, queries | `database-optimizer` |
|
||
| Python AI Agent, Deepgram/OpenAI | `ai-engineer` |
|
||
| System architecture | `software-architect` |
|
||
| UI design, components | `ui-designer` |
|
||
| UX flows, accessibility | `ux-architect` |
|
||
| Code review before commit | `code-reviewer` |
|
||
|
||
**Rule:** for tasks spanning 2+ layers — use `agents-orchestrator`.
|
||
|
||
## Post-Change Checklist (ОБЯЗАТЕЛЬНО)
|
||
|
||
После **каждого** изменения кода или конфигурации Claude **обязан** выполнить:
|
||
|
||
1. **Обновить `CLAUDE.md`** — если изменились архитектура, endpoints, модели, команды, стек или conventions
|
||
2. **Проверить `setup.sh`** — все новые сервисы/зависимости должны быть в скрипте (readiness checks, .env переменные, docker compose команды)
|
||
3. **Проверить `README.md`** — инструкции, API таблицы, структура проекта должны отражать текущее состояние
|
||
4. **Проверить `PROMPT.md`** — спецификация должна соответствовать реализации
|
||
5. **Проверить `.env.example`** — все новые переменные окружения должны быть задокументированы
|
||
|
||
Не пропускать этот чеклист. Если изменение не затрагивает файл — просто подтвердить что файл актуален.
|
||
|
||
## Conventions
|
||
|
||
- Communication language: Russian
|
||
- Guests don't register, but `user_id` reserved for future LMS
|
||
- `sessionId` (UUID) is the cross-cutting key linking LobbyEntry, ParticipantHistory, ChatMessage, SharedFile for guests
|
||
- `Room.code` is the user-facing invite code (not the DB id)
|
||
- Files store `fileKey` (S3 object key), not full URLs
|
||
- `LectureArtifact` is 1:1 with Room
|
||
- All cascade deletes: removing Room removes all related data
|