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

9.1 KiB
Raw Blame History

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

# 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:

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