Find a file
nns 284ad095c1
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
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
fix(s23): adversarial bug-hunt — 4 bugs found, all fixed
Sprint 23 (adversarial): атаковали систему как недоброжелатель.
Найдено 4 бага, все починены.

Bug #001 (Medium): NULL-byte в Product.Name вызывал 500 без тела.
  Postgres TEXT не принимает \x00. Добавил NoControlChars() в
  ProductInputValidator + CounterpartyInputValidator.

Bug #002 (Low): ProductInputValidator MaximumLength(200) конфликтовал
  со StringLength(500) в DTO и schema HasMaxLength(500). Сделал 500
  везде. Counterparty: 200 → 255 (matches HasMaxLength).

Bug #003 (CRITICAL): параллельные posting'и под Serializable выбрасывали
  PostgresException 40001 → middleware → 500 empty body. Добавил
  SerializationConflictMiddleware который мапит 40001 → 409 Conflict
  с {error, retryable: true}. Также SerializableRetry helper для
  явного retry внутри endpoint'ов с exp backoff. Применил retry-wrap
  к RetailSalesController.Post (PostCoreAsync extracted).

Bug #004 (Low): цена 0.0000001 округлялась до 0 уже после прохождения
  required-price check (check был ДО RoundIfNeeded). FindMissing-
  RequiredPriceAsync теперь округляет перед сравнением — required
  цена реально > 0 после rounding.

Bug reports: tests/e2e/reports/bugs/bug-00[1-4]-*.md (github-issue format).

Multi-tenant attacks (cat 3): clean — все cross-org GET/PUT/DELETE
дают 404, bulk-update affected=0, lists не утекают.
Auth-edge (cat 2): clean — JWT tampering 401, garbage 401, CORS evil.com
не получает allow-origin, fake refresh 400 invalid_grant.
DOS (cat 7): clean — 50MB body 413, 200 headers 431, long URL 200.
Hangfire safety (cat 8): clean — regular Admin → /hangfire 403,
  seed-demo использует tenant context, body org-id игнорируется.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 01:35:50 +05:00
.claude feat(returns): возврат от покупателя (CustomerReturn) (P1-6) 2026-05-28 09:51:04 +05:00
.forgejo/workflows feat(s21): stage→prod migration toolchain (7 скриптов + workflow) 2026-06-07 22:31:10 +05:00
.github/workflows.disabled ci: disable .github/workflows — Forgejo Actions is the primary CI now 2026-04-23 17:10:22 +05:00
assets/brand chore(brand): add new food-market logo source SVG (FOOD/MARKET wordmark с яблоком) 2026-05-02 00:19:46 +05:00
badges test(s16): regression suite 35 flows + visual 60 snapshots + nightly + CI badges 2026-06-07 16:14:11 +05:00
deploy feat(s22): data tooling — export/import + schema docs + anon dump (7 пунктов) 2026-06-07 23:00:54 +05:00
docs fix(s23): adversarial bug-hunt — 4 bugs found, all fixed 2026-06-08 01:35:50 +05:00
scripts feat(s17): onboarding wizard + help kb + feedback + diagnostic + whats-new 2026-06-07 17:04:26 +05:00
src fix(s23): adversarial bug-hunt — 4 bugs found, all fixed 2026-06-08 01:35:50 +05:00
tests fix(s23): adversarial bug-hunt — 4 bugs found, all fixed 2026-06-08 01:35:50 +05:00
.editorconfig Phase 0: project scaffolding and end-to-end auth 2026-04-21 13:59:13 +05:00
.gitattributes Phase 0: project scaffolding and end-to-end auth 2026-04-21 13:59:13 +05:00
.gitignore feat(public): Phase 6 — публичный маркетинговый сайт food-market.public на Astro 2026-04-26 19:11:34 +05:00
.nvmrc Phase 0: project scaffolding and end-to-end auth 2026-04-21 13:59:13 +05:00
CHANGELOG.md feat(s17): onboarding wizard + help kb + feedback + diagnostic + whats-new 2026-06-07 17:04:26 +05:00
CLAUDE.md Phase 0: project scaffolding and end-to-end auth 2026-04-21 13:59:13 +05:00
Directory.Build.props Phase 0: project scaffolding and end-to-end auth 2026-04-21 13:59:13 +05:00
Directory.Packages.props feat(s20): Mapster + SSO scaffold + maintenance automation (7 пунктов) 2026-06-07 21:54:12 +05:00
food-market.sln test(integration): Testcontainers.PostgreSql + WebApplicationFactory, 10 тестов (P1-21) 2026-05-27 03:14:01 +05:00
global.json Phase 0: project scaffolding and end-to-end auth 2026-04-21 13:59:13 +05:00
README.md test(s16): regression suite 35 flows + visual 60 snapshots + nightly + CI badges 2026-06-07 16:14:11 +05:00

