feat(workforce): add ClickHouse workforce analytics contour
This commit is contained in:
@@ -10,13 +10,16 @@
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
1. Скопировать шаблон окружения:
|
||||
1. Создать приватный файл окружения вне репозитория:
|
||||
|
||||
```bash
|
||||
cp scripts/detmir-support.env.example scripts/detmir-support.env
|
||||
mkdir -p "$HOME/.config/awatch-rus"
|
||||
cp scripts/detmir-support.env.example "$HOME/.config/awatch-rus/detmir-support.env"
|
||||
chmod 600 "$HOME/.config/awatch-rus/detmir-support.env"
|
||||
```
|
||||
|
||||
2. Внести фактические IP/имена хостов, сервисы, пути бэкапов, VM IDs и SSH-данные.
|
||||
Реальные пароли и приватные ключи не должны храниться в репозитории.
|
||||
|
||||
3. Запустить нужный режим:
|
||||
|
||||
@@ -32,6 +35,38 @@ cp scripts/detmir-support.env.example scripts/detmir-support.env
|
||||
./scripts/detmir-support-run.sh --scope daily --output-dir /var/log/detmir-support
|
||||
```
|
||||
|
||||
## Файл окружения
|
||||
|
||||
Скрипт загружает параметры в таком порядке:
|
||||
|
||||
1. файл из переменной `DETMIR_SUPPORT_ENV_FILE`, если она задана;
|
||||
2. `scripts/detmir-support.env`, если он существует;
|
||||
3. `$HOME/.config/awatch-rus/detmir-support.env`, если локального файла в
|
||||
репозитории нет.
|
||||
|
||||
Рекомендуемый промышленный вариант — хранить секреты в
|
||||
`$HOME/.config/awatch-rus/detmir-support.env`, а в репозитории держать только
|
||||
`scripts/detmir-support.env.example`.
|
||||
|
||||
Минимальные параметры для текущего контура DetMir:
|
||||
|
||||
```bash
|
||||
DETMIR_SUPPORT_PVE_HOST=10.10.10.2
|
||||
DETMIR_SUPPORT_AW_HOST=10.10.10.13
|
||||
DETMIR_SUPPORT_WEB_HOST=10.10.10.2
|
||||
DETMIR_SUPPORT_WEB_TLS_HOST=10.10.10.2
|
||||
DETMIR_SUPPORT_WINDOWS_HOST=192.168.100.18
|
||||
DETMIR_SUPPORT_SURICATA_HOST=10.10.10.2
|
||||
|
||||
DETMIR_SUPPORT_SSH_USER=igor
|
||||
DETMIR_SUPPORT_AW_SSH_USER=igor
|
||||
DETMIR_SUPPORT_PVE_BACKUP_DIRS=/var/lib/pve/local-btrfs/dump
|
||||
```
|
||||
|
||||
Парольные переменные вида `DETMIR_SUPPORT_AW_SSH_PASSWORD` допускаются только в
|
||||
локальном приватном env-файле. В документации, Git и отчетах пароли не
|
||||
фиксируются.
|
||||
|
||||
## Что делает скрипт
|
||||
|
||||
Собираются проверки по режиму:
|
||||
@@ -40,6 +75,20 @@ cp scripts/detmir-support.env.example scripts/detmir-support.env
|
||||
- **weekly**: всё из `daily` + расширенные проверки логов и журналов.
|
||||
- **monthly**: всё из `weekly` + проверка апдейтов и базовая фиксация документов/DR-процесса.
|
||||
|
||||
Актуальные особенности текущего контура:
|
||||
|
||||
- операторский gateway находится на `10.10.10.2`, а не на историческом
|
||||
`10.10.10.11`;
|
||||
- web health endpoint: `https://10.10.10.2/healthz`, ожидаемый ответ `200`;
|
||||
- защищенный корень gateway `https://10.10.10.2/` штатно отвечает `401`;
|
||||
- AW API health проверяется через
|
||||
`http://10.10.10.13:5600/api/0/settings/`;
|
||||
- актуальный каталог Proxmox backup storage:
|
||||
`/var/lib/pve/local-btrfs/dump`;
|
||||
- если `suricata.service` не активен, проверка процесса Suricata
|
||||
пропускается как следствие состояния сервиса, а не как отдельный сбой
|
||||
процесса.
|
||||
|
||||
## Результаты
|
||||
|
||||
В каталоге отчётов создаются файлы:
|
||||
@@ -53,3 +102,25 @@ cp scripts/detmir-support.env.example scripts/detmir-support.env
|
||||
- `0` — без ошибок и предупреждений
|
||||
- `1` — есть WARN
|
||||
- `2` — есть FAIL
|
||||
|
||||
`SKIP` означает, что проверка не могла быть выполнена в текущих условиях:
|
||||
например, нет SSH-аутентификации, сервис намеренно выключен или отсутствует
|
||||
проверяемый компонент. `SKIP` не должен маскировать причину: в строке отчета
|
||||
должна быть указана диагностическая причина, например
|
||||
`Permission denied (publickey,password)` или
|
||||
`Skipped because suricata.service state=inactive`.
|
||||
|
||||
## Текущие ожидаемые предупреждения
|
||||
|
||||
На момент актуализации документации для контура DetMir допустимо увидеть:
|
||||
|
||||
- `aw-server-rust` на `10.10.10.13` в состоянии `inactive`, если фактический
|
||||
production service — `activitywatch-server`;
|
||||
- предупреждение по резервным копиям, если последний файл в
|
||||
`/var/lib/pve/local-btrfs/dump` старше установленного порога;
|
||||
- `suricata.service state=inactive`, если IDS/IPS на данном узле не введен в
|
||||
штатную эксплуатацию.
|
||||
|
||||
Эти предупреждения нужно фиксировать в отчете и отдельно согласовывать:
|
||||
включать сервис, менять список ожидаемых сервисов или отмечать компонент как
|
||||
неиспользуемый.
|
||||
|
||||
@@ -82,6 +82,10 @@ DetMir: серверы доступны, виртуальные машины з
|
||||
reachability внутренних сетей, ошибки TLS/auth/route push.
|
||||
- Проверять Suricata: запущен ли сервис, нет ли массовых блокировок рабочего
|
||||
трафика, критичных алертов и переполнения логов.
|
||||
- Если Suricata на конкретном узле не введена в эксплуатацию и
|
||||
`suricata.service` находится в состоянии `inactive`, фиксировать это как
|
||||
контролируемое предупреждение или `SKIP` с явной причиной, а не как
|
||||
самостоятельный сбой процесса.
|
||||
- Проверять, что критичные systemd services, timers и cron jobs
|
||||
находятся в ожидаемом состоянии.
|
||||
- Проверять наличие свежих резервных копий по базовым системам.
|
||||
@@ -228,6 +232,9 @@ DetMir: серверы доступны, виртуальные машины з
|
||||
- административный доступ к Proxmox, pfSense, Linux-серверам, web-серверу,
|
||||
VPN и другим компонентам, входящим в контур;
|
||||
- безопасный способ хранения и передачи учетных данных;
|
||||
- локальный приватный файл параметров для автоматизированных проверок, например
|
||||
`$HOME/.config/awatch-rus/detmir-support.env`, с правами доступа только для
|
||||
владельца и без помещения секретов в Git;
|
||||
- контакт ответственного лица для согласования рискованных изменений;
|
||||
- список критичных сервисов и допустимые окна обслуживания;
|
||||
- сведения о провайдерах, доменах, сертификатах, внешних адресах и каналах
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
# Эксплуатационная проверка контура
|
||||
|
||||
Дата актуализации: 2026-06-23
|
||||
|
||||
Документ фиксирует минимальный профессиональный контур проверки после
|
||||
существенных изменений Rust-кода, сборщиков telemetry, ClickHouse workforce
|
||||
аналитики, gateway или Grafana dashboards.
|
||||
|
||||
## Rust / cargo gate
|
||||
|
||||
Выполнять из репозитория. `CARGO_TARGET_DIR` должен быть вне рабочей копии, чтобы
|
||||
не загрязнять diff.
|
||||
|
||||
```bash
|
||||
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian/adk-rust
|
||||
export CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target
|
||||
|
||||
cargo fmt --all --check
|
||||
cargo test --workspace --all-targets --locked
|
||||
cargo test --workspace --doc --locked
|
||||
cargo clippy --workspace --all-targets --locked -- -D warnings
|
||||
cargo audit --deny warnings
|
||||
```
|
||||
|
||||
Проверка политики зависимостей:
|
||||
|
||||
```bash
|
||||
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
|
||||
cargo deny --manifest-path adk-rust/Cargo.toml check \
|
||||
--config deny.toml \
|
||||
--hide-inclusion-graph \
|
||||
--show-stats
|
||||
```
|
||||
|
||||
Windows/RDP collector дополнительно проверяется под целевой ABI:
|
||||
|
||||
```bash
|
||||
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian/adk-rust
|
||||
export CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target
|
||||
|
||||
cargo check --target x86_64-pc-windows-gnu -p aw-windows-telemetry --locked
|
||||
cargo clippy --target x86_64-pc-windows-gnu \
|
||||
-p aw-windows-telemetry \
|
||||
--all-targets \
|
||||
--locked \
|
||||
-- -D warnings
|
||||
```
|
||||
|
||||
Repository-specific gate:
|
||||
|
||||
```bash
|
||||
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
|
||||
python3 scripts/public_secret_pattern_check.py
|
||||
|
||||
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian/adk-rust
|
||||
export CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target
|
||||
cargo run -p quality-gate -- --root /mnt/usb_hdd2/Projects/ActivityWatch-Russian
|
||||
```
|
||||
|
||||
## Browser smoke
|
||||
|
||||
Browser smoke не заменяет API/CLI проверки. Он подтверждает, что операторский
|
||||
контур реально открывается в браузере и dashboards рендерят панели.
|
||||
|
||||
Минимальный набор страниц:
|
||||
|
||||
- `http://10.10.10.13:5600/` - ActivityWatch WebUI.
|
||||
- `http://10.10.10.13:5610/reports/worktime/today` - дневной RDP отчет.
|
||||
- `http://10.10.10.13:5610/reports/worktime/management` - управленческий RDP
|
||||
отчет.
|
||||
- `http://10.10.10.2:8710/manager/brief` - 1C executive brief.
|
||||
- `http://10.10.10.2:8710/manager/actions` - очередь управленческих действий.
|
||||
- `http://10.10.10.2:8710/manager/recovery` - recovery brief.
|
||||
- `http://10.10.10.2:8710/manager/digest/weekly` - weekly digest.
|
||||
- `https://dm.iri1968.dpdns.org/` - gateway index через Basic Auth.
|
||||
- `https://dm.iri1968.dpdns.org/d/detmir-rdp-user-activity/detmir3a-rabota-pol-zovatelej-v-rdp?orgId=1&from=now-7d&to=now&timezone=browser&var-host=SHARKON2025&refresh=5m`
|
||||
- RDP user activity dashboard.
|
||||
- `https://dm.iri1968.dpdns.org/d/detmir-aw-main/detmir3a-activitywatch-overview?orgId=1&from=now-24h&to=now&timezone=browser&refresh=5m`
|
||||
- main ActivityWatch dashboard.
|
||||
|
||||
Правила:
|
||||
|
||||
- Basic Auth читать с `pve-detmir:/etc/detmir/proxmox-web-gateway.credentials`.
|
||||
Пароль нельзя печатать в логах, документации, commit messages или final report.
|
||||
- Скриншоты для диагностики хранить в `/tmp/aw-browser-smoke-*`; не коммитить.
|
||||
- Ошибки `404` по Grafana endpoint `/api/dashboards/uid/*/public-dashboards`
|
||||
не считаются отказом панели: это metadata public dashboard, не datasource.
|
||||
Пустые panels, 5xx, ошибки datasource или отсутствие данных в body/screenshot
|
||||
считаются регрессией.
|
||||
|
||||
## Production smoke
|
||||
|
||||
После deploy или изменения telemetry/workforce выполнить:
|
||||
|
||||
```bash
|
||||
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
|
||||
NO_PROXY=localhost,127.0.0.1,10.10.10.13,10.10.10.2,192.168.100.18,10.10.10.0/24 \
|
||||
no_proxy=localhost,127.0.0.1,10.10.10.13,10.10.10.2,192.168.100.18,10.10.10.0/24 \
|
||||
./check-aw-full.sh
|
||||
```
|
||||
|
||||
Для workforce ClickHouse дополнительно проверить quality views:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
(SELECT count() FROM aw_workforce.v_workforce_unknown_subjects) AS unknown_subjects,
|
||||
(SELECT count() FROM aw_workforce.v_workforce_unknown_processes) AS unknown_processes,
|
||||
(SELECT count() FROM aw_workforce.v_workforce_unknown_domains) AS unknown_domains,
|
||||
(SELECT countIf(user_login = 'unknown'
|
||||
OR (process_name = 'unknown' AND lengthUTF8(window_title) = 0))
|
||||
FROM aw_workforce.aw_window_events) AS no_user_window_rows;
|
||||
```
|
||||
|
||||
Ожидаемое состояние после cleanup/normalization: все четыре значения равны `0`.
|
||||
@@ -45,6 +45,19 @@ evidence. Russian build-runner still required for registry release evidence.
|
||||
Public security checks are advisory/public validation. Registry release
|
||||
security evidence must be generated in the Russian build contour.
|
||||
|
||||
Current local engineering gate for product changes is documented in
|
||||
`docs/OPERATIONS_VALIDATION_RUNBOOK_RU.md` and includes:
|
||||
|
||||
- full Rust workspace tests with `--workspace --all-targets --locked`;
|
||||
- doc tests;
|
||||
- `clippy` with `-D warnings`;
|
||||
- RustSec check through `cargo audit --deny warnings`;
|
||||
- dependency policy through `cargo deny`;
|
||||
- repository `quality-gate`;
|
||||
- public secret-pattern check;
|
||||
- browser smoke through ActivityWatch UI, worktime reports, 1C manager pages,
|
||||
gateway and Grafana dashboards.
|
||||
|
||||
## Conservative positioning
|
||||
|
||||
The quality layer does not claim certification, does not position AWatch-rus as
|
||||
|
||||
@@ -26,7 +26,12 @@ release evidence должен производиться на российско
|
||||
## Rust code quality
|
||||
|
||||
- Rust-код форматируется `cargo fmt --all --check`.
|
||||
- Для затронутого Rust workspace ожидаются relevant `cargo test` checks.
|
||||
- Для существенных Rust-изменений ожидается полный workspace gate:
|
||||
`cargo test --workspace --all-targets --locked`,
|
||||
`cargo test --workspace --doc --locked` и
|
||||
`cargo clippy --workspace --all-targets --locked -- -D warnings`.
|
||||
- Для Windows/RDP collector дополнительно проверяется target
|
||||
`x86_64-pc-windows-gnu` через `cargo check` и `cargo clippy`.
|
||||
- Ошибки обрабатываются явно; нет silent fallback для security-sensitive paths.
|
||||
- Timeouts, retries and bounds are explicit for network or long-running work.
|
||||
- Новые dependencies justified and license-compatible.
|
||||
@@ -95,7 +100,11 @@ release evidence должен производиться на российско
|
||||
`bash scripts/registry_readiness_check.sh`,
|
||||
`git diff --check`.
|
||||
- For shell changes, `bash -n` is mandatory for changed shell scripts.
|
||||
- For Rust/product changes, Rust checks are required by risk and scope.
|
||||
- For Rust/product changes, use
|
||||
`docs/OPERATIONS_VALIDATION_RUNBOOK_RU.md` as the default local validation
|
||||
contour.
|
||||
- For operator-facing web, gateway, worktime reports or Grafana dashboards,
|
||||
browser smoke through the rendered pages is required in addition to API checks.
|
||||
|
||||
## Evidence requirements
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# Источники ActivityWatch для workforce ingest: SHARKON2025
|
||||
|
||||
Дата проверки: `2026-06-23`
|
||||
|
||||
AW API: `http://10.10.10.13:5600/api/0`
|
||||
|
||||
Хост: `SHARKON2025`
|
||||
|
||||
## Итоговое решение P1
|
||||
|
||||
Основные источники для `aw_workforce`:
|
||||
|
||||
| Поток | Bucket | Решение | Поля |
|
||||
|---|---|---|---|
|
||||
| Desktop/window facts | `aw-watcher-window_SHARKON2025` | Загружать в `aw_window_events` | `app`, `hostname`, `processId`, `sessionId`, `source`, `title`, `username` |
|
||||
| Browser facts, Edge | `aw-watcher-web-edge_SHARKON2025` | Загружать в `aw_browser_events` | `app`, `browser`, `hostname`, `sessionId`, `source`, `title`, `url`, `username` |
|
||||
| Browser facts, Chrome | `aw-watcher-web-chrome_SHARKON2025` | Загружать как исторический browser source; если `username` отсутствует, писать `unknown` | `app`, `browser`, `sessionId`, `source`, `title`, `url` |
|
||||
|
||||
Не использовать как основной fact-source продуктивности:
|
||||
|
||||
| Bucket | Причина |
|
||||
|---|---|
|
||||
| `aw-rdp-window_SHARKON2025` | Есть активное окно RDP bridge, но нет `username` в событии; не годится для точной per-user привязки. |
|
||||
| `aw-detmir-web-category_SHARKON2025` | Это health/category signal с `signalType=collector_health` и нулевой длительностью; полезен для диагностики collector/user presence, но не для длительности продуктивности. |
|
||||
| `aw-worktime-sessions_SHARKON2025` | Авторитетный источник сессий и пользователей RDP, но это presence/session facts, а не window/browser usage facts. |
|
||||
|
||||
## Подтвержденные факты
|
||||
|
||||
`aw-watcher-window_SHARKON2025`:
|
||||
|
||||
- type: `currentwindow`;
|
||||
- client: `aw-watcher-window`;
|
||||
- hostname: `SHARKON2025`;
|
||||
- за последние 24 часа есть события с пользователями `USER1`, `USER4`, `USER5`, `Администратор`;
|
||||
- `USER1` подтвержден в этом bucket и будет нормализован loader-ом в `user1`.
|
||||
|
||||
`aw-watcher-web-edge_SHARKON2025`:
|
||||
|
||||
- type: `web.tab.current`;
|
||||
- client: `aw-watcher-web-edge`;
|
||||
- hostname: `SHARKON2025`;
|
||||
- события за последние 30 дней содержат `username`;
|
||||
- на момент проверки событий за последние 24 часа не было, поэтому источник включается как основной browser source, но freshness контролируется отдельно.
|
||||
|
||||
`aw-watcher-web-chrome_SHARKON2025`:
|
||||
|
||||
- type: `web.tab.current`;
|
||||
- client: `aw-watcher-web-chrome`;
|
||||
- hostname: `SHARKON2025`;
|
||||
- последние найденные события исторические и не содержат `username`;
|
||||
- loader загружает их с `user_login='unknown'`, пока нет надежной session correlation.
|
||||
|
||||
## Первая привязка P3
|
||||
|
||||
Файл загрузки: `clickhouse-workforce/sample/seed_sharkon2025_p3.sql`.
|
||||
|
||||
| host_name | user_domain | user_login | department | branch |
|
||||
|---|---|---|---|---|
|
||||
| `SHARKON2025` | `sharkon2025` | `user1` | `tsj` | `tsj` |
|
||||
|
||||
Ключ словаря остается `(host_name, user_login)`. Домен хранится как атрибут
|
||||
`user_domain`, потому что текущие raw-события ActivityWatch дают `username`, а не
|
||||
стабильный `DOMAIN\user` в window/browser facts.
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user