food-market/docs/sprint6-progress.md
nns 4675f38a0f
Some checks failed
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
Docker Public / Build + push Public (push) Has been cancelled
Docker Public / Deploy Public on stage (push) Has been cancelled
docs(sprint6): P2-4 done — все 5 пунктов выполнены, итог
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 17:59:47 +05:00

78 lines
5 KiB
Markdown
Raw Permalink 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.

# Спринт 6 — технический долг + 2FA
Автономная работа. После каждого пункта: `dotnet build` (SDK 8.0.126),
unit + integration тесты, коммит порцией, отметка `[x]`, коммит прогресса.
Не ломать auth. НЕ трогать global.json/POS/nginx/ОФД.
## Чек-лист
1. [x] **TD-6 Concurrency-токены на документах**`RowVersion` (PostgreSQL
`xmin` через `IsRowVersion`) на Supply/Demand/RetailSale/Transfer/Inventory.
Миграция. EF concurrency check. 409 при конфликте. Тест: два параллельных
PUT → один 200, другой 409.
✅ Postgres `xmin` (system column, без миграции) через
`UseXminAsConcurrencyToken` для 5 документов + `IVersionedEntity`-marker.
SuppliesController PUT принимает `Xmin`, сверяет, 409 при mismatch.
Bonus: Supply.Update перешёл на ExecuteDelete+AddRange (тот же fix что
в RetailSale). 2 интеграционных теста.
2. [x] **TD-2 FluentValidation**`FluentValidation.AspNetCore`, validator'ы
для SupplyInputDto/RetailSaleInputDto/ProductInputDto/CounterpartyInputDto/
EmployeeInputDto. Auto-register. Тесты на каждый.
Не используем deprecated `FluentValidation.AspNetCore` — текущая
рекомендация: `AddValidatorsFromAssemblyContaining<Program>()` + кастомный
`ValidationFilter` (IAsyncActionFilter). На неуспех → 400 ValidationProblemDetails.
5 validator'ов, 16 unit-тестов, 70 integration зелёных без регрессий.
3. [x] **TD-4 Структурные log-fields в Serilog**`LogContext.PushProperty`
в middleware: OrgId, UserId, CorrelationId. Бизнес-логи (Supply.Post,
Sale.Post) — структурно. `docs/logging.md`.
`LogEnrichmentMiddleware` после Authentication. CorrelationId из заголовка
`X-Correlation-ID` или генерируется. Business-логи на Supply.Post /
RetailSale.Post с именованными плейсхолдерами. `docs/logging.md`
с паттерном + анти-паттернами (string interpolation, PII в логах).
4. [x] **TD-1 CQRS partial (MediatR)**`CreateSupplyCommand`,
`PostRetailSaleCommand`, `GetSalesReportQuery`. Показать паттерн, не
полный рефакторинг. Тесты на handlers.
✅ MediatR подключён в `food-market.api` с авторегистрацией из
`food-market.application`. 3 handler-образца с абстракциями
(`ISupplyWriter`, `IRetailSalePoster`) — testable без EF/БД.
Контроллеры остались на прежнем flow (поэтапная миграция). 6 unit-тестов.
5. [x] **P2-4 2FA для админов (TOTP)**`AuthenticatorTokenProvider`,
endpoints `/api/me/2fa/enroll`, `/api/me/2fa/verify`, `/api/me/2fa/disable`.
Опционально для Admin+SuperAdmin. При логине с включённым 2FA — два шага.
✅ Identity `AuthenticatorTokenProvider` (RFC 6238). Endpoints:
/api/me/2fa/{status, enroll, verify, disable} с QR-URI. Password-grant
на `/connect/token` принимает custom param `otp_code`; при включённом
2FA без него — `invalid_grant` с `error_description=2fa_required`.
4 интеграционных теста (тест сам генерит TOTP через RFC 6238).
## Итог
**Все 5 пунктов выполнены.** Спринт 6 завершён 2026-05-28.
Сводка:
- **TD-6 RowVersion** — Postgres `xmin` через `UseXminAsConcurrencyToken`
на 5 документах, 409 при conflict. Bonus: исправил Supply.Update.
- **TD-2 FluentValidation** — `ValidationFilter` + 5 validator'ов
(Supply, RetailSale, Product, Counterparty, Employee).
- **TD-4 Structured logging** — `LogEnrichmentMiddleware` (OrgId/UserId/
CorrelationId в LogContext), business-логи на Post-операциях.
- **TD-1 CQRS partial** — MediatR + 3 handler-образца с testable-абстракциями.
- **P2-4 TOTP 2FA** — endpoints + интеграция в password-grant.
**Сборка:** зелёная.
**Тесты:** 57 unit + 74 integration = **131 зелёных**.
### Что осталось вне scope автономной работы
- ОФД-оператор (`Транском`/`Касса24`),
- MoySklad webhook-токены прод,
- WPF/POS UI на Windows,
- Стейдж→прод-деплой,
- Реальный SMTP-провайдер прод (Mailgun/Sendgrid),
- Backup-коды для 2FA recovery (отдельная задача).
## Лог
- Каждый пункт: build + тесты + коммит порцией + отметка [x] + коммит прогресса.
- Все правки на `main` (origin Forgejo), без коммита `global.json`.