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

4.4 KiB
Raw Permalink Blame History

Фронтенд-контракты и Модели данных 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)

Каждое операторское действие формирует блок в локальной цепочке аудита. Порядок связывания:

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)
}

Алгоритм вычисления хеша:

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.