# 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/-`, в 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 (если работал в паре с Claude) ``` ### Кодстайл - **C#**: дефолтный .NET-стиль. Один файл — один класс. Async/await везде где I/O. EF-проекции через `.ProjectToType(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//MyEntity.cs` (от `TenantEntity` если связана с org'ой). 2. DbSet + EntityTypeConfiguration в `src/food-market.infrastructure/Persistence/AppDbContext.cs` + `Configurations/`. 3. Migration в `Migrations/_.cs` — **ВРУЧНУЮ**, не через `dotnet ef migrations add`. Обязательны `[Migration("id")]` + `[DbContext(typeof(AppDbContext))]` (memory: `feedback_ef_migrations`). 4. DTO + Validator в `src/food-market.application//`. 5. Mapster TypeAdapterConfig в `MapsterConfig.Build()` если есть нетривиальное проецирование. 6. Controller в `src/food-market.api/Controllers//`. Atomic per endpoint, multi-tenant через query-filter (автоматически). 7. Integration-тест в `tests/food-market.IntegrationTests/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! 🚀