Files
LiveServer-M1/CLAUDE.md
joylessorchid cb589b540a chore: add Redis/PgBouncer readiness checks to setup.sh + post-change checklist rule to CLAUDE.md
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>
2026-03-22 14:21:40 +03:00

199 lines
9.1 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.
# 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