food-market

CI Docker API Stage verify Regression coverage

Аналог системы МойСклад для розничной торговли в Казахстане.

Состав системы

  • Сервер (ASP.NET Core 8 + PostgreSQL) — мультитенантный API, web-админка на React
  • Web-админка (React 18 + Vite + shadcn/ui) — управление магазином, справочниками, документами, отчётами
  • Кассовая программа (WPF на .NET 8) — офлайн-работоспособная касса для Windows 10+, синхронизируется с сервером, работает с весами (Масса-К в первую очередь)

Структура репозитория

food-market/
├── src/
│   ├── food-market.domain/          # доменные сущности, enum'ы, события
│   ├── food-market.application/     # use cases (MediatR), DTO, интерфейсы
│   ├── food-market.infrastructure/  # EF Core, PostgreSQL, внешние сервисы
│   ├── food-market.api/             # ASP.NET Core + OpenIddict + SignalR
│   ├── food-market.web/             # React + Vite + shadcn/ui (SPA)
│   ├── food-market.shared/          # DTO-контракты сервер ↔ POS
│   ├── food-market.pos.core/        # логика POS (независима от UI)
│   └── food-market.pos/             # WPF + .NET 8 кассовая программа
├── tests/
├── deploy/
│   ├── docker-compose.yml           # PostgreSQL для локальной разработки
│   └── Dockerfile.api
└── docs/

Именование

  • Папки, проекты, csproj, docker-образы, URL — lowercase: food-market, food-market.api
  • C# namespacefoodmarket.Api, foodmarket.Domain (lowercase root; C# не допускает дефис в идентификаторах)
  • Отображаемое имя в UI — "Food Market"

Стек

Сервер

  • .NET 8 LTS (до ноября 2026), ASP.NET Core Minimal APIs + Controllers
  • EF Core 8 + Npgsql + PostgreSQL 16
  • OpenIddict 5 (OAuth2/OIDC — password + refresh tokens)
  • MediatR + FluentValidation (CQRS-lite)
  • SignalR (real-time синхронизация)
  • Hangfire (фоновые задачи)
  • Serilog (структурированное логирование)

Web

  • React 18 + Vite + TypeScript
  • shadcn/ui + Tailwind CSS
  • TanStack Query + TanStack Table
  • AG Grid Community (для тяжёлых grid'ов)
  • Recharts / Tremor (графики)
  • react-hook-form + Zod

POS

  • .NET 8 WPF, Windows 10+
  • CommunityToolkit.Mvvm (source-generated MVVM)
  • SQLite (локальная БД)
  • Refit + Polly (API-клиент с retry)
  • System.IO.Ports (драйверы весов: Масса-К и др.)

Мультитенантность

Каждая сущность имеет OrganizationId. Пользователь scoped к организации. EF Core query filter автоматически изолирует данные между тенантами.

Локальная разработка

# Поднять PostgreSQL
cd deploy && docker compose up -d

# Мигрировать БД
cd src/food-market.api && dotnet ef database update

# Запустить API
dotnet run --project src/food-market.api

# Запустить Web
cd src/food-market.web && pnpm install && pnpm dev

Статус

🚧 Phase 0: фундамент (scaffolding, auth, multi-tenancy)