# CHANGELOG Auto-generated from git log feat:/fix: (last 90 days). ## 2026-06-07 - **feat**: security headers + rate-limits + sensitive-ops audit + session revoke + Grafana (s13) - **feat**: ОФД-scaffolding — IFiscalProvider + 4 провайдера + UI/тесты (s11) ## 2026-06-06 - **feat**: dark mode полировка + Cmd+K палитра + аудит-spec (s10-4) - **feat**: глобальная Cmd+K палитра + GET /api/search/global (s10-3) - **feat**: year-demo seeder + 4 dashboard виджета + week-stats (s10) ## 2026-06-04 - **fix**: IP-limit 60/min, locale ru-RU в playwright, исправлены payload'ы verify-spec'ов (stage-tests) - **fix**: per-username 5/мин + per-IP 30/мин — brute-force на конкретный аккаунт ловится, CI/NAT не страдают (rate-limit) - **fix**: rate-limit 5/min на /connect/token, nginx route /metrics+/swagger, Swagger в Production через IncludeSwagger (stage) ## 2026-05-31 - **fix**: bump cache version + filter SignalR-race errors in PWA test (pwa) - **fix**: SW не вмешивается в /hubs/* — SignalR negotiate сломался (pwa) - **feat**: PWA owner read-only + mobile tweaks + S9 stage specs (pwa+mobile+s9) - **fix**: убрать unused imports (TS6133) (loyalty) - **feat**: P2-12 + P2-13 — лояльность и промокоды (Sprint 9 п.1-2) (loyalty+promotions) - **feat**: IObjectStorage abstraction (Local + MinIO) — P2-15 (storage) - **feat**: react-i18next ru/en + language switcher (P2-6a — базовая) (i18n) - **feat**: OwnerDailySummaryJob + bot binding (P2-14) (telegram) - **feat**: SignalR hub /hubs/notifications per-org + dashboard live (realtime) ## 2026-05-30 - **fix**: после create — invalidate list query (не показывался сразу) (employees) - **fix**: error display через humanizeError, не «Request failed» (employees) - **fix**: уберём cache-touch после Delete — просто navigate (catalog) - **fix**: после Delete не refetch'аем удалённый товар (catalog) - **fix**: ProductEditPage — race на currencies.data + читаемая ошибка (catalog) - **fix**: Modal — role=dialog + aria-modal + aria-label на крестике (a11y) - **fix**: useShortcuts — бэр-клавиши не зависят от Shift (web) - **feat**: keyboard shortcuts на edit + list страницах + «?» overlay (web) - **feat**: Breadcrumbs на edit-страницах (Каталог / Товары / Молоко 3.2%) (web) - **feat**: Empty states с CTA на list-страницах (web) - **feat**: loading skeletons вместо «Загрузка…» в DataTable + edit-pages (web) - **feat**: toast-система — error на 4xx/5xx + success на мутации (через meta) (web) - **feat**: ConfirmDialog компонент + useConfirm hook вместо window.confirm() (web) - **feat**: demo-data seeder для test.admin.food-market.kz (stage) ## 2026-05-29 - **fix**: operationId + schemaId — генерация OpenAPI работает (swagger) - **fix**: 3 фикса по итогам stage-тестирования (reports) - **fix**: EF8 nav-collection bug в Enters/Losses/Transfers/SupplierReturns/Inventories.Update (docs) - **fix**: EF8 nav-collection bug в Products.Update + unique IX на Article (catalog) ## 2026-05-28 - **feat**: TOTP 2FA для админов через AuthenticatorTokenProvider (P2-4) (auth) - **feat**: MediatR partial — 3 handler-образца (TD-1) (cqrs) - **feat**: структурные log-fields в Serilog (TD-4) (logging) - **feat**: FluentValidation + ValidationFilter для DTO (TD-2) (validation) - **feat**: RowVersion на документах через Postgres xmin (TD-6) (concurrency) - **feat**: persisted ImportJobRegistry в БД (TD-5) (import-jobs) - **feat**: HTML-шаблоны MailKit + invite/weekly/low-stock джобы (P1-22) (email) - **feat**: per-tenant журнал мутаций OrgAuditLog (P1-18) (audit) - **feat**: оптовая отгрузка контрагенту-юрлицу (P1-5) (demands) - **feat**: Prometheus метрики /metrics + бизнес-счётчики (P1-17) (observability) - **feat**: GET /sync и POST /sales с двойной идемпотентностью (P1-12b) (pos-api) - **feat**: контракты POS v1 в food-market.shared (P1-12a) (pos-shared) - **feat**: улучшенный Swagger + TS-клиент через openapi-typescript (P1-19) (openapi) - **feat**: ABC-анализ по Парето (P1-11) (reports) - **feat**: отчёт «Прибыль» (выручка − COGS) (P1-10) (reports) - **feat**: отчёт «Остатки на дату» с реконструкцией (P1-9) (reports) - **feat**: отчёт «Продажи» с группировками и экспортом (P1-8) (reports) - **feat**: dashboard + scheduled cleanup джобы (P1-16) (hangfire) - **feat**: возврат поставщику (P1-7) (supplier-returns) - **feat**: возврат от покупателя (CustomerReturn) (P1-6) (returns) - **feat**: инвентаризация с CSV-импортом факта (P1-4) (inventories) - **feat**: атомарное перемещение между складами (P1-3) (transfers) - **feat**: списание со склада с указанием причины (P1-2) (losses) - **feat**: оприходование товара без поставщика (P1-1) (enters) ## 2026-05-27 - **feat**: авто-бэкап БД+uploads — systemd timer/service + скрипт (P0-6) (deploy) - **feat**: prod X509-ключи OpenIddict с persistent self-signed (P0-1) (auth) - **feat**: permission-based авторизация по флагам роли (P0-5) (authz) - **feat**: health-пробы /health/live и /health/ready (P0-4) (api) - **feat**: rate-limit /connect/token и /api/auth/signup (P0-3) (api) ## 2026-05-26 - **fix**: change-owner требует reason ≥ 10 символов (superadmin) - **fix**: увольнение/деактивация гасит логин связанного User (employees) - **fix**: сериализуемое проведение приёмки против lost update остатков (supplies) - **fix**: FK-guard удаления контрагента + валидация полей товара (catalog) - **fix**: refresh-token rotation немедленно инвалидирует старый токен (auth) ## 2026-05-23 - **fix**: защита денег и инварианта остатков на posting-операциях (documents) - **fix**: SuperAdmin edit-mode override обходит [Authorize(Roles=Admin)] (security) - **fix**: чиним P0-блокеры разворачивания на чистой БД (migrations) ## 2026-05-18 - **fix**: обновить node:20-alpine → 22-alpine (pnpm 11 требует Node ≥22) (docker) - **fix**: validatePassword проверяет заглавную и цифру (соответствует хинту) (validation) - **fix**: onBlur валидация через e.target.value, ре-валидация вместо сброса ошибки в onChange (signup) ## 2026-05-17 - **feat**: onBlur валидация полей во всех формах (ux) ## 2026-05-08 - **fix**: блок пустого Draft на UI + бэк уже отказывает (retail-sale) - **feat**: системная ProductGroup «Все товары» при создании org (bootstrap) - **fix**: обязательные FK-Guid проверяются на 400 + DbUpdateException → 400 (validation) - **fix**: блок overselling в Post — 409 если qty>остатка (retail-sale) - **fix**: добавить [Migration] атрибут для Phase5c — без него Migrate() не находит миграцию (migrations) - **fix**: серверная KZ-ФЛК на всех endpoint'ах принимающих phone (phone) - **fix**: Cashier/Storekeeper больше не видят /api/organization/employees + Identity-роль маппится из orgRole (auth) - **feat**: infrastructure + first full-cycle scenario + baseline report (e2e) ## 2026-05-06 - **feat**: forgot/reset password — endpoints + UI + IP rate-limit (auth) - **feat**: UI /super-admin/platform-settings + тестовая отправка (platform) - **feat**: IEmailSender + MailKit + PlatformSettingsController (platform) - **feat**: PlatformSettings entity + миграция (singleton SMTP-конфиг) (platform) - **feat**: фильтр sidebar и route-guard по ролям пользователя (roles) - **feat**: двухступенчатое удаление — «уволить» → «удалить» (employees) - **feat**: TextInput с type=email — авто-pattern для TLD-проверки (forms) - **feat**: MoneyInput для поля «Оклад» в карточке сотрудника (forms) - **feat**: убрать «ИНН» из UI — РК использует ИИН/БИН (localization) - **feat**: системная роль — read-only форма прав вместо alert (roles) - **feat**: три системные роли — Admin/Cashier/Storekeeper (roles) ## 2026-05-03 - **fix**: сохранять позицию курсора после нормализации (phone) - **fix**: нативное редактирование, фильтр не-цифр через onBeforeInput (phone) - **fix**: редактирование на месте курсора, как в обычном поле (phone) - **fix**: полностью переписать на простую модель — цифры как single source of truth (phone) - **fix**: блокировать ввод не-цифр на уровне keyDown (phone) - **fix**: не считать «7» из префикса как введённую цифру (phone) - **feat**: единый PhoneInput с зашитым «+7» и ФЛК Казахстана (phone) - **feat**: телефон обязателен + ФЛК Казахстана (77XXXXXXXXX) (signup) - **fix**: убрать «моргание» при клике на орг — переход теперь по double-click (super-admin) ## 2026-05-02 - **fix**: docker-public — актуализировать PUBLIC_*_URL под новые домены (ci) - **fix**: кнопка «Войти» вела на 410-Gone zat.kz (public) - **feat**: новый логотип food-market wordmark + apple mark (brand) ## 2026-04-30 - **feat**: миграция на food-market.kz / admin.food-market.kz (domains) ## 2026-04-28 - **feat**: полное управление сотрудниками любой орги (super-admin) - **feat**: AsyncSelect — серверный поиск в дропдаунах вместо pageSize=500 (ui) - **fix**: SuperAdmin платформы без OrganizationId + отдельный Admin для Demo Market (auth) ## 2026-04-27 - **feat**: главный администратор — терминология + защита роли/активности (employees) - **feat**: бейдж «Владелец» + блокировка удаления с объяснением (employees) - **fix**: пароль/orphan signup/tenant-guard toast/dashboard счётчик - **fix**: нейтральный placeholder в поле названия организации (public) - **fix**: закрыть критические дыры — orphan login, self-delete, owner-delete, override-баннер (auth) - **feat**: русская локализация и строгий email с TLD (validation) - **fix**: убрать русские имена/ИП из placeholder регистрации (public) ## 2026-04-26 - **feat**: Phase 6 — публичный сайт на food-market.zat.kz, админка на app. (deploy) - **feat**: Phase 6 — публичный маркетинговый сайт food-market.public на Astro (public) - **feat**: настраиваемый retention period для архивных орг (super-admin) - **fix**: убрать цикл редиректа, регресс override после пакета задач (super-admin) - **fix**: Phase4d таблица называется units_of_measure, не units (migration) - **feat**: двухуровневые справочники Группы и Ед.измерения (системные + tenant) (directories) - **feat**: системные роли read-only + русские имена + чистка дубликата у admin (roles) - **feat**: перенести справочник Стран в системную консоль (super-admin) - **fix**: SuperAdmin override должен применять tenant filter выбранной орги (tenancy) - **feat**: рабочий quick-switch + UI-блокировка мутаций в read-only (super-admin) - **feat**: Phase 2b — отдельный SuperAdminLayout и разделение от tenant-админки (super-admin) - **feat**: Phase 3 — edit-mode с reason + audit-trail (super-admin) - **feat**: Phase 2 — read-only «открыть как…» context switch (super-admin) - **feat**: /quiet и /loud команды для управления PreToolUse прогресс-лентой (bridge) - **fix**: новая org через UI получает полный bootstrap (как Demo) (super-admin) - **feat**: PreToolUse hook for Telegram progress feed + rate-limited batching (infra) - **fix**: grant SuperAdmin role to admin@food-market.local (seed) - **feat**: super-admin section + setup wizard + auto-redirect (web) - **feat**: super-admin endpoints (orgs CRUD + setup-status + audit-log + dashboard) (api) - **feat**: Organization.IsArchived/AccountOwner + SuperAdminAuditLog + migration (domain) - **feat**: add Salary, TaxNumber, Description, ImageUrl + radio role picker (employee) - **feat**: permissions matrix grouped by section + clone-from-template flow (roles) - **fix**: keep only Admin + Cashier as system, demote others to custom + migration (roles) - **feat**: event-driven Telegram bridge — webhook + Stop hook (infra) - **fix**: drop Employee.Navigation(RetailPointAssignments) to fix snapshot order (migrations) - **feat**: welcome dashboard with first-steps cards (onboarding) - **feat**: Employees + Roles pages with permissions matrix (web) - **feat**: EmployeesController + EmployeeRolesController + invite-with-temp-password (api) - **feat**: system roles per organization + map admin → Employee (seed) - **feat**: Employee, EmployeeRole, RolePermissions entities + migration (domain) - **fix**: dropdown opens as floating overlay (Portal + absolute) (searchable-select) - **fix**: theme styles + default to today for new docs (date-field) - **feat**: replace native input with react-datepicker — polished UX (date-field) - **fix**: polish calendar UX — dropdown nav, today/clear footer, ru weekdays (date-field) - **fix**: compact calendar popup — shadcn-style sizing (date-field) - **fix**: cap width + ru locale + DD.MM.YYYY format (date-fields) - **fix**: show both article and barcode in line subtitle (supply-lines) - **fix**: sticky input at viewport bottom + auto-scroll on add (supply-quick-add) - **fix**: dropdown opens upward + show only N results + create-new at bottom (supply-quick-add) - **feat**: drop supplier field, reorder sections, add cost column (product-card+list) - **fix**: keep input focused after scan / clear on add (supply-quick-add) - **fix**: dropdown not rendering — Portal + fixed position (supply-quick-add) - **feat**: inline line quick-add — scanner + autocomplete + create-on-fly (supply) - **feat**: products quick-search + by-barcode endpoints (api) - **fix**: колонка «Розничная» использует имя системного PriceType (supply) - **feat**: «Проведено» внутри формы + обязательная дата и ≥1 позиция (supply) - **fix**: catch-up Phase3b_AddShowDescriptionOnProduct (migrations) - **feat**: inline-create option in searchable Select (ui) - **feat**: searchable Select component (drop-in) (ui) - **feat**: drop ShelfLifeDays + recompose classification + auto-article + barcode trash hide (product-card) - **fix**: IsRequired применяется сразу, без перезагрузки страницы (price-types) ## 2026-04-25 - **fix**: человечная ошибка 400 + блок Save при незаполненных IsRequired ценах (product-edit) - **fix**: correct is-system seeder + require value > 0 + system-price filter/sort (price-types) - **feat**: inputs по справочнику PriceType — без dropdown'a (product-prices) - **feat**: компонент + inline-наценка в таблице групп (percent-input) - **feat**: срок годности (shelfLifeDays) + фильтр от/до (product+filters) - **feat**: чекбокс «Проведено» с confirm + системная розничная в списке (supply+products-list) - **feat**: drop IsActive, add ShelfLifeDays, restore PriceType IsSystem/IsRequired (phase3b) - **feat**: supply line retail override column (web) - **feat**: price types CRUD visibility + group markup table (web) - **feat**: product card pricing UI + settings toggles (web) - **feat**: recalc-retail endpoint + 30-day reference price refresh job (api) - **feat**: supply posting hook for cost & markup (api) - **feat**: pricing model rename and new fields (Phase3a) (domain) - **fix**: merge barcodes/prices по ключу + 409 на concurrency (products/update) - **fix**: toFixed(2) при allowFractional=true для правильного отображения (money-input) - **fix**: сохранять промежуточный ввод точки в draft (money-input) - **fix**: корректное обновление allowFractionalPrices без перелогина (money-input) - **fix**: уважать AllowFractionalPrices в формах редактирования (money-input) - **feat**: pre-check на Create/Update + warnings импорта + admin endpoint (barcode-uniqueness) - **feat**: AllowFractionalPrices — переключатель дробных цен (org-settings) - **feat**: группа обязательна, ≥1 штрихкод, умные дефолты на новом (product) - **feat**: MoneyInput/NumberInput + select-пагинация + Range на бэкенде (forms) ## 2026-04-24 - **feat**: авто-генерация числового артикула при создании (products) - **feat**: настройка ShowMinMaxStock для мин/макс остатков (org-settings) - **feat**: галки «Услуга»/«Маркируемый» скрываются по умолчанию (org-settings) - **feat**: авто-генерация EAN-13 при добавлении штрихкода (barcode) - **feat**: server-side sort by column header click (tables) - **feat**: валюта read-only, тянется из страны (как НДС) (org-settings) - **feat**: ставка в стране + опц. переопределение на товаре (vat) - **feat**: загрузка на диск сервера + галерея с лайтбоксом (product-images) - **feat**: enum Packaging (штучный/весовой/разливной) вместо IsWeighed (product) - **feat**: Country↔Currency, Organization.DefaultCurrency/MultiCurrency/DefaultVat + UI настроек (org-settings) - **fix**: сделать Token опциональным (other-system/test) ## 2026-04-23 - **feat**: async jobs с прогрессом + токен в настройках (other-system-import) - **fix**: per-page retry + чаще SaveChanges (other-system/import) - **feat**: tree-of-groups + фильтры как в OtherSystem (catalog/products) - **feat**: import archived entities too (as IsActive=false) (other-system) - **fix**: reconcile stage schema — drop TrackingType, add IsMarked (db) - **feat**: temp cleanup buttons + fix OtherSystem import duplicates (admin) - **feat**: strict OtherSystem schema — реплика потерянного f7087e9 - **fix**: убираем выдумку Kind полностью — у OtherSystem этого поля нет (other-system) - **fix**: не выдумывать Kind=Both для импортированных контрагентов (other-system) - **feat**: Telegram <-> tmux bridge + local docker-registry unit (ops) - **feat**: sales chart + KPIs (как «Показатели» в сторонняя система) (dashboard) ## 2026-04-22 - **fix**: bootstrap admin + demo org on stage/prod too, not just Dev (seeder) - **fix**: always apply EF migrations on startup, not only in Development (api) - **fix**: widen Article + Barcode.Code to 500 chars for real-world catalogs (catalog) ## 2026-04-21 - **fix**: accept fractional prices (decimal, not long) in DTOs (other-system) - **fix**: add User-Agent header + enable HTTP auto-decompression (other-system) - **fix**: drop Accept-Encoding: gzip to avoid JSON parse failure (other-system) - **fix**: set Accept header as raw string to bypass .NET normalization (other-system) - **fix**: exact Accept header value per OtherSystem requirement (code 1062) (other-system) - **fix**: trailing slash on BaseUrl so HttpClient keeps /1.2/ in path (other-system) - **fix**: OtherSystem admin endpoint uses policy-based auth on role claim directly (auth) - **fix**: return 401 instead of 302 for API challenges; persist dev signing key across restarts (auth) - **fix**: drop FM square badge from Logo; better 404 diagnostics on OtherSystem page (web) - **feat**: rebrand to FOOD MARKET green (#00B207) per mobile app logo (web) - **fix**: remove TanStack devtools palm icon; restore user profile on dashboard (web) - **fix**: pin API dev port to 5081 (match Vite proxy config)