# AWatch-rus Portal

## Назначение

Портал является рабочим кабинетом для трех ролей:

- руководитель: пульс организации, активность, подразделения, риски;
- ИБ: риск-сигналы, события безопасности, материалы проверки;
- расследователь: карточка инцидента, причины, проверяемые источники, отчет.

## Главные экраны

- `Обзор` - сводка руководителя и главный вывод.
- `Сотрудники` - карточки сотрудников и объяснение индекса.
- `Подразделения` - сравнение групп, тренды и ответственные.
- `Риски` - контроль безопасности только для чтения.
- `Расследования` - инциденты, материалы проверки и автоматическая карточка расследования только для чтения.
- `Сетевой периметр` - внешний сетевой контекст только для чтения.
- `Отчеты` - текстовый отчет, печать/PDF, выгрузка данных и управленческий текст.
- `Настройки` - параметры расчета только для чтения.

## Ролевые представления

Во вкладке `Обзор` есть переключатель представления:

- `Руководитель` - главный вывод, сводка руководителя, риски подразделений и
  карта рисков;
- `Безопасность` - записи, которые требуют проверки, связь рисков и
  активности, агрегированные события безопасности за 24 часа, расследования,
  аудит решений и материалы расследования;
- `Эксплуатация` - полнота данных, качество сбора, ошибки и телеметрия рабочих
  мест.

Переключатель не меняет модель данных и не создает новые API. Он только
группирует существующие блоки портала под разные категории пользователей:
директор, сотрудник безопасности и администратор эксплуатации.

## События безопасности

Портал поддерживает необязательный источник агрегированных событий безопасности
из ClickHouse. По умолчанию он выключен и не влияет на работу портала.

Если источник включен, портал показывает только сводные числа за 24 часа:
общее количество событий, неуспешные и подозрительные входы, RDP-сессии,
изменения учетных записей, ошибки агентов и топ подразделений. Сырые журналы и
SIEM-представление не выводятся.

Подробности настройки: [SECURITY_EVENTS_CLICKHOUSE_RU.md](SECURITY_EVENTS_CLICKHOUSE_RU.md).

## Загрузка и актуальность данных

В верхней части портала есть глобальная полоса `Загрузка и актуальность
данных`. Она показывает, что сейчас происходит с данными, и не смешивает
состояния `нет данных` и `данные еще загружаются`.

Видимые статусы:

- `Загрузка данных` - портал получает данные и готовит экран;
- `Данные готовы` - данные успешно загружены и экран актуален;
- `Данные отсутствуют` - источники ответили, но полезных записей для выбранного
  раздела или периода нет;
- `Данные устарели` - показаны ранее загруженные данные, новое фоновое
  обновление не завершилось;
- `Ошибка получения данных` - первичная загрузка не удалась, актуальных данных
  на экране нет.

Этапы прогресса:

- `Получение данных`;
- `Расчёт показателей`;
- `Формирование главного вывода`;
- `Подготовка разделов`.

Во время загрузки портал показывает заготовки карточек и текст `Загрузка
данных`; пустые таблицы и сообщения `Нет данных` не выводятся до завершения
загрузки. После успешного обновления отображается время последнего обновления.
При состоянии `Данные устарели` старый экран остается доступным, но сверху
появляется предупреждение о неудачном обновлении.

## Сводка руководителя

Показывает:

- сотрудников в работе;
- средний индекс активности;
- WARN/FAIL подразделения;
- критические риски;
- недельный тренд;
- качество данных;
- топ-5 лучших и проблемных подразделений;
- карту рисков;
- блок `Требует внимания`.

## Качество данных

Портал показывает карточку `Качество данных` в `Обзор` и
`Отчеты`. Это управленческий вывод о том, можно ли использовать текущий
`Индекс активности` и отчеты как подтвержденные показатели.

API сохраняет старое поле `agent_quality` и дополнительно отдает
`agent_quality_explain`:

- `status`;
- `title`;
- `summary`;
- `recommendation`;
- `kpi_accepted` - участвуют ли данные в показателях.

Цвета статусов:

- `OK` - зеленый, показатели подтверждены основным источником;
- `WARNING` - желтый, данные собраны резервным способом;
- `DEGRADED` - оранжевый, данные нельзя использовать как доказательные показатели;
- `UNKNOWN` - серый, агент не передал диагностику качества.

Карточка сначала показывает управленческий вывод, участвуют ли данные в показателях, и
рекомендацию. Технические поля доступны в раскрываемом блоке:

- источник коллектора;
- всего сессий;
- активных сессий;
- удаленных сеансов;
- ошибка коллектора, если она есть.

Если диагностика отсутствует, статус `UNKNOWN`, рекомендация - обновить Rust
agent и проверить поступление telemetry JSONL. Если источник `local_fallback`,
портал прямо пишет: `Диагностический режим, данные не засчитываются в показатели активности`.

## Стабильность агента за 7 дней

Портал показывает мини-блок `Стабильность агента за 7 дней`. Он отвечает на
вопрос, можно ли доверять недельным показателям, а не только текущему срезу.

`GET /api/reports` отдает:

- `agent_quality_history` - последняя запись качества по каждому дню за
  7-дневное окно;
- `agent_quality_history_summary` - сводка по дням.

Элемент `agent_quality_history` содержит:

- `date`;
- `status`;
- `source`;
- `kpi_accepted`;
- `collector_error`, если он есть.

