krona-front/docs/handoff/control-center/FRONTEND-CONTRACTS.md

80 lines
4.4 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.

# Фронтенд-контракты и Модели данных Krona Control Center
## 1. Концепция Minor Currency Units (Минорные единицы валюты)
Для исключения ошибок округления чисел с плавающей точкой (`0.1 + 0.2 !== 0.3`) все финансовые поля в Control Center хранятся исключительно в минорных единицах (копейки):
- **Хранение**: целочисленные значения `number` (`priceMonthlyMinor`, `mrrMinor`, `amountMinor`).
- **Пример**: `149 000 руб.` представляется как `14900000` (копеек).
- **Форматирование**: компонент `<MoneyDisplay amountMinor={14900000} currency="RUB" />` производит безопасное форматирование с помощью `Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB' })`, деля число на 100 исключительно на этапе рендеринга строки.
---
## 2. Неизменяемый криптографический аудит (SHA-256 Hash Chaining)
Каждое операторское действие формирует блок в локальной цепочке аудита. Порядок связывания:
```typescript
export interface OperatorAuditEvent {
id: string;
timestamp: string;
operatorRole: OperatorRole;
operatorName: string;
actionType: OperatorActionType;
entityType: 'organization' | 'installation' | 'node' | 'module' | 'announcement' | 'incident' | 'system';
entityId: string;
reason: string;
impactSummary: string;
diffBeforeAfter?: {
before: Record<string, unknown>;
after: Record<string, unknown>;
};
clientIp?: string;
previousHash: string; // Ссылка на хеш предыдущей записи
eventHash: string; // SHA-256(previousHash + timestamp + operatorRole + actionType + entityId + reason)
}
```
### Алгоритм вычисления хеша:
```typescript
export async function computeEventHash(
previousHash: string,
timestamp: string,
operatorRole: string,
actionType: string,
entityId: string,
reason: string
): Promise<string> {
const payload = `${previousHash}|${timestamp}|${operatorRole}|${actionType}|${entityId}|${reason}`;
const msgUint8 = new TextEncoder().encode(payload);
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
}
```
---
## 3. Схема постоянного хранилища IndexedDB
База данных `krona_control_center_db` (версия 1) содержит следующие хранилища объектов (Object Stores):
1. `organizations`: карточки тенантов платформы (`PlatformOrganization`).
2. `module_instances`: установленные модули и версии (`ModuleInstance`).
3. `installations`: физические устройства, кассы, терминалы (`InstallationDevice`).
4. `nodes`: серверные узлы кластера (`ClusterNode`).
5. `announcements`: сервисные сообщения и баннеры (`SystemAnnouncement`).
6. `incidents`: инциденты платформы (`PlatformIncident`).
7. `audit_log`: цепочка блоков аудита с индексом по `timestamp`.
8. `settings`: глобальные флаги (maintenance mode, circuit breaker test flags).
---
## 4. Контракт устойчивости Server Monitor Outage (Circuit Breaker)
При отказе внешнего сервиса мониторинга кластера:
1. `useKccStore.serverMonitorOutage = true`.
2. Интерфейс переходит в режим graceful degradation:
- Отображается аварийный баннер `ServerMonitorOutageBanner` с индикатором «Используются локальные кэшированные метрики».
- Метрики узлов замораживаются на последнем известном валидном снимке из IndexedDB.
- Запрещается автоматическая эвакуация нод без явного ручного подтверждения `force_offline_drain`.