diff --git a/docs/wiki/Getting-Started-and-Prerequisites.md b/docs/wiki/Getting-Started-and-Prerequisites.md new file mode 100644 index 0000000..075fc70 --- /dev/null +++ b/docs/wiki/Getting-Started-and-Prerequisites.md @@ -0,0 +1,48 @@ +# Getting Started and Prerequisites + +## 1.2 Обязательные переменные и preflight + +После `cc9e4a0` контур Grafana/Influx считается частью базового production path. Перед запуском `ansible/deploy_aw_server.yml` должны быть доступны не только WinRM/SSH секреты, но и write-token'ы InfluxDB для bucket `aw_metrics`. + +Минимальный локальный secrets-файл: + +```bash +set -a +source secrets/deploy.secrets.env +set +a +``` + +Обязательные переменные для Influx exporters: + +| Переменная | Назначение | +| --- | --- | +| `AW_WORKTIME_INFLUX_TOKEN` | Write-token для `aw-worktime-influx-exporter.service`; пишет `aw_rdp_worktime_*` ряды в `aw_metrics`. | +| `AW_DLP_INFLUX_TOKEN` | Write-token для `aw-dlp-influx-exporter.service`; пишет DLP health/signals/cases/reviews/rules в `aw_metrics`. | + +Токены должны иметь право записи в bucket `aw_metrics` в org `proxmox`. Read-only token из Grafana datasource не подходит: exporter получит `HTTP 403 Forbidden`. + +## Проверки перед deploy + +Быстрый preflight: + +```bash +test -n "$AW_WORKTIME_INFLUX_TOKEN" +test -n "$AW_DLP_INFLUX_TOKEN" +ansible-playbook --syntax-check ansible/deploy_aw_server.yml -i ansible/inventory.ini +ansible-playbook --syntax-check ansible/deploy_aw_windows.yml -i ansible/inventory.ini +``` + +`deploy_aw_server.yml` теперь сам валидирует token'ы: если `aw_worktime_influx_enabled=true` или `aw_dlp_influx_enabled=true`, но соответствующий token пустой, playbook останавливается до записи `/etc/activitywatch/aw-server.env`. + +## Runtime smoke-check + +После deploy проверьте: + +```bash +systemctl is-active aw-worktime-influx-exporter.timer +systemctl is-active aw-dlp-influx-exporter.timer +journalctl -u aw-worktime-influx-exporter.service -n 20 --no-pager +journalctl -u aw-dlp-influx-exporter.service -n 20 --no-pager +``` + +Ожидаемый результат: oneshot services завершаются `status=0/SUCCESS`, в журнале есть строки вида `wrote ... points to aw_metrics`. diff --git a/docs/wiki/Grafana-and-Prometheus-Monitoring-Stack.md b/docs/wiki/Grafana-and-Prometheus-Monitoring-Stack.md new file mode 100644 index 0000000..577f82e --- /dev/null +++ b/docs/wiki/Grafana-and-Prometheus-Monitoring-Stack.md @@ -0,0 +1,88 @@ +# Grafana and Prometheus Monitoring Stack + +## 7. Grafana / Influx exporters + +После `cc9e4a0` Influx exporters для Grafana включены как production default: + +```yaml +aw_worktime_influx_enabled: true +aw_dlp_influx_enabled: true +``` + +Оба exporter'а пишут в InfluxDB bucket: + +```text +org: proxmox +bucket: aw_metrics +url: http://10.10.10.10:8086 +``` + +Grafana datasource `InfluxDB-AW` читает тот же bucket. + +## Token parameters + +Новые обязательные параметры: + +| Ansible var | Env source | Назначение | +| --- | --- | --- | +| `aw_worktime_influx_token` | `AW_WORKTIME_INFLUX_TOKEN` | Write-token для `aw-worktime-influx-exporter.service`. | +| `aw_dlp_influx_token` | `AW_DLP_INFLUX_TOKEN` | Write-token для `aw-dlp-influx-exporter.service`. | + +Эти token'ы должны иметь `write-bucket` permission на `aw_metrics`. Grafana read-token не подходит для exporters. + +## Deploy validation + +`deploy_aw_server.yml` теперь содержит preflight assert'ы: + +- если `aw_worktime_influx_enabled=true`, `aw_worktime_influx_token` обязан быть непустым; +- если `aw_dlp_influx_enabled=true`, `aw_dlp_influx_token` обязан быть непустым. + +Кроме того, разовый запуск exporters больше не маскируется `failed_when: false`. Если запись в Influx сломана, playbook должен явно упасть, а не оставлять Grafana со старыми рядами. + +## Expected measurements + +После успешного запуска в `aw_metrics` должны быть свежие ряды: + +- `aw_window_event` +- `aw_afk_event` +- `aw_rdp_worktime_daily` +- `aw_rdp_worktime_hourly` +- `aw_rdp_worktime_summary_daily` +- `aw_dlp_endpoint_self_test` +- `aw_dlp_fileops_health` +- `aw_dlp_signal` +- DLP case/review/rule/incident measurements, если в источниках есть соответствующие события. + +Быстрая диагностика: + +```bash +systemctl start aw-worktime-influx-exporter.service +systemctl start aw-dlp-influx-exporter.service +journalctl -u aw-worktime-influx-exporter.service -n 30 --no-pager +journalctl -u aw-dlp-influx-exporter.service -n 30 --no-pager +``` + +Успешный результат: `wrote ... points to aw_metrics`. + +## Grafana checks + +Через API: + +```bash +curl -u "$GRAFANA_USER:$GRAFANA_PASSWORD" \ + http://10.10.10.11:3000/api/datasources/uid/influxdb_aw/health +``` + +Ожидается: + +```json +{"message":"datasource is working. 1 buckets found","status":"OK"} +``` + +Dashboard UID, которые должны открываться: + +- `detmir-aw-main` +- `detmir-rdp-user-activity` +- `detmir-dlp-security` +- `detmir-dlp-management` +- `awatch-dlp-overview` diff --git a/docs/wiki/Home.md b/docs/wiki/Home.md index f365457..2dcf044 100644 --- a/docs/wiki/Home.md +++ b/docs/wiki/Home.md @@ -4,6 +4,15 @@ ## 📚 Содержание +### Production guide +- [1.2 Getting Started and Prerequisites](Getting-Started-and-Prerequisites) - обязательные env-переменные, Influx token'ы и preflight validation +- [2.2 Server Infrastructure](Server-Infrastructure) - retention, journald limits и `aw-prune-local-state` +- [2.3 Russian WebUI Patch and Localization](Russian-WebUI-Patch-and-Localization) - runtime RU patch, DLP links и navigation fixes +- [2.4 Worktime API and UI Bridge](Worktime-API-and-UI-Bridge) - cache, build locks, trend optimization и foreground context +- [3 Windows Collector Suite](Windows-Collector-Suite) - RDP/session/process collectors, recovery и локализованный Administrator +- [7 Grafana and Prometheus Monitoring Stack](Grafana-and-Prometheus-Monitoring-Stack) - Influx exporters, token validation и Grafana checks +- [8 Operations, CI/CD, and Quality Assurance](Operations-CI-CD-and-Quality-Assurance) - тесты, autoheal и rollout checks + ### Архитектура - [Обзор архитектуры](Architecture) - высокоуровневая архитектура системы - [Компоненты системы](Components) - описание всех компонентов diff --git a/docs/wiki/Operations-CI-CD-and-Quality-Assurance.md b/docs/wiki/Operations-CI-CD-and-Quality-Assurance.md new file mode 100644 index 0000000..f16f295 --- /dev/null +++ b/docs/wiki/Operations-CI-CD-and-Quality-Assurance.md @@ -0,0 +1,72 @@ +# Operations, CI/CD, and Quality Assurance + +## 8. Quality gates after `cc9e4a0` + +Коммит усилил тестовое покрытие worktime path и сделал часть operational failures явными. + +## Worktime tests + +Новые/расширенные тесты: + +```bash +python3 -m pytest aw-server/test_aw_worktime_api.py aw-server/test_aw_worktime_ui_bridge.py +``` + +Покрываются: + +- in-process events cache; +- management report build locks; +- trend building с `precomputed_payloads`; +- foreground context fallback в UI bridge; +- active session id detection; +- нормализация watcher/window events. + +Ожидаемый результат для текущего набора: `28 passed`. + +## Autoheal changes + +`aw-server/aw-worktime-autoheal.sh` изменен так, чтобы management warm-up не был обязательным probe для общей доступности worktime API. + +Текущая логика: + +- обязательные probes проверяют health/report path; +- если worktime API недоступен, autoheal перезапускает `aw-worktime-api.service`; +- management warm выполняется отдельно; +- failure management warm логируется, но не переводит весь health path в hard failure. + +Timeout management warm увеличен: + +```bash +WORKTIME_MANAGEMENT_WARM_TIMEOUT_SECONDS=60 +``` + +Это снижает ложные перезапуски при тяжелой сборке management report. + +## UI bridge service hardening + +`aw-server/aw-worktime-ui-bridge.service` теперь использует: + +```ini +StartLimitBurst=20 +StartLimitIntervalSec=120 +``` + +Большее значение `StartLimitBurst` нужно для recovery-сценариев после перезапуска AW server или временной недоступности buckets: bridge может несколько раз стартовать, пока API прогревается, не попадая сразу в systemd start-limit. + +## Ansible validation + +Перед rollout: + +```bash +ansible-playbook --syntax-check ansible/deploy_aw_server.yml -i ansible/inventory.ini +ansible-playbook --syntax-check ansible/deploy_aw_windows.yml -i ansible/inventory.ini +``` + +Для Grafana exporters обязательно дополнительно проверить наличие: + +```bash +AW_WORKTIME_INFLUX_TOKEN +AW_DLP_INFLUX_TOKEN +``` + +Playbook теперь не должен скрывать ошибку записи в Influx: если exporter не может писать в `aw_metrics`, deploy считается неуспешным. diff --git a/docs/wiki/Russian-WebUI-Patch-and-Localization.md b/docs/wiki/Russian-WebUI-Patch-and-Localization.md new file mode 100644 index 0000000..df803e9 --- /dev/null +++ b/docs/wiki/Russian-WebUI-Patch-and-Localization.md @@ -0,0 +1,34 @@ +# Russian WebUI Patch and Localization + +## 2.3 Russian WebUI patch + +`aw-server/aw-ru-patch.js` продолжает быть runtime patch'ем поверх ActivityWatch WebUI, но после `cc9e4a0` логика стала более явной: текстовые переводы и навигационные исправления сведены в отдельную функцию `applyTextAndNavigationPatches(root)`. + +## `applyTextAndNavigationPatches` + +Функция выполняет общий набор patch'ей для переданного DOM root: + +- обход текстовых узлов через `walk(root)`; +- перевод атрибутов через `translateAttributes(root)`; +- исправление DLP navigation links; +- повторное применение при route change в SPA. + +Это снижает риск, что часть UI останется на английском после client-side перехода без полной перезагрузки страницы. + +## Исправление DLP links + +DLP navigation получила защиту от битых ссылок: + +- исправляются ссылки вида `/activity/dlp` и другие broken DLP activity refs; +- DLP item помечается `data-aw-ru-dlp-item="1"`, чтобы patch не дублировал элемент; +- patch различает label `DLP` внутри activity tabs и реальные broken links. + +## Улучшения локализации + +Патч теперь повторно применяет текстовые и навигационные изменения: + +- на первичной загрузке `document.body`; +- после смены route key; +- после восстановления settings host/host groups state. + +Это особенно важно для WebUI страниц, где ActivityWatch перерисовывает DOM без reload: activity views, category builder, settings и DLP navigation. diff --git a/docs/wiki/Server-Infrastructure.md b/docs/wiki/Server-Infrastructure.md new file mode 100644 index 0000000..1302239 --- /dev/null +++ b/docs/wiki/Server-Infrastructure.md @@ -0,0 +1,71 @@ +# Server Infrastructure + +## 2.2 Local state retention + +Коммит `cc9e4a0` добавил отдельный server-side maintenance path для контроля роста локального state на AW server. + +## `aw-prune-local-state.sh` + +Скрипт `aw-server/aw-prune-local-state.sh` устанавливается в: + +```text +/usr/local/bin/aw-prune-local-state.sh +``` + +Назначение: + +- чистит старые backup-файлы в `{{ aw_server_data_dir }}/backups`; +- отдельно удерживает последние DB backups и JSON backups; +- удаляет временные архивы из `/tmp`: `activitywatch-*.zip`, `hayabusa-*.zip`, `aw-hayabusa-profiles.txt`; +- удаляет временные WebUI/worktime artifacts старше одного дня: `aw-worktime-ui-bridge.py`, `views-default.json`, `apply_webui_ru_patch.out`. + +## systemd unit и timer + +Ansible создает: + +```text +/etc/systemd/system/aw-prune-local-state.service +/etc/systemd/system/aw-prune-local-state.timer +``` + +Timer: + +```ini +[Timer] +OnCalendar=*-*-* 04:40:00 +Persistent=true +``` + +То есть очистка запускается ежедневно в `04:40`; если хост был выключен, `Persistent=true` догонит пропущенный запуск. + +## Retention-параметры + +Параметры задаются в `ansible/group_vars/aw_server.yml`: + +| Переменная | Значение по умолчанию | Назначение | +| --- | ---: | --- | +| `aw_server_backup_retention_days` | `7` | Возраст backup-файлов, после которого они могут быть удалены. | +| `aw_server_backup_keep_last_db` | `2` | Минимум последних DB backup'ов, которые всегда сохраняются. | +| `aw_server_backup_keep_last_json` | `2` | Минимум последних JSON backup'ов, которые всегда сохраняются. | +| `aw_server_journal_system_max_use` | `100M` | Лимит persistent journald storage. | +| `aw_server_journal_runtime_max_use` | `50M` | Лимит runtime journald storage. | +| `aw_server_journal_system_keep_free` | `500M` | Минимально свободное место, которое journald должен оставить на FS. | + +## journald retention + +`deploy_aw_server.yml` устанавливает drop-in: + +```text +/etc/systemd/journald.conf.d/aw-rus-retention.conf +``` + +Содержимое управляется Ansible: + +```ini +[Journal] +SystemMaxUse={{ aw_server_journal_system_max_use }} +RuntimeMaxUse={{ aw_server_journal_runtime_max_use }} +SystemKeepFree={{ aw_server_journal_system_keep_free }} +``` + +После изменения drop-in playbook перезапускает `systemd-journald` и выполняет `journalctl --vacuum-size={{ aw_server_journal_system_max_use }}`. Это ограничивает рост логов без ручной очистки и снижает риск заполнения rootfs на AW server. diff --git a/docs/wiki/Windows-Collector-Suite.md b/docs/wiki/Windows-Collector-Suite.md new file mode 100644 index 0000000..a45b967 --- /dev/null +++ b/docs/wiki/Windows-Collector-Suite.md @@ -0,0 +1,68 @@ +# Windows Collector Suite + +## 3. Windows collectors + +Коммит `cc9e4a0` существенно усилил Windows/RDP контур, особенно `windows/worktime-session-collector.ps1` и общую recovery библиотеку `windows/ActivityWatch.Windows.Common.psm1`. + +## Worktime Session Collector + +`worktime-session-collector.ps1` получил крупное расширение: новые helper-функции для session/process state, отдельную публикацию session events и более строгую нормализацию buckets. + +Ключевые изменения: + +- `Ensure-Bucket` теперь принимает `ClientName` и `BucketType`, а не жестко прошитые значения; +- добавлена поддержка bucket `aw-session-events_`; +- collector публикует logon/session state и process transitions, если это включено конфигурацией; +- session records лучше отделяют active/disconnected/unknown состояния; +- downstream server-side bridge получает более качественные `sessionId`, `username`, `sessionName` и activity markers. + +## Process events + +Новый флаг: + +```yaml +aw_windows_process_events_enabled: true +``` + +Он попадает в deployment config как: + +```json +sessionEvents.processEventsEnabled +``` + +Когда флаг включен, Windows collector публикует process-level изменения в session events bucket. Это дает server-side слою больше контекста для active session detection и forensic review. + +## Localized Administrator + +Новый параметр: + +```yaml +aw_windows_builtin_administrator_name: "Администратор" +``` + +Назначение: явно фиксировать локализованное имя встроенной учетной записи Administrator с SID `*-500`. + +Для текущего Windows host `SHARKON2025` task name должен строиться как: + +```text +ActivityWatch Launch [SHARKON2025_Администратор] +``` + +Если task по `SHARKON2025_Administrator` не найден, recovery/deploy path обязан пробовать кириллическое имя `Администратор`. Это зафиксировано через: + +- default vars в `ansible/deploy_aw_windows.yml`; +- `ansible/group_vars/aw_windows.yml`; +- example vars в `ansible/group_vars/windows.example.yml`; +- env override `AWATCH_RUS_BUILTIN_ADMINISTRATOR_NAME`; +- fallback в `Get-ActivityWatchBuiltInAdministratorName`. + +## Recovery hardening + +`ActivityWatch.Windows.Common.psm1` усилил recovery path: + +- `Get-ActivityWatchBuiltInAdministratorName` сначала смотрит env override, затем SID-500 lookup, затем host-specific fallback `SHARKON2025 -> Администратор`; +- `Normalize-ActivityWatchUsers` стабилизирован для pipeline/list cases; +- удаление scheduled tasks стало устойчивее к частично удаленным task definitions; +- recovery task может ориентироваться на live interactive session и запускаться в interactive logon context, когда это безопаснее для watcher'ов. + +Операционный вывод: для RDP/console telemetry нельзя полагаться на task name с английским `Administrator` на русифицированной Windows. Локализованное имя должно быть частью deploy vars. diff --git a/docs/wiki/Worktime-API-and-UI-Bridge.md b/docs/wiki/Worktime-API-and-UI-Bridge.md new file mode 100644 index 0000000..f0d7a85 --- /dev/null +++ b/docs/wiki/Worktime-API-and-UI-Bridge.md @@ -0,0 +1,63 @@ +# Worktime API and UI Bridge + +## 2.4 Worktime API + +`aw-server/aw-worktime-api.py` теперь рассчитан на повторные management-запросы без лишнего чтения одних и тех же bucket events. + +## In-process events cache + +Добавлен in-process cache событий: + +```text +AW_WORKTIME_EVENTS_CACHE_TTL_SECONDS=30 +``` + +Ключ cache - bucket id. Значение хранит `stored_at` и список events. Cache защищен `threading.Lock`, поэтому параллельные HTTP-запросы не ломают состояние процесса. Основной эффект: management report и trend building меньше давят на `/api/0/buckets/.../events`. + +## Build locks для management report + +Функция `get_management_build_lock(host, report_date)` выдает lock на пару `host + date`. Это предотвращает параллельную сборку одного и того же management report при одновременных запросах UI, warm-up и health probes. + +Поведение: + +- первый запрос собирает payload; +- конкурирующие запросы ждут тот же lock; +- после сборки результат кладется в cache/файловый слой как раньше. + +## Оптимизация trend building + +`build_management_trend(...)` принимает `precomputed_payloads`. Текущий report payload переиспользуется как готовый день тренда, а не пересчитывается повторно. + +Практический эффект: endpoint management report меньше тратит CPU на день, который уже был рассчитан текущим запросом. + +## UI Bridge foreground context cache + +`aw-server/aw-worktime-ui-bridge.py` сохраняет `last_foreground_context` в state. Если свежий collector health event временно недоступен, bridge может использовать последний валидный foreground context вместо деградации в generic `RDP`. + +Нормализация foreground context: + +- `foregroundProcess` становится `app`; +- если процесс без `.exe`, suffix добавляется автоматически; +- `foregroundTitle` становится `title`; +- context учитывается только для активных session ids, если они известны. + +## Active session detection + +Функция `get_latest_active_session_ids(events)` группирует session events по timestamp, берет самый свежий срез и возвращает только активные `sessionId`. + +Это убирает смешивание старых disconnected-сессий с текущим состоянием и стабилизирует связку: + +```text +aw-worktime-sessions_* -> aw-rdp-window_* -> aw-watcher-window_* +``` + +## Нормализация window events + +Bridge теперь формирует window events из session state и foreground context: + +- активное окно получает app/title из foreground context; +- title дополняется агрегированным RDP summary через `build_window_title(...)`; +- `normalize_watcher_window_events(...)` подготавливает совместимый поток для `aw-watcher-window_`; +- sync в watcher bucket выполняется только если `watcher_window_needs_bridge_sync(...)` считает его нужным. + +Это сохраняет совместимость с ActivityWatch WebUI и Grafana, где часть запросов ожидает canonical watcher bucket.