# Business Risk

`Business Risk` - расчетный слой AWatch-rus, который показывает не
просто активность сотрудников, а зоны организационного риска по подразделениям.

Над ним расположен основной управленческий слой `Risk Narrative`: единая
связанная картина риска для руководителя. Он не создает новых сущностей и не
добавляет workflow, а связывает уже рассчитанные слои в один вывод:
`Trust KPI → Agent Coverage → Business Risk → Risk Heatmap → Security
Correlation → Incident Candidates → Cases`.

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

Слой предназначен для руководителя и собственника бизнеса. Он отвечает на
вопросы:

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

Business Risk и Risk Narrative не являются автоматическим обвинением
сотрудников или подразделений. Это read-only приоритизация управленческой
проверки.

## API

`GET /api/reports` отдает массив `business_risk`.

Элемент массива:

- `department` - подразделение;
- `trust_score` - доверие к KPI в процентах;
- `activity_score` - индекс активности подразделения в процентах;
- `trend` - `RISING`, `STABLE`, `FALLING` или `UNKNOWN`;
- `risk_level` - `LOW`, `MEDIUM`, `HIGH` или `CRITICAL`;
- `reasons` - список человеко-понятных причин риска;
- `recommendation` - рекомендуемое действие;
- `problem_nodes_count` - сколько проблемных узлов относится к подразделению;
- `missing_nodes_count` - сколько ожидаемых узлов не прислали telemetry;
- `stale_nodes_count` - сколько узлов присылали telemetry, но данные устарели.

Также `GET /api/reports` отдает управленческую сводку и историю:

- `executive_dashboard` - сводка руководителя по Trust KPI, покрытию агентов,
  рискам, кандидатам, делам и готовности расследований;
- `risk_heatmap` - карта рисков подразделений по Trust KPI, активности,
  покрытию агентов, открытым делам и кандидатам в инциденты;
- `security_correlation` - аналитическая связка Workforce и Security:
  активность, Trust KPI, Business Risk, кандидаты и открытые дела;
- `business_risk_history` - timeline риска по подразделениям;
- `business_risk_history_summary` - сводка динамики.
- `risk_incident_candidates` - read-only кандидаты для ручной проверки.

`executive_dashboard`:

- `trust_kpi_score` - доверие к KPI активности в процентах, если доступно;
- `agent_coverage_pct` - покрытие ожидаемых рабочих мест агентами, если
  настроен список expected nodes;
- `high_risk_departments` - до 10 подразделений с уровнем риска `HIGH` или
  `CRITICAL`;
- `critical_candidates` - до 10 кандидатов в инциденты с уровнем `HIGH` или
  `CRITICAL`;
- `open_cases` - количество открытых дел;
- `resolved_cases_30d` - количество дел, закрытых за последние 30 дней;
- `forensics_readiness` - готовность доказательного слоя: `READY`, `PARTIAL`,
  `OBSERVE` или `LIMITED`;
- `summary.main_risk` - главный риск текущего среза;
- `summary.main_improvement` - главное подтвержденное улучшение;
- `summary.main_data_gap` - главный пробел в данных.
- `summary.risk_narrative_status` - optional единый статус связанной картины
  риска: `NORMAL`, `ATTENTION`, `HIGH_RISK` или `CRITICAL`;
- `summary.main_risk_cause` - optional связанная причина риска:
  Trust KPI, Agent Coverage, Risk Heatmap, Business Risk, Security
  Correlation, Incident Candidates, Cases и готовность Forensics.

`risk_heatmap`:

- `department` - подразделение;
- `trust_kpi_score` - доверие к KPI активности, если доступно;
- `activity_score` - индекс активности подразделения, если доступен;
- `agent_coverage_pct` - оценка покрытия агентов; если список expected nodes
  не настроен, поле отсутствует, а UI показывает `UNKNOWN`;
- `business_risk_level` - текущий уровень Business Risk;
- `open_cases` - открытые дела по кандидатам этого подразделения;
- `critical_candidates` - кандидаты `HIGH`/`CRITICAL`;
- `heat_level` - итоговая зона карты: `LOW`, `MEDIUM`, `HIGH`,
  `CRITICAL` или `UNKNOWN`.
- `links` - optional read-only переходы к уже существующим слоям портала:
  Trust KPI, Agent Coverage, Business Risk, Risk Heatmap, Security
  Correlation, Incident Candidates и Cases.
- `summary` - optional связанная строка
  `Trust → Coverage → Business Risk → Risk Heatmap → Security Correlation →
  Candidates → Cases → вывод`.

`security_correlation`:

- `department` - подразделение;
- `trust_kpi_score` - доверие к KPI активности, если доступно;
- `activity_score` - индекс активности подразделения, если доступен;
- `business_risk_level` - уровень Business Risk;
- `critical_candidates` - число кандидатов `HIGH`/`CRITICAL`;
- `open_cases` - открытые дела по подразделению;
- `correlation_score` - сила связки Workforce и Security от 0 до 100;
- `correlation_reason` - человеко-понятное объяснение связи, например
  `низкий Trust KPI + высокий риск` или
  `снижение активности + рост кандидатов`.
