25 KiB
План передачи проекта агенту OpenCode
Документ нужен агенту, который должен самостоятельно разворачивать и сопровождать полный контур AWatch-rus. Писать и действовать нужно просто: сначала понять слой, затем развернуть, затем проверить, затем зафиксировать результат.
1. Цель
Развернуть AWatch-rus как единый контур:
- сбор активности пользователей с Windows/RDP рабочих мест;
- учет рабочего времени и RDP-сессий;
- DLP/ИБ-сигналы: clipboard, USB, print, browser domains, email, file ops;
- ActivityWatch Server и русифицированный WebUI;
- worktime API и управленческие отчеты;
- Grafana dashboards поверх InfluxDB;
- ClickHouse-контур для файловой 1С, расследований, detections и cases;
- портал руководителя/ИБ/эксплуатации;
- проверяемый deploy через Ansible, Rust-бинарники, systemd и Windows tasks.
Главное правило: система считается развернутой только когда есть свежие данные, открываются интерфейсы, проходят health checks и есть понятный rollback.
Второе главное правило: agent может читать private/ignored файлы только для
проверки факта и типа секрета. Значения паролей, токенов, host credentials и
private URL нельзя переносить в markdown, audit, terminal summary, commit или
handoff. В отчете писать так: ansible/inventory.ini содержит plaintext credentials; значения не фиксировались; нужна ротация.
2. Простая модель системы
Представь систему как цепочку:
Windows/RDP users
-> Windows collectors / Rust agent
-> ActivityWatch API buckets
-> Rust services on AW server
-> Worktime reports + DLP services + Influx exporters
-> Grafana dashboards + Portal
-> ClickHouse/1C analytics where configured
Если ломается ранний слой, поздний слой тоже будет пустым. Нельзя начинать с
Grafana, если ActivityWatch buckets пустые. Нельзя чинить портал, если
aw-worktime-api degraded. Нельзя чинить ClickHouse для worktime, потому что
worktime reports не зависят от ClickHouse.
3. Роли пользователей
Система должна закрывать четыре роли.
-
Руководитель:
- видит, кто работал;
- видит активное время по дням;
- видит проблемные подразделения и риски;
- получает простой вывод без технического шума.
-
ИБ:
- видит DLP-инциденты;
- видит evidence и screenshot artifacts;
- видит DLP dashboards;
- может разбирать кейсы без прямого доступа к сырой базе.
-
Эксплуатация:
- видит свежесть buckets;
- видит состояние сервисов;
- видит failed units, timers, collector guard;
- может безопасно перезапустить нужный слой.
-
Аналитик 1С:
- видит аудит файловых баз 1С;
- видит detections, timeline, cases;
- видит состояние выгрузок и качество данных;
- понимает, где данные реальные, а где proxy/fallback.
4. Обязательный функционал
4.1 ActivityWatch core
Нужно:
activitywatch-serverработает и слушает:5600;- WebUI открывается;
- CORS/landing page настроены;
- buckets создаются и обновляются;
- SQLite не перегружен тяжелыми запросами.
Проверки:
curl -fsS http://<AW_SERVER_HOST>:5600/api/0/info
curl -fsS http://<AW_SERVER_HOST>:5600/api/0/buckets | jq 'keys'
systemctl status activitywatch-server --no-pager
4.2 Windows/RDP сбор
Нужно:
- Windows toolkit установлен;
- есть
deployment-config.json; - есть scheduled tasks
ActivityWatch Launch [...]иActivityWatch Recovery; - Rust collector guard работает, PowerShell fallback остается только как fallback;
validate-deployment.ps1возвращаетoverallOk=True;- есть свежие buckets:
aw-worktime-sessions_<HOST>;aw-watcher-window_<HOST>;aw-watcher-afk_<HOST>если AFK включен;aw-dlp-endpoint-signals_<HOST>;aw-file-operations_<HOST>если file ops включен.
Развертывание:
.\windows\deploy-ensemble.ps1 `
-ServerHost <AW_SERVER_HOST> `
-ServerPort 5600 `
-Domain <WINDOWS_DOMAIN_OR_HOST> `
-Users user1,user2,user3
Проверки:
.\windows\validate-deployment.ps1 | ConvertTo-Json -Depth 10
Get-ScheduledTask | Where-Object TaskName -like 'ActivityWatch*'
Get-Service AWatchRusCollectorGuard
4.3 Worktime reports
Нужно:
aw-worktime-apiработает на:5610;/healthвозвращает OK или понятный degraded;/reports/worktime/managementстроит HTML/JSON;- report не считает служебные accounts и битые labels;
- stale cache включен для degraded path.
Проверки:
curl -fsS http://<AW_SERVER_HOST>:5610/health | jq
curl -fsS "http://<AW_SERVER_HOST>:5610/reports/worktime/management?format=json&host=<WINDOWS_HOSTNAME>&allow_stale=1" | jq '.status,.runtime'
systemctl status aw-worktime-api --no-pager
4.4 DLP
Нужно:
- DLP policy engine доступен;
- endpoint signals пишутся;
- incidents создаются;
- screenshots/evidence синхронизируются;
- case management и compliance работают, если включены;
- DLP health check зеленый или объясняет WARN/FAIL.
Проверки:
systemctl status aw-dlp-policy-engine aw-dlp-case-management --no-pager
curl -fsS http://<AW_SERVER_HOST>:5601/health || true
curl -fsS http://<AW_SERVER_HOST>:5600/api/0/buckets/aw-dlp-endpoint-signals_<HOST>
4.5 WebUI
Нужно:
- ActivityWatch WebUI не пустой;
- RU patch подключен;
- host sanitize script подключен;
- DLP review/rules UI доступен, если включен;
- worktime panel не ломает основной WebUI;
- browser cache не скрывает новую версию.
Развертывание:
ansible-playbook -i ansible/inventory.ini ansible/deploy_aw_server.yml
Проверки:
curl -fsS http://<AW_SERVER_HOST>:5600/ | head
curl -fsS http://<AW_SERVER_HOST>:5600/js/ru-patch-v5.js | head
curl -fsS http://<AW_SERVER_HOST>:5600/js/aw-host-sanitize.js | head
4.6 Portal
Нужно:
- портал работает как read-only рабочий кабинет;
- роли видят разные представления, но данные общие;
/api/healthпоказывает состояние источников;/api/reportsвозвращает KPI и markdown;- portal не должен silently mutate AW/DLP/1C;
- внешняя публикация идет через gateway/auth, не через открытые raw ports.
Развертывание:
cd adk-rust
cargo build --release -p detmir-portal
cd ../ansible
ansible-playbook -i inventory.ini deploy_detmir_portal.yml
ansible-playbook -i inventory.ini deploy_proxmox_web_gateway.yml
Проверки:
curl -fsS http://<PORTAL_HOST>:8720/api/health | jq
curl -fsS http://<PORTAL_HOST>:8720/api/reports | jq '.status,.sources'
systemctl status detmir-portal --no-pager
5. Grafana + InfluxDB
5.1 Что должно быть
InfluxDB хранит агрегаты для Grafana:
aw_rdp_worktime_daily;aw_rdp_worktime_hourly;aw_rdp_worktime_summary_daily;- DLP measurements;
- health/self-test measurements.
Grafana должна показывать:
- главный AWatch-rus dashboard;
- RDP/user activity dashboard;
- DLP/security dashboard;
- DLP management dashboard;
- overview dashboard для владельца.
Структура в репозитории разделена на три разных контура:
grafana/— плоские version-controlled JSON dashboards основного AWatch-rus контура. Их импортируетansible/deploy_grafana_dashboards.yml, а проверяетansible/deploy_grafana_check.yml.grafana-1c/— отдельный docker-compose стек для SQL-readable 1C MSSQL/Postgres dashboards.clickhouse-1c/grafana/provisioning/— provisioning ClickHouse/file-1C dashboards и datasource.
Не путать эти каталоги. Если меняется основной dashboard, править grafana/*.json
и прогонять dashboard deploy/check. Если меняется ClickHouse 1C dashboard,
смотреть clickhouse-1c/grafana/provisioning/.
5.2 Deploy order
- Убедиться, что InfluxDB доступен.
- Убедиться, что write tokens заданы в private inventory/env.
- Развернуть AW server exporters.
- Запустить exporters вручную один раз.
- Проверить, что points записались.
- Импортировать/provision Grafana dashboards.
- Запустить
detmir-grafana-check.
Команды:
systemctl start aw-worktime-influx-exporter.service
systemctl start aw-dlp-influx-exporter.service
journalctl -u aw-worktime-influx-exporter.service -n 50 --no-pager
journalctl -u aw-dlp-influx-exporter.service -n 50 --no-pager
cd ansible
ansible-playbook -i inventory.ini deploy_grafana_dashboards.yml
ansible-playbook -i inventory.ini deploy_grafana_check.yml
Проверки Grafana:
curl -u "$GRAFANA_USER:$GRAFANA_PASSWORD" \
http://<GRAFANA_HOST>:3000/api/datasources/uid/influxdb_aw/health
Ожидание: datasource OK, dashboards открываются, panels не пустые, labels пользователей нормализованы.
5.3 Правила для dashboard
- Не править только руками в Grafana UI; сначала править JSON/provisioning в репозитории.
- Для worktime не показывать machine accounts, битые Unicode labels и дубли регистра.
- Owner-facing aggregate должен называться понятным языком, например
Все сотрудники, а не техническим словомКоманда. - После импорта проверить dashboard API и открыть страницу через gateway.
6. ClickHouse + файловая 1С
6.1 Назначение
Этот контур нужен, когда 1С файловая и нужен не только KPI, а audit stack:
1C exports / reglog / host telemetry
-> landing/*
-> aw-1c-ingest-rust
-> ClickHouse analytics_1c
-> detections / timeline / cases / company intelligence
-> Grafana + Portal + briefs
6.2 Что развернуть
- ClickHouse;
- Grafana datasource ClickHouse;
- schema из
clickhouse-1c/clickhouse/init/*.sql; - landing каталоги;
- ingest timer/service;
- detections SQL;
- company intelligence refresh;
- read-only 1C analytics API;
- dashboards из
clickhouse-1c/grafana/provisioning/dashboards/files/.
6.3 Minimal local bootstrap
cd clickhouse-1c
cp .env.example .env
docker compose up -d
mkdir -p landing/{documents,postings,business_events,document_changes,companies,reglog,audit,host}
cp etl/config.example.yml etl/config.yml
6.4 Production ingest
cd adk-rust
cargo build --release -p aw-1c-ingest
/usr/local/bin/aw-1c-ingest-rust --root /opt/activitywatch/clickhouse-1c
clickhouse-client --queries-file /opt/activitywatch/clickhouse-1c/detections/insert_detections.sql
clickhouse-client --queries-file /opt/activitywatch/clickhouse-1c/detections/build_entity_timeline.sql
6.5 Проверки ClickHouse/1С
clickhouse-client --query "SHOW DATABASES"
clickhouse-client --database analytics_1c --query "SHOW TABLES"
clickhouse-client --database analytics_1c --query "SELECT count() FROM business_events"
clickhouse-client --database analytics_1c --query "SELECT count() FROM detections"
Ожидание:
- таблицы существуют;
- raw/normalized слои не пустые, если есть выгрузки;
- detections считаются;
- Grafana 1C dashboards открываются;
- API компании/brief отвечает read-only.
7. Модули и ответственность
| Слой | Где смотреть | За что отвечает |
|---|---|---|
| Rust runtime | adk-rust/crates/* |
production binaries, checks, exporters, portal, ingest |
| AW server | aw-server/, ansible/deploy_aw_server.yml |
ActivityWatch, WebUI, worktime, DLP services |
| Windows | windows/, ansible/deploy_aw_windows.yml |
collectors, tasks, guard, validation |
| Grafana/Influx | grafana/, ansible/deploy_grafana_dashboards.yml, ansible/deploy_grafana_check.yml |
flat dashboard JSON import, datasource/freshness checks |
| SQL 1C Grafana | grafana-1c/ |
separate MSSQL/Postgres 1C Grafana stack |
| 1C/ClickHouse | clickhouse-1c/, clickhouse-1c/ai/, clickhouse-1c/grafana/provisioning/ |
file 1C analytics, detections, cases, allowed Python AI helpers |
| Portal | adk-rust/crates/detmir-portal, docs/PORTAL_RU.md |
role views, reports, health |
| Gateway | ansible/deploy_proxmox_web_gateway.yml |
external protected routes |
| Docs/runbooks | docs/, adk-rust/RUNBOOK.md |
operating procedures |
7.1 Ansible playbook map
Перед deploy агент должен понимать назначение playbook, а не запускать их пакетом.
| Playbook | Назначение |
|---|---|
deploy_aw_server.yml |
ActivityWatch server, WebUI, worktime/DLP server side |
deploy_aw_windows.yml |
Windows/RDP collectors and validation artifacts |
post_validate_aw_windows.yml |
post-deploy Windows validation |
deploy_detmir_portal.yml |
portal service |
deploy_proxmox_web_gateway.yml |
protected gateway routes |
deploy_grafana_dashboards.yml |
import flat grafana/*.json dashboards |
deploy_grafana_check.yml |
datasource/dashboard health checks |
deploy_file_1c_windows_telemetry.yml |
file-1C Windows telemetry |
deploy_file_1c_analytics.yml |
file-1C analytics layer |
deploy_dlp_evidence_sync.yml |
DLP evidence artifact sync |
deploy_dlp_full_stack.yml |
full DLP server-side stack |
deploy_aw_pfsense_poller.yml |
pfSense poller integration |
audit_cryptopro_windows.yml |
Windows CryptoPro audit |
provision_proxmox_ct_and_deploy_aw.yml |
provision one Proxmox CT and deploy AW |
provision_proxmox_ct_matrix_and_deploy_aw.yml |
provision CT matrix and deploy AW |
deploy_tsj_guardian_bot_proxmox.yml |
Proxmox guardian bot |
install_full_stack.yml |
broad full-stack install wrapper; use only with explicit scope |
8. Полный порядок развёртывания
Шаг 0. Не ломать рабочий контур
Перед любыми изменениями:
git status --short --branch
git log --oneline -5
Если есть unrelated dirty tree, не откатывать его. Работать только с нужными файлами.
Шаг 1. Подготовить private конфигурацию
Проверить:
ansible/inventory.ini;- private group vars;
- Influx tokens;
- Grafana credentials;
- Windows host/user list;
- gateway host/auth;
- ClickHouse credentials;
- 1C export paths.
Нельзя коммитить реальные secrets. Нельзя вставлять значения из
ansible/inventory.ini, private env, vault, runtime configs или host credentials
в docs/audit. Разрешено писать только факт: где найдено, какой тип секрета, что
сделать для remediation.
Шаг 2. Собрать Rust
cd adk-rust
cargo fmt --all -- --check
cargo build --release --workspace
cargo test -p detmir-core
cargo test -p detmir-portal
cargo test -p worktime-api
cargo test -p worktime-influx-exporter
Если workspace слишком большой, собирать targeted crates, которые нужны текущему deploy.
Шаг 3. Проверить Ansible syntax
cd ansible
ansible-playbook --syntax-check deploy_aw_server.yml
ansible-playbook --syntax-check deploy_aw_windows.yml
ansible-playbook --syntax-check deploy_detmir_portal.yml
ansible-playbook --syntax-check deploy_grafana_dashboards.yml
ansible-playbook --syntax-check deploy_grafana_check.yml
Шаг 4. Развернуть AW server
ansible-playbook -i inventory.ini deploy_aw_server.yml
После:
systemctl --failed --no-pager
systemctl status activitywatch-server aw-worktime-api --no-pager
curl -fsS http://<AW_SERVER_HOST>:5600/api/0/info
curl -fsS http://<AW_SERVER_HOST>:5610/health | jq
Шаг 5. Развернуть Windows/RDP
ansible-playbook -i inventory.ini deploy_aw_windows.yml
Или вручную на Windows:
.\windows\deploy-ensemble.ps1 -ServerHost <AW_SERVER_HOST> -ServerPort 5600 -Domain <DOMAIN> -Users user1,user2
.\windows\validate-deployment.ps1
После проверить свежесть buckets на AW server.
Шаг 6. Запустить worktime chain
systemctl restart aw-worktime-api
systemctl start aw-worktime-prewarm.service || true
curl -fsS "http://<AW_SERVER_HOST>:5610/reports/worktime/management?format=json&host=<WINDOWS_HOSTNAME>&allow_stale=1" | jq
Шаг 7. Запустить Influx exporters
systemctl start aw-worktime-influx-exporter.service
systemctl start aw-dlp-influx-exporter.service
journalctl -u aw-worktime-influx-exporter.service -n 50 --no-pager
journalctl -u aw-dlp-influx-exporter.service -n 50 --no-pager
Ожидание: wrote ... points.
Шаг 8. Развернуть Grafana dashboards/checks
ansible-playbook -i inventory.ini deploy_grafana_dashboards.yml
ansible-playbook -i inventory.ini deploy_grafana_check.yml
Проверить:
- datasource health OK;
- dashboard pages HTTP 200;
- worktime panels не пустые;
- DLP panels не пустые при наличии DLP events.
Шаг 9. Развернуть 1C/ClickHouse
Если 1С контур нужен:
cd clickhouse-1c
docker compose up -d
clickhouse-client --queries-file clickhouse/init/00_database.sql
clickhouse-client --queries-file clickhouse/init/01_raw_tables.sql
clickhouse-client --queries-file clickhouse/init/02_core_tables.sql
clickhouse-client --queries-file clickhouse/init/03_views.sql
clickhouse-client --queries-file clickhouse/init/04_company_intelligence.sql
clickhouse-client --queries-file clickhouse/init/05_financial_reporting.sql
Затем включить ingest, detections и dashboards.
Шаг 10. Развернуть portal/gateway
cd adk-rust
cargo build --release -p detmir-portal
cd ../ansible
ansible-playbook -i inventory.ini deploy_detmir_portal.yml
ansible-playbook -i inventory.ini deploy_proxmox_web_gateway.yml
Проверить:
curl -fsS http://<PORTAL_HOST>:8720/api/health | jq
curl -fsS http://<PORTAL_HOST>:8720/api/reports | jq '.status,.sources'
Шаг 11. Финальная приемка
Минимум:
systemctl --failedпустой на ключевых узлах;- AW API отвечает;
- buckets свежие;
- Windows validation OK;
- worktime report OK;
- DLP health OK/WARN с понятной причиной;
- Influx exporters пишут points;
- Grafana datasource OK;
- dashboards открываются;
- portal health OK;
- ClickHouse/1C tables не пустые, если включен 1C контур;
- нет secrets в staged diff.
9. Диагностика по симптомам
Portal пустой
- Проверить
/portal/api/health. - Проверить
aw-worktime-api. - Проверить ActivityWatch buckets.
- Проверить ClickHouse только если пустой именно 1C/security-events слой.
Grafana пустая
- Проверить Influx datasource health.
- Проверить exporters logs.
- Проверить Influx bucket/measurements.
- Проверить dashboard JSON/provisioning.
- Проверить time range и host variable.
Worktime неверный
- Проверить
aw-worktime-sessions_<HOST>. - Проверить
AW_WORKTIME_EVENTS_LIMIT. - Проверить user normalization.
- Проверить stale cache.
- Не трогать ClickHouse.
DLP пустой
- Проверить Windows collector/guard.
- Проверить
aw-dlp-endpoint-signals_<HOST>. - Проверить policy engine.
- Проверить DLP case/evidence services.
- Проверить DLP Influx exporter только для Grafana.
1C пустая
- Проверить landing files.
- Проверить
aw-1c-ingest-rust. - Проверить ClickHouse schema.
- Проверить detections SQL.
- Проверить Grafana ClickHouse datasource.
10. Как агент должен работать
- Сначала читать
AGENTS.md. - Затем читать этот документ.
- Для конкретного слоя читать профильный doc:
- Windows:
docs/windows/deployment.md; - Worktime:
docs/OPERATIONS_RUNBOOK_WORKTIME_RU.md; - Portal:
docs/PORTAL_RU.md; - Grafana:
docs/GRAFANA_DASHBOARDS_RU.md; - 1C/ClickHouse:
clickhouse-1c/README.md; - Rust migration/runtime:
adk-rust/RUNBOOK.md.
- Windows:
- Перед изменением фиксировать
git status. - Перед deploy делать syntax/build checks.
- После deploy делать runtime checks.
- Перед созданием docs/audit по private files проверять, что в текст не попали значения credentials. Писать только sanitized факт и remediation.
- В ответе пользователю писать:
- что изменено;
- какие команды выполнены;
- что проверено;
- что осталось рискованным или не проверено.
11. Запреты
- Не печатать secrets.
- Не копировать значения secrets из private/ignored файлов в audit, markdown, terminal summary, commit message или handoff.
- Не коммитить private inventory/env.
- Не править production Grafana только руками без отражения в repo.
- Не перезапускать все сервисы подряд.
- Не трогать сетевой периметр/gateway/pfSense без отдельной команды.
- Не делать destructive DB operations без backup.
- Не считать
ansible --syntax-checkполной проверкой: нужна runtime проверка. - Не считать открывшийся UI доказательством: нужны свежие данные.
12. Итоговая Definition of Done
Полная замена ручного оператора возможна только если агент умеет:
- поднять server и Windows collectors;
- проверить buckets и freshness;
- восстановить worktime report;
- запустить Influx exporters;
- импортировать/проверить Grafana dashboards;
- поднять ClickHouse/1C ingest;
- проверить portal health/reports;
- найти слой отказа по симптомам;
- сделать rollback по backup;
- написать короткий отчет без секретов.
Если один из пунктов не выполнен, система не считается полностью переданной агенту.