Сводка считает:

- сколько дней были `OK`;
- сколько дней были `WARNING`, `DEGRADED` или `UNKNOWN`;
- процент дней, когда показатели были подтверждены.

Если за 7 дней меньше 5 дней `OK`, портал и краткий вывод показывают:
`Показатели требуют проверки: нестабильный сбор данных агента`.

## Качество данных по рабочим местам

Портал показывает карточку `Качество данных по рабочим местам`. Она отвечает
на управленческий вопрос: какие узлы дают подтвержденные данные, а какие
снижают доверие к показателям.

`GET /api/reports` отдает:

- `agent_quality_nodes` - последняя запись качества по каждому
  `hostname`, при его отсутствии по `machine_id`, иначе `unknown`;
- `agent_quality_nodes_summary` - сводка по узлам.

Элемент `agent_quality_nodes` содержит:

- `hostname`;
- `last_seen_utc`;
- `source`;
- `status`;
- `kpi_accepted`;
- `sessions_total`;
- `rdp_sessions`;
- `collector_error`, если он есть;
- `recommendation`.

Сводка содержит:

- `total_nodes`;
- `ok_nodes`;
- `degraded_nodes` - узлы в `WARNING` или `DEGRADED`;
- `unknown_nodes`;
- `accepted_kpi_nodes_pct`.

Если `accepted_kpi_nodes_pct < 80` и узлы есть, краткий вывод показывает:
`Показатели требуют проверки: менее 80% рабочих мест дают подтвержденные данные`.

Главная страница не перегружается: показывается сводка и таблица максимум из
10 проблемных узлов. Источник `local_fallback` никогда не подтверждает показатели.

## Полнота данных

Портал показывает карточку `Полнота данных`. Она отвечает на вопрос,
насколько текущий `Индекс активности` репрезентативен по всему парку рабочих
мест.

Источник ожидаемого состава парка задается JSON-файлом:

- CLI/env: `--expected-nodes-path` или `DETMIR_PORTAL_EXPECTED_NODES_PATH`;
- default: `config/expected_nodes.json`;
- публичный пример: `config/expected_nodes.example.json`.

Формат:

```json
{
  "nodes": [
    {
      "hostname": "HOST-EXAMPLE-001",
      "department": "Бухгалтерия",
      "owner": "OWNER-EXAMPLE",
      "criticality": "normal"
    }
  ]
}
```

`GET /api/reports` отдает `agent_coverage_sla`:

- `expected_nodes` - сколько рабочих мест ожидается по конфигу;
- `reporting_nodes_24h` - сколько узлов прислали свежую за 24 часа
  телеметрию, принятую в показатели;
- `stale_nodes` - узлы есть в telemetry, но последняя запись старше 24 часов;
- `missing_nodes` - узлы из expected list не найдены в telemetry;
- `coverage_pct` - процент узлов, подтверждающих показатели;
- `freshness_pct` - процент узлов со свежей telemetry независимо от качества
  источника;
- `sla_status` - статус полноты данных: `OK`, `WARNING`, `CRITICAL` или `UNKNOWN`;
- `problem_nodes` - максимум выводится в UI по 10 проблемным узлам.

Правила полноты данных:

- `coverage_pct >= 90%` - `OK`;
- `75-89%` - `WARNING`;
- `<75%` - `CRITICAL`;
- если expected list отсутствует или пустой - `UNKNOWN`.

Если статус `CRITICAL`, краткий вывод показывает:
`Полнота данных критически недостаточна: показатели нельзя считать репрезентативными`.

Если статус `WARNING`, краткий вывод показывает:
`Показатели требуют проверки: часть рабочих мест не присылает свежую телеметрию`.

Источник `local_fallback` может повышать `freshness_pct`, если телеметрия
свежая, но не повышает `coverage_pct` и не засчитывается как подтвержденные
показатели.

## Переход от риска к расследованию

Кнопка `Открыть расследование` переводит пользователя в карточку только для чтения.

Карточка содержит:

- номер;
- риск;
- подразделение;
- ответственного;
- индекс активности;
- отклонение;
- статус;
- краткое описание;
- почему это риск;
- что проверить;
- рекомендуемые действия;
- материалы расследования;
- дату формирования.

Предупреждение обязательно:

```text
Расследование сформировано автоматически. Решение принимает ответственный сотрудник.
```

## Проверка

Smoke-тест:

```bash
node scripts/detmir-portal-tabs-smoke.mjs
```

Тест проверяет все вкладки, настройки только для чтения и переход от риска к расследованию.

Проверка страницы архитектуры и CSS:

```bash
DETMIR_PORTAL_SMOKE_URL=http://127.0.0.1:8720/portal/ node scripts/detmir-portal-tabs-smoke.mjs
curl -fsS http://127.0.0.1:8720/portal/architecture | grep -E 'Rust Agent|PowerShell Provider|implemented|planned|future'
rg -n '[0-9]+ (px|fr|rem|em|%)' adk-rust/crates/detmir-portal/src/static/app.css || true
```

Ожидаемый результат:

- `/portal/architecture` возвращает `200`;
- страница содержит `Rust Agent`, `PowerShell Provider`, `implemented`,
  `planned`, `future`;
- команда `rg` не находит разорванные CSS-единицы вида `1 px`, `8 px`,
  `1 fr`.
