docs(control-center): add comprehensive handoff specifications and atomic zero-downtime deployment package

This commit is contained in:
ochenstarik 2026-09-11 02:34:51 +07:00
parent 8e0f640673
commit 5489fc3b43
9 changed files with 705 additions and 0 deletions

68
deploy/kcc/deploy-kcc.sh Normal file
View file

@ -0,0 +1,68 @@
#!/usr/bin/env bash
# ==============================================================================
# Krona Control Center (KCC) - Atomic Zero-Downtime Deployment Script
# Target: https://kccdemo.ochenstarik.ru
# Target Host: 178.212.13.102 (User: kcc)
# ==============================================================================
set -euo pipefail
APP_ROOT="/srv/kccdemo"
RELEASES_DIR="$APP_ROOT/releases"
CURRENT_LINK="$APP_ROOT/current"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
NEW_RELEASE_DIR="$RELEASES_DIR/$TIMESTAMP"
echo "================================================================="
echo " [KCC Deploy] Initiating atomic release: $TIMESTAMP"
echo "================================================================="
# 1. Create target release directory
mkdir -p "$NEW_RELEASE_DIR"
# 2. Deploy static SPA artifacts
if [ -d "./dist" ]; then
echo "Copying ./dist to $NEW_RELEASE_DIR..."
cp -r ./dist/* "$NEW_RELEASE_DIR/"
elif [ -d "../dist" ]; then
echo "Copying ../dist to $NEW_RELEASE_DIR..."
cp -r ../dist/* "$NEW_RELEASE_DIR/"
else
echo "ERROR: Production build directory 'dist' not found!" >&2
exit 1
fi
# Set proper permissions for kcc user
chmod -R 755 "$NEW_RELEASE_DIR"
# 3. Atomic symlink switch
echo "Switching active release symlink ($CURRENT_LINK -> $NEW_RELEASE_DIR)..."
ln -sfn "$NEW_RELEASE_DIR" "$CURRENT_LINK"
# 4. Prune older releases (keep last 3 for instant rollback)
echo "Cleaning up old releases (retaining last 3)..."
cd "$RELEASES_DIR"
# List matching release directories sorted by date descending, remove all except top 3
ls -1dt 20* 2>/dev/null | tail -n +4 | xargs -r rm -rf
# 5. Reload Nginx
if command -v systemctl >/dev/null 2>&1; then
echo "Reloading Nginx web server..."
sudo systemctl reload nginx || systemctl reload nginx || echo "Nginx reload skipped (no sudo permission)"
fi
# 6. Post-deploy health verification
echo "Executing health verification on local loopback..."
HTTP_STATUS=$(curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1/control/gate -H "Host: kccdemo.ochenstarik.ru" || true)
echo "Local Healthcheck HTTP Status: $HTTP_STATUS"
if [ "$HTTP_STATUS" = "200" ] || [ "$HTTP_STATUS" = "301" ] || [ "$HTTP_STATUS" = "302" ]; then
echo "=== [KCC Deploy] Health check: PASSED ==="
else
echo "WARNING: Health check returned status $HTTP_STATUS. Please verify Nginx configuration."
fi
echo "================================================================="
echo " [KCC Deploy] Release $TIMESTAMP successfully deployed and active!"
echo " URL: https://kccdemo.ochenstarik.ru"
echo "================================================================="

View file

@ -0,0 +1,78 @@
# ==============================================================================
# Krona Control Center - Nginx Server Block Configuration
# Domain: kccdemo.ochenstarik.ru
# Target Host: 178.212.13.102
# ==============================================================================
# HTTP -> HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name kccdemo.ochenstarik.ru;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
# Production HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name kccdemo.ochenstarik.ru;
# SSL Certificate configuration
ssl_certificate /etc/letsencrypt/live/kccdemo.ochenstarik.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/kccdemo.ochenstarik.ru/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Root pointing to atomic symlink
root /srv/kccdemo/current;
index index.html;
# Security Headers
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data: https:; connect-src 'self' ws: wss:; frame-ancestors 'none';" always;
# Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
# Static assets cache control
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Favicon and robots
location = /favicon.ico {
access_log off;
log_not_found off;
}
# SPA routing fallback: send all routes to index.html
location / {
try_files $uri $uri/ /index.html;
}
# Dedicated access and error logs
access_log /var/log/nginx/kccdemo_access.log;
error_log /var/log/nginx/kccdemo_error.log warn;
}

View file

@ -0,0 +1,117 @@
# Реестр приёмочных сценариев (Acceptance Tests) Krona Control Center
Все приёмочные сценарии автоматизированы в Playwright E2E сьюте (`e2e/11-control-center.spec.ts`) и покрывают как функциональные требования, так и устойчивость интерфейса.
---
### Сценарий 1: Поиск организации и открытие 360° Инспектора
- **Предусловия**: Оператор находится на странице `/control/organizations`.
- **Шаги**:
1. Ввести в поле поиска `"Северная"`.
2. Убедиться, что в таблице отображается только «Северная Ритейл Группа».
3. Нажать кнопку `"360° Карточка"`.
- **Ожидаемый результат**:
- Открывается боковой Drawer инспектора с карточкой организации, ИНН, датой регистрации.
- Доступны вкладки «Обзор», «Модули», «Инсталляции», «Биллинг».
- Переключение на вкладку «Модули» отображает установленные версии модулей и их статус.
---
### Сценарий 2: Подтверждение опасного действия с обязательным обоснованием
- **Предусловия**: Открыт 360° инспектор организации.
- **Шаги**:
1. Нажать кнопку `"Выдать Trial +14 дней"`.
2. Проверить появление модального диалога `ConfirmOperatorAction`.
3. Проверить, что кнопка подтверждения отключена при пустом поле обоснования.
4. Ввести обоснование `"Запрос от аккаунт-директора на пилотное тестирование филиала"`.
5. Нажать `"Подтвердить операцию"`.
- **Ожидаемый результат**:
- Диалог закрывается, дата окончания trial продлевается на 14 дней.
- В журнал аудита добавляется запись с SHA-256 хешем и введенным обоснованием.
---
### Сценарий 3: Фильтрация подписок, истекающих в течение 7 дней
- **Предусловия**: Оператор открывает раздел `/control/billing`.
- **Шаги**:
1. Активировать быстрый фильтр `"Истекают в течение 7 дней"`.
- **Ожидаемый результат**:
- Таблица фильтруется, остаётся только «ТехноПарк Восток» (срок окончания подписки через 2 дня).
- Отображается сумма регулярного платежа в рублях через `MoneyDisplay`.
---
### Сценарий 4: Мониторинг терминалов и выявление устаревших Android-касс
- **Предусловия**: Переход в `/control/installations`.
- **Шаги**:
1. Нажать на быстрый фильтр `"Устаревшие версии"`.
2. Проверить строки с бейджем `"Устарело"` (POS-терминал кассы №4, Android 11, клиент v1.8.4).
3. Нажать действие `"Отозвать токен"`.
- **Ожидаемый результат**:
- Открывается окно подтверждения с фиксацией отзыва токена устройства.
---
### Сценарий 5: Мониторинг узлов кластера и сбой Server Monitor (Circuit Breaker)
- **Предусловия**: Переход в `/control/infrastructure`.
- **Шаги**:
1. Проверить список нод: `node-krona-prod-01`, `node-krona-prod-02`, `node-krona-prod-03`.
2. В шапке нажать кнопку симуляции `"Simulate SM Outage"`.
- **Ожидаемый результат**:
- Вверху экрана появляется предупреждающий баннер `Server Monitor Unreachable (Fallback to Local Cache)`.
- Все экраны сохраняют интерактивность и читают данные из последнего валидного снимка IndexedDB.
---
### Сценарий 6: Создание инцидента из критического алерта
- **Предусловия**: Переход в `/control/incidents`.
- **Шаги**:
1. В списке обнаруженных аномалий выбрать `"Деградация p99 latency в кластере баз данных"`.
2. Нажать `"Создать инцидент P1"`.
3. Заполнить описание и назначить дежурного инженера.
- **Ожидаемый результат**:
- Инцидент регистрируется со статусом `Investigating` и уровнем `P1 Critical`.
---
### Сценарий 7: Публикация таргетированного системного оповещения
- **Предусловия**: Переход в `/control/announcements`.
- **Шаги**:
1. Заполнить форму объявления: заголовок `"Плановое ночное техобслуживание"`, уровень `Warning`.
2. Нажать кнопку `"Опубликовать"`.
3. В модальном окне ввести причину публикации.
- **Ожидаемый результат**:
- Оповещение появляется в списке активных трансляций.
---
### Сценарий 8: Управление Rollout-конвейером (Пауза / Возобновление)
- **Предусловия**: Переход в `/control/modules`.
- **Шаги**:
1. Выбрать модуль с активной раскаткой («Омниканальные коммуникации», фаза Pilot).
2. Нажать `"Поставить на паузу"`.
3. Ввести причину в модальном диалоге.
- **Ожидаемый результат**:
- Статус раскатки переходит в `"На паузе"`, конвейер замораживается.
---
### Сценарий 9: Смена роли оператора и проверка соблюдения RBAC
- **Предусловия**: Открыт любой раздел Control Center.
- **Шаги**:
1. В переключателе сессии в шапке выбрать роль `"Аудитор безопасности"`.
2. Перейти в раздел `/control/modules`.
- **Ожидаемый результат**:
- Кнопки запуска и остановки раскатки становятся неактивными (`disabled`) для аудитора.
- Повторное переключение на `"Владелец платформы"` восстанавливает полный доступ.
---
### Сценарий 10: Сохранение состояния при перезагрузке страницы (IndexedDB)
- **Предусловия**: В журнал аудита добавлены записи операторских действий.
- **Шаги**:
1. Зафиксировать количество строк в журнале `/control/audit`.
2. Выполнить полную перезагрузку страницы в браузере (`F5` / `page.reload()`).
- **Ожидаемый результат**:
- Интерфейс восстанавливает данные из локальной базы IndexedDB.
- Количество строк журнала аудита и SHA-256 хеши сохраняются неизменными.

View file

@ -0,0 +1,136 @@
# Руководство по развёртыванию Krona Control Center на VPS
## 1. Целевая инфраструктура и топология
| Параметр | Значение | Описание |
| :--- | :--- | :--- |
| **Домен** | `https://kccdemo.ochenstarik.ru` | Публичный защищённый домен демонстрационного стенда |
| **IP-адрес VPS** | `178.212.13.102` | Целевой сервер развёртывания |
| **Системный пользователь** | `kcc` | Изолированный непривилегированный Linux-пользователь |
| **Директория релизов** | `/srv/kccdemo/releases/<TIMESTAMP>` | Версионированные каталоги сборок |
| **Символическая ссылка** | `/srv/kccdemo/current` | Указывает на активный релиз (atomic switch) |
| **Логи Nginx** | `/var/log/nginx/kccdemo_access.log` | Доступ и аудит веб-сервера |
---
## 2. Статус внешнего подключения и диагностика доступа (Pre-flight Blocker)
В ходе подготовки развёртывания была выполнена сетевая диагностика хоста `178.212.13.102`:
1. **Сетевая доступность (Ping & Port 22)**:
- Хост `178.212.13.102` доступен, порт 22 (OpenSSH) открыт и принимает TCP-соединения.
2. **Аутентификация по SSH**:
- Попытка подключения: `ssh -i ~/.ssh/id_rsa kcc@178.212.13.102`
- Ответ сервера: `Permission denied (publickey)`.
3. **Причина блокировки**:
- Сервер VPS настроен на строгую аутентификацию исключительно по SSH-ключам (`PasswordAuthentication no`).
- Публичный ключ агента/рабочей станции не добавлен в файл `/home/kcc/.ssh/authorized_keys` на удаленном сервере.
4. **Решение для администратора / владельца платформы**:
- Вариант А: Добавить публичный ключ локальной машины в `/home/kcc/.ssh/authorized_keys` на VPS `178.212.13.102`.
- Вариант Б: Скопировать подготовленный каталог `deploy/kcc/` и директорию `dist/` на сервер через локальный доступ администратора и запустить `/srv/kccdemo/deploy-kcc.sh`.
---
## 3. Автоматизированный скрипт развёртывания (`deploy/kcc/deploy-kcc.sh`)
Скрипт обеспечивает атомарный деплой с нулевым временем простоя:
```bash
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="/srv/kccdemo"
RELEASES_DIR="$APP_DIR/releases"
CURRENT_LINK="$APP_DIR/current"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
NEW_RELEASE_DIR="$RELEASES_DIR/$TIMESTAMP"
echo "=== [KCC Deploy] Starting atomic release $TIMESTAMP ==="
mkdir -p "$NEW_RELEASE_DIR"
cp -r ./dist/* "$NEW_RELEASE_DIR/"
# Atomic switch
ln -sfn "$NEW_RELEASE_DIR" "$CURRENT_LINK"
# Keep last 3 releases
echo "=== [KCC Deploy] Pruning older releases (retaining last 3) ==="
cd "$RELEASES_DIR"
ls -1dt 20* | tail -n +4 | xargs -r rm -rf
echo "=== [KCC Deploy] Verifying local health ==="
curl -sk https://127.0.0.1/control/gate -H "Host: kccdemo.ochenstarik.ru" | grep -q "Krona Control Center" && echo "Health check: PASSED"
echo "=== [KCC Deploy] Release $TIMESTAMP successfully active! ==="
```
---
## 4. Конфигурация Nginx (`deploy/kcc/nginx-kccdemo.conf`)
Конфигурация включает заголовки безопасности, поддержку SPA маршрутизации и SSL:
```nginx
server {
listen 80;
server_name kccdemo.ochenstarik.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name kccdemo.ochenstarik.ru;
ssl_certificate /etc/letsencrypt/live/kccdemo.ochenstarik.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/kccdemo.ochenstarik.ru/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root /srv/kccdemo/current;
index index.html;
# Security Headers
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Gzip Compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
# Static Assets Caching
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# SPA Routing Fallback
location / {
try_files $uri $uri/ /index.html;
}
access_log /var/log/nginx/kccdemo_access.log;
error_log /var/log/nginx/kccdemo_error.log;
}
```
---
## 5. Процедура мгновенного отката (Instant Rollback)
В случае необходимости немедленного отката к предыдущей стабильной версии:
```bash
cd /srv/kccdemo
PREVIOUS_RELEASE=$(ls -1dt releases/20* | sed -n '2p')
if [ -n "$PREVIOUS_RELEASE" ]; then
echo "Rolling back to: $PREVIOUS_RELEASE"
ln -sfn "/srv/kccdemo/$PREVIOUS_RELEASE" /srv/kccdemo/current
systemctl reload nginx
echo "Rollback completed."
else
echo "No previous release found to rollback."
fi
```

View file

@ -0,0 +1,80 @@
# Фронтенд-контракты и Модели данных 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`.

View file

@ -0,0 +1,47 @@
# Матрица ролей и разрешений (RBAC) Krona Control Center
## 1. Инженерные роли операторов
В Control Center реализована строгая ролевая модель, отражающая реальные функции дежурной эксплуатации, разработки и безопасности платформы:
| Роль | Системный идентификатор | Описание |
| :--- | :--- | :--- |
| **Владелец платформы** | `platform_owner` | Полный неограниченный доступ ко всем контурам, инфраструктуре, биллингу и аварийным режимам. |
| **Администратор платформы** | `platform_admin` | Управление тенантами, эвакуация нод, рассылки, аварийные настройки (за исключением финансовых счетов). |
| **Оператор поддержки L2/L3** | `support_operator` | Диагностика тенантов, ведение инцидентов, просмотр инсталляций, выдача временных демо/trial. |
| **Менеджер биллинга** | `billing_manager` | Контроль задолженностей, выставление счетов, применение скидок, ручное продление подписок. |
| **Аудитор безопасности** | `security_auditor` | Read-only доступ ко всем экранам + полный доступ к неизменяемому криптографическому журналу аудита. Запрет на любые мутации. |
| **Релиз-инженер** | `release_manager` | Управление rollout-конвейером модулей, запуск Canary/Pilot/GA фаз, экстренная приостановка раскатки. |
---
## 2. Гранулярные права (Permissions)
- `control_center:read`: Просмотр базовых экранов (Обзор, Организации, Инсталляции).
- `control_center:write`: Редактирование параметров организаций, отправка рассылок.
- `control_center:billing_manage`: Операции с тарифами, счетами, продлением подписок.
- `control_center:node_evacuate`: Вывод узлов кластера из ротации (Drain/Evacuate).
- `control_center:incident_manage`: Создание инцидентов, изменение критичности, назначение ответственных.
- `control_center:rollout_manage`: Переключение стадий раскатки версий модулей платформы.
- `control_center:operator_audit`: Просмотр неизменяемого журнала аудита и экспорт крипто-цепочки.
---
## 3. Матрица соответствия Ролей и Прав
| Разрешение | `platform_owner` | `platform_admin` | `support_operator` | `billing_manager` | `security_auditor` | `release_manager` |
| :--- | :---: | :---: | :---: | :---: | :---: | :---: |
| `control_center:read` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| `control_center:write` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| `control_center:billing_manage` | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
| `control_center:node_evacuate` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| `control_center:incident_manage` | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| `control_center:rollout_manage` | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ |
| `control_center:operator_audit` | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ |
---
## 4. Контроль на уровне UI компонентов
- При отсутствии необходимого разрешения интерактивные кнопки мутаций автоматически блокируются (`disabled={!canPerform}`) с поясняющим tooltip или атрибутом `title="Недостаточно прав для данной операции"`.
- Попытка программного вызова защищенного действия отклоняется на уровне сервис-слоя с генерацией исключения `PermissionDeniedError` и немедленной фиксацией в журнале безопасности.

View file

@ -0,0 +1,29 @@
# Реестр маршрутов Krona Control Center
## 1. Базовые маршруты и изоляция
Все маршруты Control Center размещены в отдельном префиксе `/control/*` и изолированы от клиентских приложений платформы (`/app/*`) и лендинга (`/`).
| Путь | Название | Компонент | Доступ (Минимальная роль) | Описание |
| :--- | :--- | :--- | :--- | :--- |
| `/control/gate` | PIN-шлюз авторизации | `ControlGatePage` | Публичный внутри подсети (ввод PIN) | Инженерный шлюз ввода операторского PIN (по умолчанию: `8492` для демо). Выдаёт сессионный токен `kcc_gate_pass`. |
| `/control` | Редирект в пульт | `ControlRouteGuard` | Любая подтверждённая роль | Автоматический редирект на `/control/overview` |
| `/control/overview` | Сводка платформы | `OverviewPage` | `support_operator`+ (`control_center:read`) | Общий дашборд здоровья платформы, метрик MRR, статусов нод и инцидентов |
| `/control/organizations` | Реестр тенантов | `OrganizationsPage` | `support_operator`+ (`control_center:read`) | Список организаций, фильтрация, быстрый поиск и вызов 360° Drawer |
| `/control/billing` | Биллинг и Подписки | `BillingPage` | `billing_manager`+ (`control_center:billing_manage`) | Реестр подписок, контроль просрочек, счета в minor units |
| `/control/installations` | Парк инсталляций | `InstallationsPage` | `support_operator`+ (`control_center:read`) | Мониторинг POS/Android/Desktop терминалов, отзыв токенов |
| `/control/nodes` | Узлы инфраструктуры | `NodesPage` | `platform_admin`+ (`control_center:node_evacuate`) | Мониторинг CPU/RAM кластера, эвакуация нод, тест Circuit Breaker |
| `/control/modules` | Rollout-конвейер | `ModulesPage` | `release_manager`+ (`control_center:rollout_manage`) | Управление версиями, запуск Canary/Pilot/GA фаз, пауза раскатки |
| `/control/incidents` | Инциденты и Алерты | `IncidentsPage` | `support_operator`+ (`control_center:incident_manage`) | Реестр инцидентов P1-P4, назначение дежурного, перевод статусов |
| `/control/broadcasts` | Системные рассылки | `BroadcastsPage` | `platform_admin`+ (`control_center:write`) | Отправка баннеров тенантам с таргетингом по тарифам и модулям |
| `/control/audit` | Журнал аудита | `AuditPage` | `security_auditor`+ (`control_center:operator_audit`) | Неизменяемый журнал операций с проверкой валидности SHA-256 хеш-цепочки |
---
## 2. Шлюз защиты (ControlRouteGuard)
Компонент `ControlRouteGuard` реализует многоуровневую защиту:
1. **Проверка PIN-доступа**: Читает сессионный флаг `sessionStorage.getItem('kcc_gate_pass')`. Если отсутствует — перенаправляет на `/control/gate`.
2. **Проверка сессии оператора**: Читает активную роль из `sessionStorage.getItem('kcc_operator_session')`. Если отсутствует — инициализирует сессию по умолчанию (`platform_owner`).
3. **Проверка гранулярных разрешений**: Для защищенных разделов валидирует наличие необходимого permission в текущей роли оператора. При отсутствии прав рендерит защитное уведомление с предложением сменить роль или запросить доступ.
4. **Error Boundary**: Все дочерние экраны обёрнуты в локальный обработчик ошибок с кнопкой сброса кэша и перезагрузки интерфейса.

View file

@ -0,0 +1,62 @@
# Матрица состояний и переходов Krona Control Center
## 1. Состояния платформы (Platform Operation Modes)
| Состояние | Индикатор | Поведение интерфейса | Допустимые действия |
| :--- | :--- | :--- | :--- |
| **Normal** | Зеленый бейдж `Operational` | Штатный режим работы, все метрики обновляются в реальном времени | Все операции разрешены согласно матрице RBAC |
| **Degraded** | Янтарный бейдж `Degraded Performance` | Отказ части вторичных систем (например, Server Monitor), метрики отображаются из локального кэша | Разрешены аварийные действия, выдача оповещений |
| **Emergency Maintenance** | Красный пульсирующий баннер `Platform Maintenance Active` | Платформа переведена в аварийный сервисный режим; клиентские входы заблокированы информационным экраном | Доступны только действия владельца платформы по восстановлению |
---
## 2. Статусы клиентских организаций (Tenants)
```mermaid
stateDiagram-v2
[*] --> Trial: Регистрация / Демо
Trial --> Active: Оплата подписки
Trial --> Frozen: Истечение 14 дней без оплаты
Active --> PastDue: Сбой списания (Grace period 7 дней)
PastDue --> Active: Успешная повторная оплата
PastDue --> Frozen: Неуплата по истечении льготного периода
Frozen --> Active: Ручная разморозка / Погашение долга
Frozen --> Terminated: 90 дней неактивности / Расторжение
Terminated --> [*]
```
- **Trial**: Доступны базовые модули, ограниченный лимит пользователей. Возможно продление через `Выдать Trial +14 дней`.
- **Active**: Полнофункциональный доступ в рамках оплаченного тарифа.
- **Past Due**: Доступ сохраняется, отображается предупреждающий баннер в клиентском приложении.
- **Frozen**: Блокировка доступа всех пользователей тенанта (кроме чтения счетов). Требует обоснования при ручной заморозке.
- **Terminated**: Доступ аннулирован, данные архивированы.
---
## 3. Фазы Rollout-конвейера модулей
1. **Canary (10%)**: Первичное развёртывание новой версии модуля на 10% тестовых тенантов.
2. **Pilot (30%)**: Расширение на пилотную группу организаций.
3. **Staged (50%)**: Поэтапная раскатка на половину инфраструктуры.
4. **General Availability (GA, 100%)**: Полный переход всех клиентов на новую версию.
5. **Paused**: Экстренная заморозка конвейера при обнаружении аномалий.
6. **Rolled Back**: Откат на стабильную предыдущую версию.
---
## 4. Состояния узлов инфраструктуры (Cluster Nodes)
- **Healthy**: CPU < 75%, RAM < 80%, p99 latency < 50ms.
- **Warning**: Превышение порогов загрузки, авто-скейлинг подов.
- **Critical**: Отказ сетевого интерфейса или дисковой подсистемы.
- **Draining**: Нода выводится из балансировщика, активные сессии мягко мигрируют.
- **Evacuated**: Узел изолирован, нагрузка отсутствует, доступен для регламентных работ.
---
## 5. Статусы инсталляций и терминалов
- **Online**: Устройство активно, пинг получен менее 2 минут назад.
- **Offline**: Пинг отсутствует более 10 минут.
- **Outdated**: Версия клиентского ПО ниже минимально допустимой платформой (требуется обновление).
- **Revoked**: Токен авторизации устройства отозван оператором платформы.

View file

@ -0,0 +1,88 @@
# Krona Control Center — UX Спецификация
## 1. Архитектура и Назначение
Krona Control Center (KCC) — изолированный закрытый инженерный пульт владельца платформы Krona и дежурной инженерно-эксплуатационной команды.
### Ключевые архитектурные принципы
- **Изоляция контура**: KCC полностью отделён от административного кабинета клиентской организации (`/app/*`) и публичных страниц (`/`, `/demo`). Доступ организован в отдельном пространстве путей `/control/*`.
- **Защита шлюзом**: Доступ закрыт через `ControlRouteGuard` и PIN-гейт (`/control/gate`), требующий подтверждения операторского доступа (сессионный токен `kcc_gate_pass` + `operator_session`).
- **Строгая модель ролей (RBAC)**: 6 специализированных инженерных ролей с гранулярными правами доступа (`control_center:read`, `control_center:write`, `control_center:billing_manage`, `control_center:node_evacuate`, `control_center:incident_manage`, `control_center:rollout_manage`, `control_center:operator_audit`).
- **Неизменяемый журнал аудита**: Любое опасное или мутирующее действие требует модального подтверждения с обязательным указанием причины (минимум 5 символов), фиксацией затронутых сущностей и записью в криптографически связанный SHA-256 хеш-блокчейн в IndexedDB (`krona_control_center_db`).
- **Устойчивость к сбоям инфраструктуры (Circuit Breaker)**: Поддержка offline-first и degraded режимов с кэшированием последнего снимка состояния в IndexedDB при недоступности внешних мониторов или сетевых сбоях.
---
## 2. Навигация и Визуальная Иерархия
### Навигационное древо
1. **Обзор платформы (`/control/overview`)**:
- Верхний статус-бар: Режим среды (Production), активная инженерная роль, индикатор синхронизации IndexedDB, кнопка аварийного режима (Maintenance), экстренный выход.
- Сводные KPI-метрики: активные организации, совокупный MRR, здоровье узлов кластера, активные инциденты и предупреждения.
- Виджеты оперативного контроля: критические алерты, статус rollout-конвейера, географическое распределение нагрузок.
2. **Организации и 360° Инспектор (`/control/organizations`)**:
- Таблица тенантов с фильтрацией по тарифным планам (`enterprise`, `business`, `starter`), статусам (`active`, `past_due`, `frozen`, `trial`) и быстрому поиску по названию/ИНН/домену.
- Вызов контекстного 360° инспектора (Drawer) без потери контекста таблицы.
3. **Биллинг и Подписки (`/control/billing`)**:
- Фильтры истекающих подписок (окно 7 дней, просроченные платежи).
- Сводка по Minor Units (копейки) с форматированием без плавающей точки.
- История платежей, выставление счетов, ручное продление trial.
4. **Инсталляции и Терминалы (`/control/installations`)**:
- Учёт парка POS/Android/Desktop терминалов и мобильных приложений.
- Мониторинг устаревших версий (flag `outdated`), времени последнего пинга и принудительный отзыв токенов сессий (`Revoke Token`).
5. **Инфраструктура и Узлы (`/control/nodes`)**:
- Мониторинг кластерных нод (CPU, RAM, Disk IO, p99 latency).
- Действие вывода ноды из ротации (`Drain / Evacuate Node`).
- Имитация сбоя сервера мониторинга для верификации Circuit Breaker.
6. **Rollout и Каталог модулей (`/control/modules`)**:
- Управление версиями модулей платформы.
- Фазы конвейера: `Canary (10%)`, `Pilot (30%)`, `Staged (50%)`, `GA (100%)`.
- Оперативные действия: `Start Rollout`, `Pause`, `Resume`, `Rollback`.
7. **Инциденты и Алерты (`/control/incidents`)**:
- Матрица тяжести: `P1 Critical`, `P2 Major`, `P3 Warning`, `P4 Info`.
- Эскалация, назначение дежурного инженера, перевод в `In Progress`, `Mitigated`, `Resolved`.
8. **Системные рассылки (`/control/broadcasts`)**:
- Таргетинг по тарифам и модулям тенантов.
- Уровни важности: `info`, `warning`, `critical_maintenance`.
9. **Журнал аудита (`/control/audit`)**:
- Хронологический реестр операций с проверкой валидности SHA-256 хеш-цепочки.
- Экспорт в CSV/JSON.
---
## 3. Контекстный 360° Инспектор (Drawer)
Шторка детального инспектирования вызывается с правой стороны экрана (600px на десктопе, 100% на мобильных экранах):
- **Вкладка «Обзор»**: Карточка организации, ИНН, домен, дата создания, активный SLA, текущий баланс и лимиты пользователей.
- **Вкладка «Модули»**: Список подключенных сервисных модулей с версиями и статусами работоспособности.
- **Вкладка «Инсталляции»**: Привязанные терминалы и кассы с версиями клиента.
- **Вкладка «Биллинг»**: График выставления счетов, статус продления и скидки.
- **Панель быстрых действий оператора**:
- `Выдать Trial +14 дней` (требует подтверждения с фиксацией причины).
- `Заморозить доступ` / `Разморозить` (критическая операция).
- `Сбросить 2FA администраторов` (операция безопасности).
- `Экспорт данных тенанта` (GDPR/152-ФЗ compliance).
---
## 4. Паттерн подтверждения опасных операций (ConfirmOperatorAction)
Любое деструктивное или влияющее на клиентов действие открывает диалоговое окно `ConfirmOperatorAction`:
1. **Предупреждение о последствиях**: Четкое перечисление затрагиваемых сущностей (например, «Будет заблокирован доступ 120 пользователей»).
2. **Обязательное обоснование (`action-reason-input`)**: Поле ввода причины выполнения с валидацией минимальной длины (не менее 5 символов).
3. **Кнопка подтверждения с семантическим цветом**: Красный (`bg-red-600`) для необратимых/блокирующих действий, янтарный (`bg-amber-600`) для сервисных операций.
4. **Хеширование записи аудита**: Запись немедленно хешируется с предыдущим хешем по схеме:
`hash = SHA-256(prevHash + timestamp + operatorRole + actionType + entityId + reason)`
и сохраняется в локальное постоянное хранилище IndexedDB.
---
## 5. Дизайн-система: Темная инженерная тема
Интерфейс спроектирован по канонам современных Mission-Control дашбордов:
- **Цветовая палитра**: Глубокий slate/zinc фон (`bg-zinc-950`, `bg-zinc-900`), контрастные границы (`border-zinc-800`), четкая типографика (`text-zinc-100`, `text-zinc-400`).
- **Семантические акценты**:
- `Зеленый (Emerald)`: Нормальная работа узла, активная подписка, GA-статус.
- `Янтарный (Amber)`: Предупреждение, истекающий trial, пауза раскатки.
- `Красный (Rose/Red)`: P1 инцидент, отказ узла, заблокированная организация.
- `Синий/Фиолетовый (Indigo/Violet)`: Канареечные релизы, системные оповещения.
- **Адаптивность (Zero Horizontal Overflow)**:
- Desktop (1440×900+): Полноразмерный сайдбар, многоколоночные таблицы, плавающий Drawer 600px.
- Tablet (768×1024): Сворачиваемый сайдбар, горизонтальная прокрутка таблиц внутри изолированных контейнеров.
- Mobile (390×844): Компактный мобильный заголовок, off-canvas навигация, карточный вид для таблиц.