# Windows Rust Agent Worktime/RDP ## Назначение `awatch-agent-rs` заменяет PowerShell-сборщик `worktime-session-collector.ps1` для учета Windows/RDP-сессий. Цель перехода: - меньше зависимость от PowerShell и локали Windows; - стабильный сбор RDP/local/disconnected сессий через WinAPI WTS; - единый `TelemetryRecord` для портала, отчетов, KPI активности и UEBA; - сохранение PowerShell-сценария только как legacy fallback. Агент не собирает содержимое окон, документов, ввод с клавиатуры или снимки экрана. Для worktime/session path используются только: - `username`; - `session_id`; - `session_type`; - `active`; - `started_at`, если платформа отдаст это поле; - `remote_addr`, если платформа отдаст это поле. ## Конфигурация агента Файл Windows: ```text C:\ProgramData\AWatch-rus\agent\awatch-agent.toml ``` Минимальный пример: ```toml server_url = "https:///api/telemetry" api_key = "CHANGE_ME" collect_interval_seconds = 30 role = "workstation" enable_processes = true enable_network = true enable_security_events = true enable_workforce_activity = true spool_dir = "C:\\ProgramData\\AWatch-rus\\agent\\spool" timeout_seconds = 10 retry_attempts = 3 aw_api_base = "http://:5600/api/0" aw_worktime_enabled = true ``` По умолчанию в example-конфиге `aw_worktime_enabled=false`. Включайте его только после настройки `aw_api_base`, spool-директории и rollback-процедуры. ## Источники сессий Агент пишет диагностическое поле `session_source`: - `wts_api` - основной промышленный путь через WinAPI WTS; - `quser_utf16` - fallback через `query user`/`quser` в UTF-16; - `quser_lossy` - fallback через обычный console output; - `env_sessionname_fallback` - fallback по переменной `SESSIONNAME`; - `local_fallback` - последняя локальная заглушка, когда системные источники не вернули сессии. В `TelemetryRecord.diagnostics` дополнительно пишутся: - `sessions_collected_total`; - `rdp_sessions_total`; - `active_sessions_total`; - `collector_source`; - `collector_error`. ## Достоверность данных агента Портал и отчеты поднимают diagnostics в два блока: - `agent_quality` - обратная совместимость и технические счетчики; - `agent_quality_explain` - управленческий вывод о доверии к KPI. Статусы `agent_quality`: - `ok` - основной источник `wts_api`, ошибки коллектора нет; - `fallback` - данные получены через `quser_utf16`, `quser_lossy` или `env_sessionname_fallback`; - `degraded` - используется `local_fallback` или есть некритичная ошибка коллектора; - `error` - есть критичная ошибка коллектора, например отказ доступа, некорректный обязательный payload или ошибка парсинга; - `unknown` - старый агент или payload без diagnostics. Статусы `agent_quality_explain`: - `OK` - данные приняты в KPI; - `WARNING` - данные собраны резервным способом, допустимы как оперативный ориентир, но требуют проверки для доказательной базы; - `DEGRADED` - данные не приняты в KPI; - `UNKNOWN` - агент не передал диагностику качества данных. `local_fallback` считается диагностическим сигналом, а не доказательством активности. События worktime, опубликованные из `local_fallback`, получают `active=false`, `ignoredForKpi=true` и не должны увеличивать KPI сотрудника или подтверждать RDP-активность. В портале для этого режима выводится текст: `Диагностический режим, данные не засчитываются в KPI`. Портал также строит `agent_quality_history` за 7 дней из telemetry JSONL: последняя запись каждого дня превращается в статус доверия к KPI. Если за неделю меньше 5 дней `OK`, недельный KPI считается требующим валидации. Портал строит `agent_quality_nodes` по последней записи каждого рабочего места за период. Ключ узла выбирается так: `hostname`, затем `machine_id`, затем `unknown`. Это позволяет не ломать старые telemetry payload и одновременно показывать руководителю, какие рабочие станции портят достоверность KPI. Источник `local_fallback` в этой сводке помечается как диагностический и не подтверждает KPI узла. На основе `agent_quality_nodes` портал также считает `agent_coverage_sla`: покрытие ожидаемого парка рабочих мест по файлу expected nodes. Свежий `local_fallback` может подтверждать наличие телеметрии, но не подтверждает KPI узла и снижает `coverage_pct`. ## PowerShell Legacy Fallback В `deployment-config.json` используется блок: ```json { "collectors": { "worktimeSessionEnabled": true, "worktimeSessionMode": "rust_primary", "worktimeLegacyFallbackEnabled": true } } ``` Режимы: - `powershell_primary` - старое поведение, PowerShell collector основной; - `rust_primary` - Rust agent основной, PowerShell запускается только как legacy fallback при недоступности Rust agent или stale worktime bucket. Для полного отключения PowerShell worktime fallback: ```json { "collectors": { "worktimeSessionEnabled": false, "worktimeSessionMode": "rust_primary", "worktimeLegacyFallbackEnabled": false } } ``` ## Проверка Проверить локальный JSON агента: ```powershell C:\ProgramData\AWatch-rus\agent\awatch-agent-rs.exe ` --config C:\ProgramData\AWatch-rus\agent\awatch-agent.toml ` --once --print-json ``` Ожидаемые признаки: - `active_sessions` содержит local/RDP/disconnected сессии; - `rdp_sessions` содержит активные RDP-сессии; - `session_source` равен `wts_api` в штатном режиме; - `diagnostics.rdp_sessions_total` соответствует числу RDP-сессий. Проверить, что legacy PowerShell не запущен: ```powershell Get-CimInstance Win32_Process | Where-Object { $_.Name -match 'powershell|pwsh' -and $_.CommandLine -match 'worktime-session-collector.ps1' } ``` Проверить ActivityWatch bucket: ```bash curl "http://:5600/api/0/buckets/aw-worktime-sessions_/events?limit=5" ``` В свежих событиях должно быть: ```json { "source": "awatch-agent-rs", "sessionSource": "wts_api", "collectorSource": "wts_api", "ignoredForKpi": false } ``` ## Spool и восстановление Если `aw_worktime_enabled=true`, но `aw_api_base` временно недоступен, агент кладет worktime-записи в: ```text \aw-worktime ``` При следующем успешном цикле агент пытается выгрузить накопленный spool с тем же `retry_attempts`. ## Rollback на PowerShell 1. Остановить Rust Scheduled Task или сервис агента. 2. В `deployment-config.json` установить: ```json { "collectors": { "worktimeSessionEnabled": true, "worktimeSessionMode": "powershell_primary", "worktimeLegacyFallbackEnabled": true } } ``` 3. Перезапустить guard/recovery AWatch-rus. 4. Проверить, что `worktime-session-collector.ps1` снова пишет события в `aw-worktime-sessions_`. PowerShell collector не удаляется из поставки именно для такого rollback.