- `explanation` - optional управленческое объяснение: какие слои связаны,
  почему корреляция высокая и что это значит для руководителя.

Элемент `business_risk_history`:

- `date` - дата daily point;
- `department` - подразделение;
- `risk_level` - `LOW`, `MEDIUM`, `HIGH` или `CRITICAL`;
- `trust_score` - доверие к KPI на момент расчета;
- `activity_score` - активность подразделения;
- `reasons` - причины риска для этой точки.

`business_risk_history_summary`:

- `departments_worsened` - сколько подразделений ухудшили риск;
- `departments_improved` - сколько подразделений улучшили риск;
- `stable_high_risk` - сколько подразделений 3+ дня остаются в `HIGH`/`CRITICAL`;
- `new_high_risk` - сколько подразделений впервые вошли в `HIGH`/`CRITICAL`.

Элемент `risk_incident_candidates`:

- `id` - стабильный идентификатор кандидата;
- `department` - подразделение, если известно;
- `owner` - ответственный, если известен;
- `hostname` - рабочее место, если кандидат связан с узлом;
- `risk_level` - ориентировочный уровень риска;
- `reason` - причина постановки в очередь проверки;
- `evidence` - технические признаки, на которых основан кандидат;
- `first_seen_utc` - первое наблюдение;
- `last_seen_utc` - последнее наблюдение;
- `recommendation` - рекомендуемое действие.
- `incident_review` - статус проверки кандидата.
- `incident_review_audit` - история изменений статуса проверки кандидата.

`incident_review`:

- `candidate_id` - идентификатор кандидата;
- `status` - `NEW`, `IN_REVIEW`, `CONFIRMED`, `FALSE_POSITIVE` или `POSTPONED`;
- `reviewer` - проверяющий, если указан;
- `comment` - комментарий проверки;
- `updated_at` - время последнего изменения статуса.

`incident_review_audit`:

- `candidate_id` - идентификатор кандидата;
- `old_status` - предыдущий статус;
- `new_status` - новый статус;
- `reviewer` - проверяющий, если указан;
- `comment` - комментарий к изменению;
- `changed_at_utc` - время изменения в UTC.

Для изменения review-статуса используется:

```http
POST /api/incident-review
```

Пример тела:

```json
{
  "candidate_id": "risk-candidate-example",
  "status": "IN_REVIEW",
  "reviewer": "operator",
  "comment": "Назначена ручная проверка"
}
```

Хранение пока файловое:

```text
<state_dir>/data/incident_reviews.json
<state_dir>/data/incident_review_audit.jsonl
```

Если файла нет, все кандидаты отображаются как `NEW`.
Если audit-файла нет, портал продолжает работать, а история изменений
отображается как отсутствующая. Audit JSONL является append-only журналом:
история изменений не удаляется и не перезаписывается при смене статуса.

## Investigation Pack Export

Для каждого кандидата можно выгрузить доказательный пакет расследования:

```http
GET /api/investigation-pack/{candidate_id}
GET /api/investigation-pack/{candidate_id}?format=markdown
```

Пакет не создает инцидент автоматически и не меняет review-статус. Это только
экспорт текущего кандидата для руководителя, ИБ или внутренней проверки.

JSON/Markdown содержит:

- `candidate_id`;
- подразделение, ответственного и рабочее место;
- уровень риска;
- причины риска;
- evidence-признаки;
- первое и последнее наблюдение;
- текущий review-статус и комментарий;
- `review_audit_history`;
- `trust_kpi_snapshot`;
- `agent_quality_snapshot`;
- `business_risk_snapshot`.

Markdown-версия содержит разделы:

```text
Краткое резюме
Причины риска
Доказательства
История проверки
Снимок доверия к KPI
Качество данных агента
Бизнес-риск
Вывод
```

Если audit-файл отсутствует, пакет всё равно формируется, а раздел истории
проверки показывает, что изменения не зафиксированы.

## Логика риска

На риск влияют:

- низкий `trust_score`;
- низкий `activity_score`;
- падающий тренд активности;
- отсутствие телеметрии;
- наличие проблемных узлов в SLA покрытия агентов.

`local_fallback` не считается подтвержденным KPI. Если телеметрия свежая, но
пришла из диагностического fallback-источника, она может подтверждать факт
наличия агента, но снижает доверие к KPI и повышает бизнес-риск.

Типовые причины:

- `низкий Trust KPI`;
- `низкая активность`;
- `падающий тренд`;
- `нет свежей телеметрии`;
- `много проблемных узлов`.

## UI

В портале отображается карточка `Риски подразделений`.

Показывается ТОП-10 подразделений с максимальным риском:

- подразделение;
- уровень риска;
- причины;
- рекомендация.

