food-market/docs/ONBOARDING.md
nns 439301b92d
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
docs: ONBOARDING sprint-history до 28 + quality marathon summary
2026-06-09 03:42:51 +05:00

276 lines
14 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.

# Onboarding для нового разработчика food-market
Этот документ — путь от «клонировал репо» до «открыл первый PR» за 3 дня.
Если что-то не сходится с реальностью — это **баг документации**,
отредактируй и оставь PR.
## День 1 — установка и первый запуск
### Что нужно
- macOS / Linux. Windows только для POS WPF (см. отдельно ниже).
- .NET 8 SDK (точная версия из `global.json``dotnet --list-sdks`
должен показывать её; если нет — `winget install Microsoft.DotNet.SDK.8`
/ `brew install dotnet@8`).
- Node.js 20+ (`nvm install 20 && nvm use 20`).
- pnpm 9+ (`npm i -g pnpm`).
- PostgreSQL 14+ (на macOS: `brew install postgresql@14 && brew services start postgresql@14`).
- git, curl, python3 (для скриптов в `tests/e2e/`).
- Docker для интеграционных тестов (Testcontainers) и stage-deploy.
### Установка проекта
```bash
git clone http://192.168.1.193:3000/nns/food-market.git
cd food-market
# БД для dev — пустая, инициируется миграциями автоматически.
createdb -U $USER food_market
# Backend
dotnet restore
dotnet build food-market.sln -c Debug --nologo
# Web frontend
cd src/food-market.web && pnpm install && cd ../..
```
### Запуск
```bash
# Терминал 1: API
ASPNETCORE_ENVIRONMENT=Development dotnet run --project src/food-market.api
# → http://localhost:5081, Swagger на /swagger
# Терминал 2: Web SPA
cd src/food-market.web && pnpm dev
# → http://localhost:5173
```
### Проверка что работает
```bash
# Health
curl http://localhost:5081/health/ready
# Зарегистрируйся
curl -X POST http://localhost:5081/api/auth/signup \
-H "Content-Type: application/json" \
-d '{"organizationName":"DevOrg","email":"dev@local.test","password":"DevPass123!","phone":"+77001234567"}'
# Логин и получи токен
TOKEN=$(curl -sX POST http://localhost:5081/connect/token \
-d 'grant_type=password&username=dev@local.test&password=DevPass123!&client_id=food-market-web&scope=openid profile email roles api offline_access' \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])')
# Что я могу
curl -sH "Authorization: Bearer $TOKEN" http://localhost:5081/api/me | python3 -m json.tool
```
### Тесты
```bash
# Unit
dotnet test tests/food-market.UnitTests --nologo
# Integration (нужен Docker — Testcontainers поднимает Postgres-контейнер)
dotnet test tests/food-market.IntegrationTests --nologo
# E2E (Playwright против локального API)
cd tests/e2e
E2E_ADMIN_URL=http://localhost:5081 ./run.sh stage-smoke
```
## День 2 — где что лежит
### Структура (укрупнённо)
```
food-market/
├── src/
│ ├── food-market.domain/ — POCO + enum'ы + интерфейсы. Без EF, без ASP.NET.
│ ├── food-market.application/ — DTO, FluentValidation, MediatR-handler'ы, Mapster config.
│ ├── food-market.infrastructure/ — EF Core, миграции, Identity, OpenIddict storage.
│ ├── food-market.api/ — Controllers, middleware, Hangfire jobs, OpenIddict server.
│ ├── food-market.web/ — React 19 + Vite SPA админки (admin.food-market.kz).
│ ├── food-market.public/ — Astro marketing-сайт (food-market.kz).
│ ├── food-market.shared/ — DTO-контракты сервер↔POS.
│ ├── food-market.pos.core/ — POS-логика (UI-agnostic).
│ └── food-market.pos/ — WPF (net8.0-windows; собирается на любой OS).
├── tests/
│ ├── food-market.UnitTests/ — xUnit + InMemory EF (быстрые юниты).
│ ├── food-market.IntegrationTests/— xUnit + Testcontainers Postgres (через WebApplicationFactory).
│ ├── e2e/ — Playwright (TS) + ad-hoc Python smoke-скрипты.
│ └── load/ — k6 (нагрузочные).
├── deploy/ — Dockerfile.{api,web,public}, compose, nginx, скрипты (prod-deploy/rollback/smoke/anonymize/swagger-diff).
├── docs/ — markdown (этот файл — `ONBOARDING.md`, плюс ARCHITECTURE/RUNBOOK/etc).
└── food-market.sln
```
### Что почитать в первую очередь
Порядок имеет значение — от general к specific:
1. **[ARCHITECTURE.md](ARCHITECTURE.md)** — общая картина: слои, deployment-топология, ключевые потоки, что реализовано / scaffolding / не реализовано (после 22 спринтов).
2. **[glossary.md](glossary.md)** — все доменные термины (Tenant / Organization / Stock / RetailSale / …) с ссылками на классы.
3. **[MULTI-TENANCY.md](MULTI-TENANCY.md)** — query-filter, SuperAdmin override, как не утечь cross-org.
4. **[DEVELOPER-GUIDE.md](DEVELOPER-GUIDE.md)** — паттерны (CQRS-like, MediatR, валидаторы, Mapster), стиль кода, как добавлять новые endpoint'ы.
5. **[api-reference.md](api-reference.md)** — auto-generated список всех 190+ endpoint'ов (обновляется weekly через Hangfire).
6. **[error-codes.md](error-codes.md)** — каталог HTTP-кодов для humanizeError на фронте.
7. **[secrets.md](secrets.md)** — env-vars + где хранятся секреты.
8. **[observability.md](observability.md)** — Prometheus метрики, Serilog, /health.
9. **[RUNBOOK.md](RUNBOOK.md)** — как разруливать инциденты («api не стартует», «остатки разъехались», и т.п.).
10. **[performance-baseline.md](performance-baseline.md)** — k6 baseline + что НЕ масштабируется.
### Sprint-history
Хронология фич: `docs/sprint1-progress.md``docs/sprint28-progress.md`.
Каждый — что было сделано + цифры. Полезно когда видишь странное имя
файла и хочешь понять «когда и зачем».
После Sprint 24 — серия "quality marathon":
- **25** — hourly quality-watchdog (`~/quality-watchdog.sh`) с
auto-incident loop в Server-Claude очередь.
- **26** — flaky-test detection (`tests/regression/find-flaky.sh`) +
observability stack (Grafana JSON + Prometheus alerts + RUNBOOK
action-per-alert).
- **27** — cross-feature integration tests (`tests/integration/`) +
4-часовой soak (k6) + crash recovery (11.7s ≤ 30s SLA).
- **28** — overnight maintenance: api-reference auto-gen fix
(195→240 endpoints), HSTS header на stage, integration spec
gap-fill (1C-CSV import, GDPR export, security headers).
### Тестовый стенд
- **Stage**: `https://test.admin.food-market.kz``~/deploy-stage.sh` собирает образ и катит. Подробности в [stage-access.md](stage-access.md).
- **Prod**: `https://admin.food-market.kz`НЕ деплоится автоматически (Sprint 21 toolchain готов, см. `deploy/prod-deploy.sh`, но реальный сервер не настроен).
### Git workflow
- Origin — Forgejo на `http://192.168.1.193:3000/nns/food-market.git`.
GitHub — mirror.
- Никаких force-push'ей в main (после первого тэга).
- Branch для серьёзных фич: `feat/<sprint>-<short-name>`, в Pull Request →
Squash & Merge.
- Каждый коммит на собственной фиче — `feat(scope): subject` (см.
`git log --oneline` для примеров).
## День 3 — первый PR
### Найти первую задачу
- `grep -rn "TODO\|FIXME" src/` — около 30 живых TODO. Самые маленькие
обычно UX-полировка (i18n, copy, validation message).
- `docs/sprintNN-progress.md` последнего спринта → раздел «Открытые TODO».
- В Forgejo Issues (если есть): bug-001..004 в `tests/e2e/reports/bugs/`
— некоторые фиксы уже сделаны, остаются follow-up'ы.
- Слабый шаг: посмотри `docs/performance-baseline.md` раздел «Сводка:
что нужно поправить» — там список задач со статусом ✅/⚠️/❌.
### Что сделать перед PR
1. `git fetch origin && git rebase origin/main` (memory: `feedback_serialize_edits`
мы один-коммитящий-за-раз; не делай параллельных правок).
2. `dotnet build` + `dotnet test` (unit + integration) — должны быть зелёные.
3. `pnpm -C src/food-market.web exec tsc --noEmit` — TS clean.
4. Локальный smoke если правил controller'ы: запусти API + `curl` на затронутый
endpoint.
5. Для UI: открой `/login` локально, проверь что страница работает.
### Шаблон PR-сообщения
```
<тип>(scope): краткое описание
Что: …
Зачем: …
Как тестировал: …
Связанные issue/sprint: …
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> (если работал в паре с Claude)
```
### Кодстайл
- **C#**: дефолтный .NET-стиль. Один файл — один класс. Async/await везде
где I/O. EF-проекции через `.ProjectToType<TDto>(MapsterConfig.Config)`
для новых endpoint'ов (Sprint 20+).
- **TS**: prettier+eslint конфиг в `src/food-market.web`. Hooks naming
`useFoo`. Server-state — TanStack Query, не useState.
- **CSS**: только Tailwind utility-classes. Никаких inline styles.
- **Комментарии**: только если объясняют **почему**, не **что**. Если
переписал паттерн — оставь reference на `[memory:feedback_serialize_edits]`
или sprint-doc.
## FAQ
### Q: API не стартует, ругается на global.json
`dotnet --list-sdks` должен содержать ровно ту версию что в `global.json`
(8.0.417). Если нет — установи SDK. **НЕ редактируй global.json** — это
сломает CI и другие dev-машины.
### Q: Integration-тесты падают с "Cannot find docker daemon"
Включи Docker Desktop / `sudo systemctl start docker`. Testcontainers
тащит `postgres:16-alpine` (один раз, потом из кеша).
### Q: Web стартует но не видит API
Проверь что `src/food-market.web/vite.config.ts` proxy указывает на
`http://localhost:5081`. Если порт API изменился — обнови.
### Q: Сертификат OpenIddict не создаётся
Dev-режим: `App_Data/` должен быть writable. Прод: см.
[openiddict-keys.md](openiddict-keys.md).
### Q: Как добавить новую сущность
Шаги (псевдо-flow):
1. POCO в `src/food-market.domain/<Area>/MyEntity.cs` (от `TenantEntity` если связана с org'ой).
2. DbSet + EntityTypeConfiguration в `src/food-market.infrastructure/Persistence/AppDbContext.cs` + `Configurations/`.
3. Migration в `Migrations/<timestamp>_<name>.cs`**ВРУЧНУЮ**, не через `dotnet ef migrations add`. Обязательны `[Migration("id")]` + `[DbContext(typeof(AppDbContext))]` (memory: `feedback_ef_migrations`).
4. DTO + Validator в `src/food-market.application/<Area>/`.
5. Mapster TypeAdapterConfig в `MapsterConfig.Build()` если есть нетривиальное проецирование.
6. Controller в `src/food-market.api/Controllers/<Area>/`. Atomic per endpoint, multi-tenant через query-filter (автоматически).
7. Integration-тест в `tests/food-market.IntegrationTests/<Area>Tests.cs` — минимум один happy-path.
8. Если возвращаешь в Web — обновить `src/food-market.web/src/lib/types.ts`.
### Q: Как запустить нагрузочный тест
```bash
cd tests/load
BASE_URL=http://localhost:5081 k6 run retail-sales-parallel.js
# или против stage:
BASE_URL=https://test.admin.food-market.kz k6 run signup-burst.js
```
См. [performance-baseline.md](performance-baseline.md) для интерпретации цифр.
### Q: Где POS WPF тестировать
Нужен Windows. На macOS/Linux можно собрать (`dotnet build src/food-market.pos`)
но не запустить UI. Тесты POS-логики в `src/food-market.pos.core`
кроссплатформенные.
### Q: Хочу понять как работает …
- **Tenant isolation** → `MULTI-TENANCY.md` + `AppDbContext.ApplyTenantFilter`.
- **OpenIddict** → `openiddict-keys.md` + Program.cs `AddOpenIddict()`.
- **POS sync с idempotency** → `food-market.pos.core` + `PosBatchAckController`.
- **ОФД** → `ofd-integration.md` + `Infrastructure/Fiscal/`.
- **CSV import** → `imports.md` + `ProductsController.ImportCsv`.
- **GDPR org export** → `OrgExportJob` (Sprint 22).
## Где спрашивать
- Forgejo issues — для багов и feature requests.
- В коде — поиск по docstring (комментарии часто отвечают «почему сделано
именно так»).
- Sprint-progress файлы — там цифры и trade-off'ы зафиксированы.
- Memory-файлы Claude Code в `~/.claude/projects/-home-nns-food-market/memory/`
— что-то типа CHANGELOG развития, более информально.
Welcome! 🚀