- IDEA.md: product vision from the user's perspective (input for design)
- Architecture, ADRs, data model, REST API overview
- Auth and roles, library storage (NFS, path regexes, scanner, search),
playback, recommendation system ("My Wave"), track upload queue
- Web, Android (offline, self-update), i18n, design system
- Testing strategy, Gitea Actions CI/CD, deployment, conventions, roadmap
- Clickable web/Android design prototypes and wave button variants
- .claude/launch.json to serve the prototypes locally
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
2.8 KiB
Markdown
43 lines
2.8 KiB
Markdown
# Соглашения
|
||
|
||
## Git
|
||
|
||
- Trunk-based: короткие ветки от `main`, merge через PR (squash).
|
||
- Имена веток: `feat/wave-moods`, `fix/scan-rename`, `chore/ci-cache`.
|
||
- Conventional Commits: `feat(wave): add running profile`, `fix(api): ...`. Скоупы: `api`, `agent`, `rec`, `web`,
|
||
`mobile`, `core`, `i18n`, `ci`, `deploy`, `docs`. Breaking change — `!` и раздел `BREAKING CHANGE:`.
|
||
- Изменение API = изменение `openapi.yaml` + регенерация клиентов в том же PR.
|
||
- Существенные архитектурные решения — новый ADR в [decisions.md](decisions.md).
|
||
|
||
## Go (`services/api`)
|
||
|
||
- `gofumpt`, `golangci-lint` (конфиг в репо). Ошибки оборачиваются `fmt.Errorf("...: %w", err)`;
|
||
доменные ошибки — типизированные (`ErrForbidden`, `ErrNotFound`) и маппятся в problem+json в одном месте.
|
||
- Контекст первым аргументом, без глобального состояния, зависимости через конструкторы (`NewService(repo, clock, ...)`).
|
||
- `clock` и генератор ID — интерфейсы (детерминированные тесты).
|
||
- SQL — только в `queries/*.sql` (sqlc), без ORM.
|
||
|
||
## Python (`services/recommender`)
|
||
|
||
- `uv`, `ruff` (lint + format), `mypy --strict`, Pydantic v2 для схем.
|
||
- Тяжёлые вычисления — `numpy`, без циклов Python по трекам.
|
||
- Конфиги контекстов и весов — YAML, валидируются Pydantic при старте.
|
||
|
||
## TypeScript
|
||
|
||
- `strict`, ESLint (flat config) + Prettier, без `any` (кроме сгенерированного кода).
|
||
- Общая логика — в `packages/core`, платформенная — только адаптеры в `apps/*`.
|
||
- Все строки UI — через i18n, хардкод текста ловит `eslint-plugin-i18next`.
|
||
|
||
## API
|
||
|
||
- `snake_case` в JSON, курсорная пагинация, problem+json с `code`.
|
||
- Новые поля — только дополнительные; удаление / переименование — через новую версию эндпоинта или депрекацию на один минорный релиз.
|
||
|
||
## Безопасность
|
||
|
||
- Секреты только через env / docker secrets, никогда в репозитории.
|
||
- Любой ввод, попадающий в команды (`mount`, `ffmpeg`), — только как отдельные аргументы `exec.Command`, без shell,
|
||
с whitelist-валидацией.
|
||
- Пути файлов — проверка, что итоговый путь внутри корня источника (`filepath.Rel` без `..`).
|