Files
AWatch-rus/docs/POWERSHELL_TO_RUST_ROADMAP_RU.md
T

28 KiB
Raw Blame History

Roadmap: замена PowerShell на Rust EXE

Дата: 2026-06-05

Цель: убрать зависимость AWatch-rus от PowerShell-скриптов на рабочих хостах и заменить их на самодостаточные Rust EXE/службы без потери данных, без ухудшения пилотной демонстрации и без изменения функционального объема.

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

Актуальная статусная матрица оставшихся PowerShell-файлов: POWERSHELL_SCRIPT_STATUS_MATRIX_RU.md.

Операторский checkpoint от 2026-06-05 сохранен в private .ops-контуре: Phase 0 live inventory выполнен, Phase 2 validation для уже переведенных Windows Rust paths выполнен успешно. В tracked документации не публикуются live hostnames, private IP, токены и runtime evidence paths.

1. Целевое состояние

К концу миграции:

  • на Windows/RDP-хостах регулярный сбор данных, evidence-sync, 1C upload, guard/recovery и validation выполняются Rust EXE;
  • в Scheduled Tasks и Windows Services нет штатных AWatch-rus задач, которые запускают powershell.exe или pwsh.exe;
  • install-kit поставляет Rust EXE, конфиги и service/task definitions вместо runtime .ps1;
  • Ansible разворачивает Rust binaries и конфиги, а не копирует PowerShell runtime scripts;
  • Telegram/Codex/bot контур вызывает Rust helpers или читает Rust JSON snapshots, не опираясь на пути к .ps1;
  • legacy PowerShell хранится только как временный rollback-слой до прохождения acceptance gates и затем удаляется из install-kit;
  • Linux/AW/Proxmox части остаются Rust-first; Ansible может остаться оркестратором, потому что это инфраструктурный deploy layer, а не runtime PowerShell.

2. Текущее состояние

Уже выполнено или частично выполнено:

  • awatch-agent-rs заменяет Windows worktime-session-collector.ps1 для worktime/RDP path. Legacy PowerShell оставлен как fallback и управляется collectors.worktimeSessionEnabled, worktimeSessionMode, worktimeLegacyFallbackEnabled.
  • aw-windows-telemetry.exe уже используется для:
    • file1c-upload;
    • dlp-evidence-sync.
  • aw-1c-ingest-rust пишет 1C/file analytics в ClickHouse на серверной стороне.
  • aw-windows-telemetry.exe validate-deployment добавлен как Rust validation gate первого уровня. Он проверяет уже мигрированные Windows Rust paths, свежесть worktime bucket, Rust collector guard service и queue sanity без запуска PowerShell.
  • AWatchRusCollectorGuard переключен с aw-collector-guard.ps1 на aw-windows-telemetry.exe collector-guard. Старый PowerShell guard оставлен как rollback script, но штатный service runtime его не запускает. Rust guard получает sessionId из native process snapshot, дедуплицирует legacy collectors по (kind, sessionId) и не запускает пользовательские launch tasks повторно, если legacy collectors уже активны.
  • aw-windows-telemetry.exe добавил P0 runtime collector subcommands: browser-domains-collector, dlp-endpoint-collector, file-operations-collector. На live Windows/RDP host они включены через collectors.*Mode=rust_primary, работают в трех пользовательских сессиях, а P0 PowerShell collector runtime отсутствует. Это не означает полного удаления legacy .ps1: они оставлены как rollback/reference до расширения глубокой функциональной parity.
  • Основные серверные AWatch-rus/AW/DLP helpers уже Rust-first: detmir-status, detmir-check, detmir-auto, detmir-heal-safe, aw-rus-healthd-rust, dlp-*, worktime-*, aw-health-check, check-aw-data, aw-prune-local-state и другие.

Остаток PowerShell в рабочем дереве:

  • 26 product .ps1 в windows/;
  • operator/MCP helper scripts/powershell/detmir-powershell-profile.ps1;
  • parse-check helper .pssa_run.ps1;
  • .venv/bin/activate.ps1 внутри virtualenv не является продуктовым компонентом и не входит в миграцию.

3. Инвентаризация Windows PowerShell

