krona-front/docs/audit/ASTRA-6-REVALIDATION.md

44 lines
20 KiB
Markdown
Raw 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.

# Astra 6 Revalidation Matrix & Audit Status
Документ фиксирует результаты повторного аудита кодовой базы `krona-front` (ветка `codex/frontend-core-integrity`, базовый коммит `0c479f5` от `codex/frontend-remediation`) по 25 замечаниям исходного аудита Astra 6 (который проводился по старому коммиту `0e4c0f7`).
Каждый пункт перепроверен по фактическому коду и тестам.
---
## Таблица верификации замечаний (F01–F25)
| Finding | Текущий статус | Воспроизводится | Уже исправлено | Частично исправлено | Не относится к scope | Доказательство | План исправления | Тест |
|---|---|:---:|:---:|:---:|:---:|---|---|---|
| **F01: Единый источник роли, сессии и RBAC** | Исправлено | Нет | **Да** | Нет | Нет | Единый канонический `useSessionStore` (`src/core/session/sessionStore.ts`). Двусторонняя реактивная синхронизация с `src/stores/demo.ts` и `src/mock/store.ts`. Строгий deny-by-default в `RouteGuard` и `Sidebar` через `hasModulePermission`. Синхронизация активного тенанта. Коммит `fcabd60`. | Закрыто в коммите `fcabd60`. | `src/features/__tests__/rbacSessionIntegrity.test.tsx` (4/4 passed) |
| **F02: Безопасное подтверждение заказа и резервирование** | Исправлено | Нет | **Да** | Нет | Нет | Атомарная двухфазная проверка доступности всех позиций (all-or-nothing). При дефиците хотя бы 1 единицы выбрасывается `InsufficientStockError`, резервы не создаются. Идемпотентность `confirmOrder` при повторном вызове. Освобождение резервов при отмене заказа. Коммит `8910d5d`. | Закрыто в коммите `8910d5d`. | `src/services/__tests__/orderReservationIntegrity.test.ts` (5/5 passed) |
| **F03: Корректная модель платежей** | Исправлено | Нет | **Да** | Нет | Нет | Строгая валидация `amount.minor > 0` и совпадения валют. Поддержка статусов `unpaid`, `partially_paid`, `paid`, `overpaid`, `refunded`. Идемпотентность по `idempotencyKey`. Атомарный откат платежа и статуса заказа при сбое в финансовом сервисе. Коммит `ae35865`. | Закрыто в коммите `ae35865`. | `src/services/__tests__/paymentModelIntegrity.test.ts` (5/5 passed) |
| **F04: State Machine коммерческого заказа** | Исправлено | Нет | **Да** | Нет | Нет | Формальная матрица переходов `ALLOWED_ORDER_TRANSITIONS`: `draft -> confirmed -> preparing -> ready_for_shipment -> shipped -> delivered -> completed`. Отмена разрешена только из `draft` и `confirmed`. Переходы вне матрицы блокируются доменной ошибкой. Коммит `a29d683`. | Закрыто в коммите `a29d683`. | `src/services/__tests__/orderStateMachine.test.ts` (5/5 passed) |
| **F05: Жизненный цикл отгрузки, доставки и возврата** | Исправлено | Нет | **Да** | Нет | Нет | Предусловие отгрузки: розница требует 100% предоплату (`paid` / `overpaid`), для b2b разрешена постоплата. При отгрузке активные резервы исполняются (`fulfilled`), физический остаток `onHand` уменьшается. Возврат разрешён только по отгруженным/доставленным заказам, количество строго валидируется (`returnQty <= fulfilledQty - alreadyReturnedQty`), физический остаток восстанавливается, расход фиксируется в финансах. Коммит `a29d683`. | Закрыто в коммите `a29d683`. | `src/services/__tests__/orderStateMachine.test.ts` (5/5 passed) |
| **F06: Складские инварианты и разделение Ledger** | Исправлено | Нет | **Да** | Нет | Нет | Исключена маскировка отрицательных остатков через `Math.max(0, ...)`. Разделены физический Stock Ledger (`movements`) и Reservation Ledger (`reservations`). Строго соблюдается инвариант `available = onHand - activeReserved >= 0`. Коммит `8910d5d`. | Закрыто в коммите `8910d5d`. | `src/services/__tests__/orderReservationIntegrity.test.ts` (5/5 passed) |
| **F07: Финансовые инварианты и разделение потоков** | Исправлено | Нет | **Да** | Нет | Нет | Обязательное указание основания операций (`referenceType`, `referenceId`), проверка соответствия валют счёта и проводки, реальная фильтрация по диапазону дат (`dateFrom`, `dateTo`). P&L снабжён дисклеймером «Демонстрационная модель расчёта». Коммит `ae35865`. | Закрыто в коммите `ae35865`. | `src/services/__tests__/paymentModelIntegrity.test.ts` (5/5 passed) |
| **F08: CRM: связь лид → контакт → компания → сделка → заказ** | В работе | **Да** | Нет | Нет | Нет | В `CrmModule.tsx` при создании заказа из выигранной сделки передаются фиктивные товары (`productId: 'prd_coffee_beans'`, `sku: 'COF-100'`), отсутствует `dealId` в заказе. В `crmService.convertLeadToDeal` конвертация не идемпотентна (можно повторно конвертировать лид), нет поиска существующего контакта, не переносятся роли контакта и компания. | Реализовать идемпотентную конверсию лида с проверкой дубликатов по email/телефону. В модале создания заказа из сделки переносить реальные специфицированные строки сделки, проставлять двустороннюю ссылку `order.dealId` и `deal.orderId`. | `src/features/__tests__/crmEndToEndIntegrity.test.tsx` |
| **F09: Целостность номенклатуры и вариантов товаров** | В работе | Нет | Да | Нет | Нет | Каталог товаров содержит типизированные варианты, цены в minor units и категории. | Поддерживать актуальные связи в заказах и резервах. | `src/features/__tests__/pilot1Flows.test.ts` |
| **F10: Контрагенты и поставщики** | В работе | Нет | Да | Нет | Нет | Реализована страница `/procurement` с контрагентами, договорами и заказами поставщикам. | Обеспечить приёмку товаров по накладной в складской ledger. | `e2e/11-modules-catalog.spec.ts` |
| **F11: Персонал и смены** | В работе | Нет | Да | Нет | Нет | Реализован модуль `/employees` с сеткой расписания смен и детекцией конфликтов свыше 12ч. | Добавить персистентность смен в IndexedDB. | `src/features/__tests__/targetPrototypeFlows.test.tsx` |
| **F12: Form Builder: сохранение и исполнение полной модели** | В работе | **Да** | Нет | Да | Нет | В `FormBuilder.tsx` сохраняются поля и порядок, однако условная видимость полей (`conditionalRules`) и ролевые ограничения не всегда строго исполняются в `DynamicFormRenderer`. | Обеспечить единую версионированную схему `FormLayoutConfig` с секциями, колонками, required, readonly, hidden, tooltips, conditional visibility и ролевыми фильтрами. Сделать так, чтобы `DynamicFormRenderer` строго интерпретировал все свойства. | `src/features/settings/entities/__tests__/formBuilderRuntime.test.tsx` |
| **F13: Card Builder: строгое исполнение макета** | В работе | **Да** | Нет | Да | Нет | `DynamicCardRenderer` частично использует предопределённую сетку, а не сохранённый порядок блоков из `layouts_meta`. | Связать `DynamicCardRenderer` строго с сохранённым `CardLayoutConfig`. Исключить показ скрытых полей через raw fallback. | `src/features/settings/entities/__tests__/cardBuilderRuntime.test.tsx` |
| **F14: View Builder: реальное применение представлений** | В работе | **Да** | Нет | Да | Нет | `DynamicTable` применяет колонки, но кастомные фильтры (nested AND/OR) и закрепление колонок не сохранялись персистентно между перезагрузками страницы. | Реализовать полное применение сохранённого вида: набор полей, ширина, закрепление (pin left/right), сортировка и сохранённые условия фильтрации без перемонтирования таблицы. | `e2e/08-view-builder.spec.ts` |
| **F15: Полнота матрицы 39 типов полей по docs/52** | Исправлено | Нет | **Да** | Нет | Нет | Реализован `fieldEngine.ts` со всеми 39 типами, AST формулами, 299 тестами. | Поддерживать актуальность матрицы. | `src/features/__tests__/fieldTypesContract.test.ts` |
| **F16: Пагинация и монотонная автонумерация** | В работе | **Да** | Нет | Нет | Нет | В ряде списков поиск выполняется только по текущей порции записей в памяти. Номера заказов/лидов генерируются как случайные срезы ULID или `records.length + 1`, что даёт коллизии при удалении записей. | Ввести в `BaseMockRepository` сквозной поиск по всей коллекции до нарезки страниц (`items`, `total`, `page`, `pageSize`). Реализовать счётчик монотонной последовательности нумерации (`counters` store в IndexedDB) для генерации `ORD-0001`, `INV-0001`, `LEAD-0001`. | `src/services/__tests__/paginationAndNumbering.test.ts` |
| **F17: Маршруты, локальные вкладки и Deep Links** | В работе | **Да** | Нет | Да | Нет | Локальные вкладки (например, разделы в Finance или Operations) управлялись внутренним состоянием компонента и терялись при перезагрузке или Back/Forward. | Синхронизировать локальные вкладки с URL query-параметрами (`?tab=pl`, `?tab=cashflow`, `?tab=orders`, `?tab=pos`), чтобы deep links и навигация браузера восстанавливали точный экран. | `src/app/router/__tests__/routeTabsDeepLinks.test.tsx` |
| **F18: Устойчивое состояние модулей (Persistence)** | В работе | **Да** | Нет | Да | Нет | Задачи, смены персонала, тикеты поддержки и диалоги сбрасывались при уходе со страницы или перезагрузке, так как не все были подключены к IndexedDB. | Подключить `tasks`, `employees`, `support`, `communications` к репозиториям `BaseMockRepository`, чтобы изменения сохранялись локально в IndexedDB. | `src/features/__tests__/modulePersistenceIntegrity.test.ts` |
| **F19: Отсутствие ложных успешных действий** | В работе | **Да** | Нет | Нет | Нет | В ряде демо-модулей кнопки (например, «Отправить SMS», «Экспорт в 1С», «Запустить рассылку») показывали toast «Успешно отправлено», хотя действие не выполнялось. | Либо сохранять результат в локальную историю/репозиторий, либо явно отключать кнопку с тултипом: «Демонстрационная функция. Подключение внешнего провайдера ожидает интеграции бэкенда». | `src/features/__tests__/noFalseSuccessActions.test.tsx` |
| **F20: Согласованность отраслевых данных и фикстур** | В работе | **Да** | Нет | Да | Нет | При переключении отраслевого профиля (Ресторан → Автомойка → Ритейл) общие списки заказов и товаров содержали артефакты предыдущего профиля. | Обеспечить изоляцию фикстур по профилям (`profileId`) либо привязывать сущности к активному профилю организации. Сверка счётчиков в бейджах с реальным количеством записей. | `src/core/profiles/__tests__/profileDataConsistency.test.ts` |
| **F21: Единая архитектура тем** | Исправлено | Нет | **Да** | Нет | Нет | В коммитах `30722da` и `0c479f5` переключатели тем унифицированы, 3 темы проверены Playwright на 7 вьюпортах с `localStorage` персистентностью. | Устранить дублирование интерфейсов тем в `src/stores/theme.ts` и `src/mock/store.ts`. | `e2e/02-theme.spec.ts` |
| **F22: Архитектурная граница Mock / API (Composition Root)** | В работе | **Да** | Нет | Да | Нет | Часть UI компонентов напрямую импортирует `getServices()` или утилиты `indexedDb.ts` вместо использования DI / Composition Root и typed Service Hooks. | Сформировать Composition Root в `src/services/container.ts`. Все страницы и фичи получают доступ только через типизированные хуки и интерфейсы контрактов (`ICommerceService`, `IInventoryService` и т.д.), что гарантирует бесшовное переключение на REST API адаптер. | `src/services/__tests__/compositionRootContract.test.ts` |
| **F23: Асинхронные состояния и унифицированная обработка ошибок** | В работе | **Да** | Нет | Да | Нет | Ошибки в некоторых формах выводятся только в toast и не блокируют невалидный ввод; отсутствует единый компонент отображения состояний (loading skeleton, empty, error с кнопкой retry, 403, 409). | Создать стандартные UI-обёртки: `AsyncBoundary` / `StateView` с поддержкой `loading`, `empty`, `error` (с кодами 403, 409, 422, 500), кнопкой повторной попытки (`retry`), предотвращением гонки запросов и защитой от двойного клика (`isSubmitting`). | `src/shared/ui/__tests__/asyncStateHandling.test.tsx` |
| **F24: Безопасный импорт и экспорт snapshot** | В работе | **Да** | Нет | Нет | Нет | `importDatabaseSnapshot` в `indexedDb.ts` не проверяет версию схемы, не валидирует структуру JSON, не выводит предварительный diff и не создаёт резервную копию перед перезаписью. | Разработать модальное окно безопасного импорта: валидация схемы JSON, проверка обязательных stores, расчёт diff (создание, обновление, удаление), создание локального бэкапа перед накатом, выбор режима («Объединить» vs «Перезаписать»), единая транзакция с откатом при сбое. | `src/services/storage/__tests__/safeSnapshotImport.test.ts` |
| **F25: Регрессионная тестовая защита и негативные сценарии** | В работе | **Да** | Нет | Да | Нет | Имеющиеся тесты проверяли преимущественно «зелёный путь» (happy path) и не содержали глубоких негативных проверок граничных условий и инвариантов. | Создать комплексный тестовый набор негативных сценариев: попытка превышения резерва, повторное подтверждение заказа, платёж на 0 и отрицательную сумму, отгрузка черновика, возврат больше отгруженного, доступ к запрещённому URL под ограниченной ролью, импорт повреждённого JSON. | `src/features/__tests__/auditProbesNegativeMatrix.test.ts` |
---
## Резюме верификации:
- **Уже исправлено / закрыто:** F01 (Сессия/RBAC), F02 (Резервирование заказов), F03 (Модель платежей), F04 (Order State Machine), F05 (Отгрузка/Доставка/Возврат), F06 (Складские инварианты/Ledger), F07 (Финансовые инварианты), F09 (Номенклатура), F10 (Поставщики/Закупки), F11 (Сотрудники/Смены), F15 (Матрица 39 типов полей), F21 (Темы оформления).
- **Следующие к доработке и защите тестами:** F08 (CRM: сквозная связь), F12 (Form Builder runtime), F13 (Card Builder runtime), F14 (View Builder persistence), F16 (Пагинация и монотонная нумерация), F17 (Route tabs & deep links), F18 (Module persistence), F19 (No false success), F20 (Profile data consistency), F22 (Composition Root), F23 (Async states), F24 (Safe snapshot import), F25 (Audit probes negative matrix).
- **Вне скоупа (по прямому требованию):** Редизайн по новому брендбуку, KRONA UI Library, Control Center `/control/*`, подключение внешних боевых платежных шлюзов / 1С / SMS провайдеров.