Приоритет владельца: sysadmin проверяет весы/принтер/сканер на ноутбуке магазина
без входа в кассу. Отдельный exe (food-market.pos.hwcheck), ссылается ТОЛЬКО на
pos.core ради Hardware/* — не умеет быть кассой (нет логина, сервера, БД, токенов,
сетевых запросов).
- pos.core/Hardware/HardwareProbe.cs: детект COM-портов (занят/свободен, VID/PID,
описание) и принтеров Windows (имя/порт/в сети/число заданий) — только чтение,
очередь не трогаем. WMI под OperatingSystem.IsWindows(); на Linux — базовый COM.
- pos.core/Hardware/BarcodeScan.cs: контрольная цифра EAN-13/EAN-8 и оценка
«сканер vs ручной набор» по среднему интервалу между символами (чистая логика).
- food-market.pos.hwcheck: окно на Avalonia (код, без XAML), светлая тема, русский.
Весы (Найти/Прочитать/Запустить-Остановить, live-вес ~350 мс, сырой hex, ручной
выбор порта/скорости/протокола), COM-порты с пометкой «занят», принтеры (только
чтение), сканер (EAN + тип ввода), «Сохранить/Копировать отчёт». Тестовая печать
ВЫКЛ по умолчанию, включается только --allow-test-print.
- tests: EAN контрольная цифра (13/8, валид/битый) + классификация ввода. 50/50.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ApiFactory поднимает реальный API на одноразовом postgres:16-alpine (Ryuk off —
сеть к Docker Hub нестабильна, образ закэширован; RateLimiting off через env, т.к.
лимитер читает конфиг эагерно). Program сделан public partial для фабрики.
Сценарии (10 зелёных):
- signup-flow: signup→token→/api/me с org; дубль-signup 400; слабый пароль 400.
- tenant isolation A vs B: контрагент A не виден B (список + прямой GET 404).
- permission: кастомная роль без ProductsEdit → PUT товара 403, GET 200; админ не 403.
- supply post→unpost: остаток 0→10, Cost=70 (скользящее среднее), unpost→0; двойной post 409.
- retail overselling: продажа сверх остатка → 409; недоплата → 400.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>