Revised the CLAUDE.md file to enhance clarity and accuracy in the project description. Updated terminology to reflect current functionality, including changes in user roles and media processing. Improved the architecture section by detailing the domain model and dependencies, ensuring a clearer understanding of the system's structure. Added references to documentation for better guidance on subsystem specifications.
11 KiB
CLAUDE.md
Инструкции для Claude Code при работе в этом репозитории.
Что это
TeleWave — сервис онлайн-каналов: зритель смотрит сетку каналов, видео отдаётся из хранилища на сервере. Админ ведёт библиотеку, каналы и эфир.
Работает: аутентификация, роли, пользователи; библиотека шоу/серий, коллекции, жанры, метаданные
(TMDb/OMDb), обработка медиа (ffmpeg → HLS), изображения; группы, шаблон сетки, стыки и заставки,
автосборка по профилям, обмен конфигурацией файлом и запросом к ИИ; генерация ленты, live-раздача,
публичный просмотр, статистика хранилища. Telegram-бот сознательно не делаем. Конвенции — зеркало
PnvPanel (тот же автор).
Спеки в docs/ — источник правды по домену, читай до правок в подсистеме:
tv-scheduler-architecture.md (группы, сетка, слоты, стыки,
заставки, планировщик, автосборка, обмен конфигурацией — главный документ),
media-storage-and-streaming.md и
server-storage-setup.md (медиа и хранилище).
Стек
- Backend: C# / .NET 10, ASP.NET Core Minimal API, Clean Architecture, CQRS через
LiteCqrs.Net(лёгкая альтернатива MediatR с явным разделением Command/Query — см. README). EF Core 10 + Npgsql, Identity + JWT, FluentValidation, Serilog, маппинг DTO вручную, OpenAPI + Scalar UI, тесты на xUnit + NSubstitute. - Frontend: React 19 + Vite + TS, TanStack Query/Router (файловые роуты,
routeTree.gen.tsгенерируется сборкой), shadcn поверх Radix + Tailwind v4, Zustand (только auth+тема), react-hook-form + zod, i18n (ru/en), pnpm + oxlint + prettier.
Архитектура — жёсткие правила
Зависимости строго внутрь: Api → Infrastructure → Application → Domain.
- Domain — без внешних зависимостей:
Auth,Library(шоу, серии, коллекции, жанры),Media,Images,Programming(группы, сетка, слоты, стыки + чистый планировщикPlanning),Broadcast(каналы, заставки, лента, live),Settings. Модель rich: приватные сеттеры, фабрикиCreate, поведенческие методы. - Application — CQRS-хендлеры, DTO, валидаторы и порты (
Common/Interfaces/I*.cs:IAppDbContext,ICurrentUser,IMediaProcessor,IMediaStorage,IBumperRenderer,IMetadataProvider,IImageStore,IStorageInspector, …). Зависит только от Domain: никакихNpgsql/AspNetCore.Identity, лишь их абстракции. - Infrastructure — реализации портов: EF Core (
AppDbContext : IdentityDbContext<AppUser, AppRole, Guid>, конфигурации вPersistence/Configurations), ffmpeg, хранилище, метаданные, идемпотентныйDbInitializer(роли + админ из envAdminSeed__*). - Api — Minimal API (
Endpoints/*Endpoints.cs), middleware, DI composition root (Program.cs).
Обязательно:
- Команды меняют состояние в транзакции (
UnitOfWorkBehavior); запросы только читают. Диспетчер —ISender/ICommandHandler/IQueryHandler, регистрация вApplication/DependencyInjection.cs. - Управляемые ошибки — через
Result<T>(Common/Models/Result.cs), не исключениями. Валидация — FluentValidation черезValidationBehavior; хендлер не перепроверяет формат ввода. - Всё I/O асинхронно,
CancellationTokenпробрасывается до EF/HTTP; никаких.Result/.Wait(). Nullable включён,TreatWarningsAsErrors=true— предупреждения анализаторов не игнорировать. - Планировщик (
Domain/Programming/Planning) — чистая функция: входPlanningInput, никаких запросов и часов внутри. Данные под него собираетApplication/Programming/Planning.
Инварианты, которые легко нарушить
- Роли динамические, у пользователя ровно одна; системные
admin/user(IsSystem=true) не переименовать и не удалить, последнего админа не разжаловать, себя не заблокировать и не удалить. - Регистрация открытая (создаётся
user, токены сразу); понадобится модерация — заводи отдельный флаг, не переиспользуйIsBlocked. Вход поUserName, email и SMTP не используются; JWT access + refresh в httpOnlytw_refresh_tokenс обнаружением повторного использования отозванного. - Правка сетки эфир не двигает: команда поднимает ревизию шаблона, ленту пересобирает применение.
- Вещательные сутки начинаются с
Channel.DayStartTime(06:00), сетка задаётся во времени канала (UtcOffsetMinutes), в базе всё в UTC.
Единый контейнер
- Один образ: Api раздаёт REST (
/api) и статику SPA изwwwroot(fallback наindex.html), один origin, база API — относительный/api. Multi-stage Dockerfile: node → dotnet sdk → aspnet. Отдельный nginx для статики не вводить — ломает требование единого контейнера. - Работает под непривилегированным
USER $APP_UID(uid/gid 1654) статически, без gosu/entrypoint: права на bind-mount выставляет оператор (docs/server-storage-setup.md§ 5). Data Protection не заводим — шифруемых секретов на диске нет. TLS внешний:appотдаёт HTTP и доверяетX-Forwarded-*. - docker-compose: только
app. PostgreSQL внешний (ConnectionStrings__Defaultиз.env), база и пользователь создаются заранее вручную; миграции применяются на старте (ApplyMigrationsAsync), правCREATEDBне нужно.
Соглашения по коду
<Verb><Noun>Command/<Get|List><Noun>Query+Handler/Validator(где есть что проверить), папки по фичам (Auth/Login/,Programming/Templates/Generate/, …). Один публичный тип на файл = имя файла, кромеBody— тела Api-эндпоинтов, не совпадающие с командой 1:1 (sealed recordвнизу файла эндпоинта). DTO — суффиксDto.- Ошибки — каталоги
XErrors(Error.Validation/NotFound/Conflict/…), наружу единымapplication/problem+json(Api/Common/ResultExtensions.cs). Секреты не логировать. - Изображения — только через реестр
Image(Domain/Images, галереяfeatures/admin/images): картинка хранится какImageIdи выбирается контроломImageGallery/GalleryBrowser, своих файловых полей не заводить. Файлы —images/{id}{ext}, отдаются по/api/images/{id}. - Фронт: фича = папка в
src/features/admin/<фича>; тексты только через i18n, ключи вru.tsиen.ts. - Комментарии объясняют почему, а не что; по-русски, как в существующем коде.
Команды
Backend (из backend/):
dotnet build
dotnet csharpier format . # только через dotnet (версия из .config/); в CI — csharpier check
dotnet test tests/TeleWave.Domain.Tests # по одному проекту: MSBuild не берёт несколько
dotnet test tests/TeleWave.Application.Tests
dotnet test tests/TeleWave.Integration.Tests # Testcontainers; без Docker пропускаются
dotnet run --project src/TeleWave.Api
dotnet ef migrations add <Name> --project src/TeleWave.Infrastructure --startup-project src/TeleWave.Api
Frontend (из frontend/):
pnpm install && pnpm dev
pnpm lint && pnpm typecheck && pnpm build
pnpm format && pnpm format:check # CI падает на неотформатированном — прогоняй после правок
Инфраструктура: docker compose up -d --build (только api; postgres внешний). Окружение — Windows,
оболочка PowerShell; для POSIX-скриптов есть Bash-инструмент.
Рабочие принципы
- Базовый срез реализован — правь его по месту. Новые крупные направления с непринятыми решениями (многоэкземплярность, транскод-профили, новые подсистемы) — только после сверки с пользователем. При неоднозначности — вопрос, а не предположение.
- Меняешь поведение подсистемы — обнови её спеку в
docs/тем же заходом. - Соблюдай границы слоёв — главный инвариант проекта.
- Не коммить и не пуши без явной просьбы.
- Отвечай пользователю на русском.