Карточка `Динамика рисков` показывает:

- ухудшившиеся подразделения;
- улучшившиеся подразделения;
- стабильный высокий риск;
- новый высокий риск;
- последние точки timeline с причинами.

Карточка `Кандидаты в инциденты` показывает TOP-10 записей для ручной
проверки. Это не автоматическое создание инцидента и не подтвержденное
нарушение.

В карточке можно сменить review-статус кандидата:

- `В проверку` -> `IN_REVIEW`;
- `Подтвердить` -> `CONFIRMED`;
- `Ложный` -> `FALSE_POSITIVE`;
- `Отложить` -> `POSTPONED`.

Для каждого кандидата портал показывает текущий статус, проверяющего, время
последнего изменения, последний комментарий и раскрываемую историю изменений.
Это формирует доказательную цепочку:

```text
кандидат -> проверка -> решение -> кто/когда/почему
```

Кнопка `Скачать пакет расследования` выгружает Markdown-пакет по выбранному
кандидату без создания инцидента.

## Case Management

Подтвержденный кандидат можно вручную перевести в дело. Дело не создается
автоматически: оператор должен нажать `Создать дело` у кандидата со статусом
`CONFIRMED`.

Сущность `case`:

- `case_id`;
- `candidate_id`;
- `title`;
- `status`;
- `owner`;
- `created_at_utc`;
- `updated_at_utc`;
- `summary`;
- `decision`.

Статусы:

```text
OPEN
IN_PROGRESS
RESOLVED
REJECTED
ARCHIVED
```

API:

```http
POST /api/cases
GET /api/cases
GET /api/cases/{case_id}
GET /api/cases/{case_id}?format=markdown
POST /api/cases/{case_id}/status
```

Хранение:

```text
<state_dir>/data/cases.json
```

Правила:

- дело создается только из `CONFIRMED` кандидата;
- повторное создание для того же кандидата возвращает существующее активное
  дело, если оно не архивировано;
- дело содержит ссылку на кандидата, решение и текущий Investigation Pack;
- Markdown-экспорт карточки дела включает пакет расследования, статус
  проверки, audit review и решение по делу;
- создание/смена статуса дела не создает обычный инцидент автоматически.

## Markdown

Оперативный отчет выводит раздел `Связанная картина риска` первым
содержательным разделом после заголовка, даты и краткого итога. Это главный
управленческий вывод: что происходит, почему это риск и какие слои это
подтверждают.

Такой же порядок используется в UI `/portal` и `/reports`: сначала отдельная
карточка `Связанная картина риска`, затем `Сводка руководителя`, далее
доверие к KPI/качество данных, Business Risk/Heatmap/Correlation, кандидаты,
дела и технические детали. В `/api/reports` narrative остается в существующих
обратно совместимых полях: первый `executive_points[]` и
`executive_dashboard.summary.main_risk_cause`.

Оперативный отчет содержит разделы:

```text
## Связанная картина риска
## Сводка руководителя
## KPI
## Достоверность данных
## SLA покрытия агентов
## Карта рисков подразделений
## Корреляция Workforce ↔ Security
## Риски подразделений
## Динамика бизнес-рисков
## Кандидаты в инциденты
## Проверка кандидатов в инциденты
## Аудит проверки инцидентов
```

Раздел можно использовать в PDF/Markdown-отчете для руководителя.

## Executive Summary

Executive summary сначала показывает связанный управленческий вывод по Risk
Narrative, а затем только поддерживающие технические пункты. Отдельные строки
по Business Risk и кандидатам не дублируют главный вывод, если эти причины уже
вошли в narrative.

Формат:

```text
Главный управленческий вывод: В подразделении Бухгалтерия связаны слои:
Trust KPI 50%, Agent Coverage 80%, Risk Heatmap HIGH, Business Risk MEDIUM,
Security Correlation 40/100, Incident Candidates 1, Cases 0. риск связан из-за
слабого Trust KPI, падения активности, слабого покрытия агентов.
```

Если подразделение 3+ дня подряд находится в `HIGH` или `CRITICAL`,
добавляется отдельный вывод:

```text
Подразделение Бухгалтерия сохраняет высокий риск несколько дней подряд.
```

Также выводятся до 3 кандидатов в инциденты:

```text
Кандидат в инцидент risk-candidate-...: HIGH — KPI не принят
```

## Ограничения

- Это proxy-модель управленческого риска, а не юридическое заключение.
- Для точной интерпретации нужны корректные expected nodes, стабильная
  telemetry и актуальные department rollups.
- Если данных по подразделению нет, риск может повышаться из-за недостаточной
  доказательной базы, а не из-за фактической работы сотрудников.
- `risk_incident_candidates` - только очередь `review required`; реальные
  инциденты создаются отдельно ответственным сотрудником.
- Смена `incident_review.status` не создает запись в обычной очереди
  `incidents` и не подтверждает нарушение автоматически.