Скрипт Роль Цель миграции Приоритет
worktime-session-collector.ps1 RDP/worktime сбор закрепить замену через awatch-agent-rs, затем удалить fallback P0 done/stabilize
browser-domains-native-collector.ps1 browser/domain и DLP web-сигналы aw-windows-telemetry.exe browser-domains-collector; live Rust primary, legacy fallback/reference P0 live/stabilize
dlp-endpoint-signals-collector.ps1 clipboard/USB/print/DLP incident signals aw-windows-telemetry.exe dlp-endpoint-collector; live Rust primary, screenshots только для DLP events P0 live/stabilize
file-operations-collector.ps1 file create/delete/rename/archive hints aw-windows-telemetry.exe file-operations-collector; live Rust primary with queue/spool P0 live/stabilize
email-outbound-collector.ps1 outbound email metadata/DLP Rust email metadata collector P1
dlp-policy-client.ps1 получение DLP policy Rust policy client/cache P1
export-upload-file-1c-telemetry.ps1 1C telemetry upload закрепить aw-windows-telemetry.exe file1c-upload, затем удалить legacy P0 done/stabilize
sync-dlp-evidence-artifacts.ps1 DLP evidence upload закрепить aw-windows-telemetry.exe dlp-evidence-sync P0 done/stabilize
export-evtx-for-hayabusa.ps1 bounded EVTX export Rust EVTX export helper P1
export-upload-hayabusa-to-aw-server.ps1 EVTX/Hayabusa upload Rust upload helper или режим в aw-windows-telemetry.exe P1
aw-standalone-service.ps1 supervisor service wrapper Rust Windows service wrapper P0
aw-collector-guard.ps1 guard/restart/recovery Rust guard with allowlist, lock, cooldown P0 done/stabilize
hardening-recovery.ps1 recovery/hardening Rust recovery CLI; destructive actions behind --apply P1
validate-deployment.ps1 post-deploy validation Rust validation CLI aw-windows-telemetry.exe validate-deployment; расширять до полной parity перед удалением .ps1 P0 started
rebuild-worktime-tasks.ps1 rebuild scheduled tasks Rust task reconciliation CLI P1
fix-session-watchers.ps1 repair session watchers Rust repair subcommand P2
cleanup-disc-sessions.ps1 cleanup stale disconnected sessions Rust maintenance subcommand P2
migrate-awatch-rus-paths.ps1 path migration Rust migration CLI with backup and dry-run P1
deploy-single-user.ps1 single-user deploy Rust/Ansible-backed installer action P1
deploy-domain-users.ps1 domain deploy Rust/Ansible-backed installer action P1
deploy-ensemble.ps1 orchestrated deploy Rust deploy coordinator or Ansible playbook wrapper P1
install-standalone-service.ps1 local service install Rust installer/bootstrap CLI P0
install-collector-guard-service.ps1 guard service install Rust installer/bootstrap CLI P0
install-dlp-client.ps1 DLP client install Rust installer/bootstrap CLI P1
audit-cryptopro.ps1 CryptoPro audit Rust audit CLI P2
run-user1-probe.ps1 manual probe Rust diagnostic probe P2

4. Неприкосновенные ограничения

  • Не делать big-bang replacement.
  • Не отключать PowerShell fallback до прохождения shadow/parity gates.
  • Не переносить функции, которые требуют скрытого сбора, keylogging, screen recording или content interception. Скриншоты допустимы только для DLP incident evidence, если это явно включено политикой.
  • Не менять бизнес-логику DLP, 1C, worktime или evidence при переносе.
  • Не менять thresholds, bucket names, event schema и ClickHouse schema без отдельного решения.
  • Не ломать install-kit и rollback ради удаления .ps1.
  • Не хранить live hostnames, private IP, tokens, passwords или runtime evidence paths в публичных tracked docs.

5. Общий контракт каждого Rust EXE

Каждый заменяющий EXE должен иметь:

  • --config <path>;
  • --json для машинного вывода;
  • --dry-run для всех действий, меняющих состояние;
  • --timeout-seconds;
  • --log-path или structured logging в штатный каталог;
  • --version;
  • стабильные exit codes:
    • 0 - OK;
    • 1 - usage/config/runtime error;
    • 2 - check выполнен, но состояние WARN/FAIL;
    • 3 - action запрещен safety policy;
  • structured JSON event для audit trail;
  • lock/cooldown для guard/recovery/actions;
  • spool/queue для сетевых upload path;
  • atomic writes для state files;
  • no implicit sudo/admin: повышенные права должны быть видны в task/service definition;
  • rollback compatibility с текущими config keys.

6. Фазы миграции

Phase 0. Baseline и реестр вызовов

Цель: зафиксировать, где PowerShell реально используется.

Действия:

  1. Сканировать репозиторий:
    • windows/*.ps1;
    • windows/installkit/innosetup/*.iss;
    • ansible/*.yml;
    • ansible/group_vars/*.yml;
    • scripts/*;
    • docs/runbooks.
  2. Снять runtime baseline на тестовом Windows host:
    • Scheduled Tasks;
    • Windows Services;
    • текущие command lines процессов;
    • deployment-config.json;
    • свежесть AW buckets;
    • наличие DLP evidence и 1C upload.
  3. Для каждого скрипта зафиксировать:
    • входные параметры;
    • env/config keys;
    • side effects;
    • event schema;
    • log/state paths;
    • expected exit codes;
    • rollback path.

Выход фазы:

  • docs/POWERSHELL_TO_RUST_ROADMAP_RU.md как базовая дорожная карта;
  • отдельный runtime inventory для live-контура в private/operator notes, без публикации секретов.

Phase 1. Windows Rust foundation

Цель: подготовить общий Windows runtime вместо набора разрозненных EXE.

Действия:

  1. Расширить существующие awatch-agent-rs и aw-windows-telemetry только в рамках parity, без новых функций.
  2. Вынести общие Windows helpers:
    • config loading;
    • ActivityWatch HTTP client;
    • evidence upload client;
    • Windows task/service inspection;
    • Event Log/EVTX access;
    • filesystem state/spool;
    • structured logs/audit.
  3. Зафиксировать единый Windows config contract:
    • C:\ProgramData\AWatch-rus\deployment-config.json;
    • C:\Program Files\AWatch-rus\windows\*.exe;
    • C:\ProgramData\AWatch-rus\logs;
    • C:\ProgramData\AWatch-rus\spool;
    • C:\ProgramData\AWatch-rus\switch-backups.

Gate:

cd adk-rust
cargo fmt --all -- --check
cargo test --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo build --release -p awatch-agent-rs -p aw-windows-telemetry

Phase 2. Закрепить уже выполненные замены

Цель: не переписать повторно то, что уже переведено, а довести до production definition of done.

Компоненты:

  • worktime-session-collector.ps1 -> awatch-agent-rs;
  • export-upload-file-1c-telemetry.ps1 -> aw-windows-telemetry.exe file1c-upload;
  • sync-dlp-evidence-artifacts.ps1 -> aw-windows-telemetry.exe dlp-evidence-sync;
  • aw-collector-guard.ps1 -> aw-windows-telemetry.exe collector-guard через AWatchRusCollectorGuard service wrapper;
  • серверный writer -> aw-1c-ingest-rust.

Действия:

  1. Проверить, что task/service actions запускают EXE, а не PowerShell.
  2. Проверить, что PowerShell fallback выключен там, где Rust уже стабилен.
  3. Проверить свежесть buckets/ClickHouse/evidence after restart.
  4. Обновить install-kit file list: Rust EXE являются primary artifact.
  5. Оставить legacy .ps1 только как rollback на ограниченный период.

Gate:

  • ActivityWatch File1C Upload запускает aw-windows-telemetry.exe;
  • ActivityWatch DLP Evidence Sync запускает aw-windows-telemetry.exe;
  • worktime events имеют source=awatch-agent-rs;
  • AWatchRusCollectorGuard запущен и его child process - aw-windows-telemetry.exe collector-guard;
  • guard не создает duplicate legacy browser/fileops/DLP endpoint collectors при stale bucket: при уже активных collectors launch tasks не запускаются повторно;
  • 1C ClickHouse ingest идет по aw-1c-ingest-rust;
  • PowerShell worktime process count = 0 в штатном режиме.
  • PowerShell aw-collector-guard.ps1 process count = 0 в штатном режиме.

Phase 3. Runtime collectors

Цель: заменить регулярный сбор данных на Windows.

Порядок:

  1. browser-domains-native-collector.ps1
    • current status: live Rust primary through aw-windows-telemetry.exe browser-domains-collector;
    • ActivityWatch window/category health events are written with source=aw-windows-telemetry-rust;
    • UIAutomation URL/domain extraction implemented in Rust: browser process detection, normalized URL, host/rootDomain, default/custom category rules, aw-watcher-web-*, aw-detmir-web-category_* and web DLP incident schema preserve the legacy bucket/event contract;
    • live disconnected RDP sessions may legitimately report browserDetected=false and urlDetected=false until a browser is foreground in an interactive user session;
    • screenshots только для DLP incident evidence.
  2. dlp-endpoint-signals-collector.ps1
    • current status: live Rust primary through aw-windows-telemetry.exe dlp-endpoint-collector;
    • endpoint collector health is written with source=aw-windows-telemetry-rust;
    • clipboard metadata/hash/length, USB insert, print job metadata and DLP incident event semantics implemented in Rust with legacy fields: requestedAction, enforcementMode, nativeChannelAction, enforcementSuppressed, content pack matches and enforced;
    • destructive endpoint enforcement for USB write-block and print cancel is intentionally not enabled during pilot hardening: Rust emits equivalent audit/incident semantics and suppresses unsafe block actions unless a separate enforcement decision is made;
    • incident screenshot policy remains: screenshots only for DLP events.
  3. file-operations-collector.ps1
    • current status: live Rust primary through aw-windows-telemetry.exe file-operations-collector;
    • bounded filesystem watcher, operation schema, queue/spool and create/rename/delete smoke are verified;
    • per-session queue/state/log files are used, so RDP sessions do not share one state file;
    • legacy PowerShell remains installed only as rollback/reference.
  4. email-outbound-collector.ps1
    • metadata-only parity;
    • Outlook/SMTP mode behavior preserved;
    • no content interception beyond current documented behavior.
  5. dlp-policy-client.ps1
    • Rust policy fetch/cache;
    • strict validation;
    • safe fallback to last known good policy.

Shadow-mode:

  • Rust collector writes source=<rust-component> and mode=shadow;
  • PowerShell remains primary during comparison;
  • compare event counts, schema, timestamps, severity, policy hits and evidence links for at least several collection cycles.

Gate:

  • no duplicate management conclusions in portal;
  • event schema compatible with current AW/DLP consumers;
  • no stale buckets introduced;
  • no uncontrolled screenshot capture;
  • Rust collector survives AW API outage by spooling and later flushing.

Phase 4. Guard, service wrapper и recovery

Цель: заменить PowerShell, который управляет процессами и восстановлением.

Компоненты:

  • aw-standalone-service.ps1;
  • aw-collector-guard.ps1;
  • hardening-recovery.ps1;
  • rebuild-worktime-tasks.ps1;
  • fix-session-watchers.ps1;
  • cleanup-disc-sessions.ps1.

Действия:

  1. Сделать Rust Windows service wrapper:
    • supervises configured collectors;
    • records child process state;
    • no hidden PowerShell spawn in normal mode.
  2. Сделать Rust guard/recovery:
    • allowlist actions only;
    • lock file;
    • cooldown;
    • dry-run by default for destructive or repair actions;
    • audit entry for every change.
  3. Перевести rebuild/fix/cleanup в subcommands одного maintenance EXE.

Gate:

  • controlled restart of one collector works;
  • stale collector detection matches old guard;
  • recovery cannot restart arbitrary process/service;
  • rollback restores PowerShell guard/service within one operator action.

Phase 5. Install/deploy/validate

Цель: install-kit перестает запускать PowerShell как штатный bootstrap.

Компоненты:

  • install-standalone-service.ps1;
  • install-collector-guard-service.ps1;
  • install-dlp-client.ps1;
  • deploy-single-user.ps1;
  • deploy-domain-users.ps1;
  • deploy-ensemble.ps1;
  • validate-deployment.ps1;
  • migrate-awatch-rus-paths.ps1;
  • InnoSetup AWatch-rus-InnoSetup.iss;
  • Ansible Windows playbooks/group vars.

Действия:

  1. Создать Rust bootstrap/installer EXE:
    • install/update service;
    • install/update scheduled tasks;
    • write config atomically;
    • backup previous config/tasks;
    • emit JSON validation report.
  2. Перевести validation в Rust:
    • task actions;
    • service status;
    • bucket freshness;
    • file permissions;
    • rust binary version matrix;
    • no PowerShell runtime task check.
  3. Обновить InnoSetup:
    • package *.exe;
    • run Rust bootstrap;
    • keep .ps1 out of normal install payload after stabilization.
  4. Обновить Ansible:
    • deploy EXE;
    • configure task/service actions to EXE;
    • remove default .ps1 paths from bot/env after migration.

Gate:

  • clean install on test Windows host;
  • upgrade from PowerShell install to Rust install;
  • rollback to previous package;
  • validate-deployment JSON is consumed by CI/operator without parsing human text;
  • install-kit verification confirms no powershell.exe in primary install action.

Phase 6. Ops-only хвост

Цель: убрать одноразовые PowerShell helpers.

Компоненты:

  • audit-cryptopro.ps1;
  • run-user1-probe.ps1;
  • scripts/powershell/detmir-powershell-profile.ps1;
  • .pssa_run.ps1.

Решение:

  • audit-cryptopro.ps1 -> Rust audit CLI;
  • run-user1-probe.ps1 -> Rust diagnostic probe or remove if obsolete;
  • operator PowerShell profile is not production runtime and can be retired after Rust/SSH operator commands exist;
  • .pssa_run.ps1 removed when no product PowerShell remains.

Gate:

  • no production task/service depends on these helpers;
  • docs no longer instruct operator to run PowerShell for routine checks;
  • one emergency manual path remains documented, but not packaged as runtime.

Phase 7. Decommission

Цель: убрать PowerShell from product surface.

Действия:

  1. Remove .ps1 from install-kit file list.
  2. Remove powershell.exe installer run action.
  3. Remove default .ps1 paths from Ansible/bot env.
  4. Update architecture/docs:
    • Windows collectors are Rust EXE;
    • PowerShell no longer prerequisite for runtime;
    • rollback history documented separately.
  5. Run tracked-file hygiene scan for public docs.

Gate:

rg -n "powershell\\.exe|\\.ps1|PowerShell" windows ansible docs scripts README.md

Expected result:

  • only historical notes, explicit rollback docs, or non-runtime examples remain;
  • no install-kit primary action launches PowerShell;
  • no AWatch-rus Scheduled Task action launches PowerShell in live validation.

7. Rollout по хостам

Порядок раскатки:

  1. Local build host:
    • build Windows EXE;
    • artifact check;
    • installer dry-run.
  2. Test Windows/RDP host:
    • install Rust EXE side-by-side;
    • shadow-mode collectors;
    • compare with PowerShell.
  3. Canary production Windows/RDP host:
    • one host, one business day;
    • monitor bucket freshness, DLP incidents, 1C upload, evidence upload.
  4. Remaining Windows hosts:
    • staged batches;
    • no more than one failure domain at a time.
  5. AW server / Proxmox / gateway:
    • update Ansible/bot references;
    • verify server Rust services remain active;
    • verify ClickHouse ingest and portal health.
  6. Install-kit:
    • publish Rust-first package;
    • keep previous package as rollback artifact.

8. Acceptance gates

Local gates:

cd adk-rust
cargo fmt --all -- --check
cargo test --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo build --workspace --release
cargo build --release --target x86_64-pc-windows-gnu -p awatch-agent-rs -p aw-windows-telemetry

Repository gates:

scripts/check_detmir_rust_release_artifacts.sh
scripts/verify_innosetup_installer.sh
git diff --check

Windows gates:

Get-ScheduledTask | Where-Object {
  $_.TaskName -like 'ActivityWatch*' -or $_.TaskName -like 'AWatch*'
} | Select-Object TaskName,TaskPath,State

Expected:

  • task actions point to Rust EXE for migrated components;
  • no migrated component runs powershell.exe;
  • logs are fresh;
  • spool is empty or draining;
  • AW buckets are fresh;
  • DLP evidence sync only uploads DLP incident evidence;
  • 1C upload does not copy screenshots.

Server gates:

detmir-status --json
detmir-check --json
systemctl --failed --no-pager
systemctl list-timers aw-1c-ingest.timer --no-pager

Expected:

  • AWatch-rus severity is OK or explained WARN;
  • no failed Rust services;
  • ClickHouse writer timer is active;
  • portal data freshness is acceptable for pilot.

9. Rollback model

До decommission каждая миграция хранит rollback:

  • previous EXE/script backup in switch-backups;
  • previous task/service definition;
  • previous deployment-config.json;
  • one-command switch back for canary host;
  • rollback reason written to audit log.

Rollback триггеры:

  • AW bucket stale/dead after migration;
  • DLP event loss or uncontrolled duplicate events;
  • evidence upload fails repeatedly and spool grows;
  • 1C upload stops producing landing files;
  • service/guard restarts loop;
  • Windows host shows sustained CPU/RAM regression from new EXE;
  • user-visible pilot portal data quality degrades.

10. Риски

Риск Где Снижение риска
Windows API differs from PowerShell cmdlets DLP, tasks, Event Log, print, WMI parity fixtures, canary, schema comparison
UIAutomation/browser URL extraction changes behavior browser collector shadow-mode and domain count comparison
Outlook/SMTP metadata behavior differs email collector metadata-only parity, explicit mode tests
Privilege mismatch services/tasks/recovery install under same account, explicit elevation, validation
AV/EDR blocks unsigned EXE Windows hosts code signing plan, allowlist, staged rollout
Duplicate events during shadow all collectors shadow source tags, portal ignores shadow for KPI
Rollback not fast enough production canary backup tasks/configs, single switch command
Public docs leak live contour details tracked docs placeholders and git grep hygiene scan

11. Минимальный порядок ближайших работ

  1. Зафиксировать live inventory PowerShell usage на тестовом Windows/RDP host.
  2. Закрепить уже сделанные Rust paths:
    • worktime/RDP;
    • 1C file upload;
    • DLP evidence sync.
  3. Расширить aw-windows-telemetry.exe validate-deployment до полной parity с validate-deployment.ps1, потому что он станет главным gate для следующих замен.
  4. Перенести aw-standalone-service.ps1 и aw-collector-guard.ps1, потому что они управляют runtime collectors.
  5. Стабилизировать P0 runtime collectors после live Rust-primary switch:
    • browser domains;
    • DLP endpoint signals;
    • file operations. URL/domain extraction и clipboard/USB/print incident semantics закрыты на уровне Rust code/schema/runtime self-test. Следующий шаг перед удалением legacy .ps1 - burn-in, canary rollback test и live foreground-browser proof в интерактивной RDP-сессии.
  6. Перенести deploy/install scripts и InnoSetup primary action.
  7. Убрать PowerShell paths из Ansible/bot env.
  8. Удалить .ps1 из install-kit и оставить только historical rollback docs.

12. Итоговая оценка

Миграция реалистична, потому что серверная часть уже Rust-first, а Windows контур уже имеет два рабочих Rust основания: awatch-agent-rs и aw-windows-telemetry.exe.

Критичный участок не сервер, а Windows runtime и install-kit:

  • dlp-endpoint-signals-collector.ps1;
  • browser-domains-native-collector.ps1;
  • aw-collector-guard.ps1;
  • aw-standalone-service.ps1;
  • validate-deployment.ps1;
  • InnoSetup action that still launches PowerShell.

До пилота не нужно удалять весь PowerShell хвост. Для пилота достаточно закрепить уже работающие Rust-primary paths, не допустить копирования скриншотов в 1C контуре, оставить скриншоты только для DLP events, иметь понятный rollback и честно формулировать границу parity: code/schema/runtime path закрыт, а полный live URL/domain incident proof требует активного foreground browser в интерактивной RDP-сессии. Полное удаление PowerShell из install-kit лучше делать после canary и shadow parity по DLP/browser/file collectors.