34 KiB
DetMir/AWatch-rus: hardline resilience hardening
Документ фиксирует реализованные и проверенные шаги по доведению живого контура до fail-closed уровня. Он не заменяет production runbook; здесь только изменения, влияющие на отказоустойчивость.
2026-06-30: crash-test readiness gate and healthd route boundary
Статус: implemented in repo, deployed on live AW server, verified by manual crash test.
Что прогонялось:
- baseline
check-aw-full.sh, SQLite hot-path plan, disk/headroom, RDP guard; - bounded parallel load на
/api/0/info,/aw-worktime-sessions_SHARKON2025/events?limit=100,aw-detmir-web-category_SHARKON2025и Worktime API; - controlled restart:
aw-worktime-api,activitywatch-server,AWatchRusCollectorGuard; - gateway/ClickHouse/Grafana reachability checks;
- live
scripts/detmir_resilience_check.sh --liveon AW server.
Что найдено:
systemctl is-active activitywatch-serverне равен полной готовности API: сразу послеsystemctl restart activitywatch-serverпервый/api/0/infoмог уйти в 15 секунд timeout, затем API стабилизировался и hot-path/events?limit=100отвечал быстро;aw-dlp-case-management.serviceоставался active при disabled DLP profile;aw-rus-healthd.serviceпадал из-за TCP timeout с AW server до192.168.100.19:5985/3389, хотя фактическая RDP/WinRM проверка с admin/VPN side и bucket freshness были зелёными;- SQLite hot-path index
events_bucketrow_starttime_desc_indexприсутствовал и использовался,TEMP B-TREEдля worktime event query не строился.
Что изменено:
scripts/detmir_resilience_check.sh --liveтеперь использует readiness-loop для/api/0/info, проверяет worktime hot path, Worktime API rows/degraded state, SQLite hot-path index/plan и disabled-state optional DLP/Loki units;aw-rus-healthd-rustполучил fail-closed параметрAW_RUS_HEALTH_RDP_TCP_REQUIRED/--rdp-tcp-required;- default/example остаётся
true; в DetMir production выставленоfalse, потому что server-side TCP до RDP сейчас является route/ACL boundary, а не authoritative proof of collector health; - active drift
aw-dlp-case-management.serviceостановлен, unit оставлен disabled для штатного будущего включения DLP contour.
Live verification:
check-aw-full.sh:FRESH=8,STALE=0,DEAD=0;- targeted load after stabilization:
info_p2/p4/p8/p12по24/24HTTP 200, worktime events40/40HTTP 200, web category bucket40/40HTTP 200, Worktime today30/30HTTP 200; AWatchRusCollectorGuardrestart: serviceRunning,GUARD_CHILDREN=1, collector process layout unchanged;aw-rus-healthd.service:status=0/SUCCESS,ok=11,warn=3,fail=0;scripts/detmir_resilience_check.sh --liveafter fixes: readiness, hot path, Worktime API, SQLite index, optional DLP and Loki checks pass; Hayabusa quarantine warning remains informational evidence to review.
Safety guardrails:
- no AW bucket schema, API, UI or Workforce business logic changed;
- GitHub/Grafana/ClickHouse are still validation/visibility surfaces, not Russian registry release evidence;
- DLP remains optional/reconnectable, not removed.
2026-06-25: optional DLP runtime off switch and statistics
Статус: implemented in repo, deployed, live disable verified on 2026-06-25.
Проблема:
- DLP runtime может создавать избыточную нагрузку на InfluxDB, Grafana, ClickHouse и AW server при включенных aggregator/exporter/case/report pipeline;
- простая остановка DLP units раньше приводила бы к ложным красным health, readiness и contour checks.
Что добавлено:
AW_DLP_ENABLED=falseдля AW server runtime;DETMIR_DLP_ENABLED=falseдля управляющего DetMir contour check;dlp-health-checkвозвращает штатныйdlp:mode=disabled;detmir-dlpне выполняет SSH health probe при disabled mode;detmir-check,check-aw-full,check-aw-dataпропускают DLP buckets при disabled mode;detmir-readinessне требует DLP Influx write и DLP systemd units при disabled mode;scripts/detmir_dlp_runtime_control.shсобирает JSON-срез DLP units/buckets и выполняет controlleddisable|enable.- live
disableсохраняет отдельные evidence-снимкиcurrent,pre_disableиdisabledв/var/lib/activitywatch/health/dlp-runtime-history/.
Safety guardrails:
- ActivityWatch server, worktime, Hayabusa, 1C/ClickHouse core не отключаются;
- historical DLP buckets/evidence не удаляются;
- disabled-state не заявляет, что DLP проверки выполнены;
- это не claim замены DLP/SIEM/EDR и не удаление DLP-функциональности.
Runbook:
Live verification 2026-06-25:
- before disable, active DLP runtime units were present:
aw-dlp-influx-exporter.timer,activitywatch-dlp-aggregator.timer, DLP report/integration timers, policy/case services anddetmir-portal-evidence.service; - after disable, active/enabled DLP units:
0/0; AW_DLP_ENABLED=false,AW_DLP_INFLUX_ENABLED=false,AW_DLP_DISABLED_REASON=operator_disabled_to_reduce_influx_grafana_clickhouse_load;dlp-health-checkanddetmir-dlpboth returneddlp:mode=disabled;check-aw-fullreported DLP buckets asSKIPPED;- ActivityWatch core remained active:
activitywatch-server,aw-worktime-api.
Residual non-DLP findings from the same check:
- RDP-side collectors require separate recovery: AFK/window/worktime buckets were stale;
- server-side WinRM reachability to
192.168.100.18:5985was unavailable; aw-rus-healthd.servicewas already failed and is tracked separately from this DLP runtime disable.
2026-06-24: Hayabusa poison-package isolation
Статус: implemented locally, unit-tested, deployed on AW server.
Проблема:
- один битый zip в
/opt/hayabusa/inbox/incomingмог остановить весь Hayabusa pipeline; aw-hayabusa-drop.pathпосле повторных падений мог упереться в systemd start-limit;- восстановление требовало ручного переноса bad zip в quarantine.
Что изменено:
aw-hayabusa-autoprocess-rustпроверяет drop zip доaccept;- corrupt/empty/unsafe zip и битые sidecar-файлы не попадают в рабочий inbox;
- bad drop package переносится в
/opt/hayabusa/quarantine/drop/...вместе с.meta.json,.caseid, optional.sha256иreason.json; aw-hayabusa process-inboxбольше не abort'ит весь batch из-за одного incoming package;- failed incoming package переносится в
/opt/hayabusa/quarantine/incoming/...с partial staging payload иreason.json, если пакет остался в incoming; - пакеты, уже архивированные wrapper'ом как
failed-no-evtxилиfailed-analysis, остаются в штатном archive/intake manifest для расследования.
Safety guardrails:
- quarantine не удаляет evidence;
- replay выполняется только после re-export или явного восстановления пакета;
- один poison archive не должен мешать обработке остальных zip;
- operational failures инфраструктуры (
aw-hayabusaотсутствует, права, broken runtime) остаются красными и не маскируются как успешная обработка.
Проверки:
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
bash -n aw-server/hayabusa/aw-hayabusa.sh
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian/adk-rust
export CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target
cargo test -p hayabusa-tools
Результат проверки:
bash -n aw-server/hayabusa/aw-hayabusa.shpassed;cargo test -p hayabusa-toolspassed: 5 tests passed.
Production deployment note:
- после сборки и доставки нового
aw-hayabusa-autoprocess-rustнужно выполнить live dry-run на empty drop и контролируемый bad-zip test в непроизводственном каталоге или с временным isolated--drop-dir; - live production queue руками не мутировать без предварительного backup/listing.
Live rollout evidence:
- deployed on AW server on
2026-06-24; - previous
/usr/local/bin/aw-hayabusaand/usr/local/bin/aw-hayabusa-autoprocess-rustwere backed up with timestamp suffix; /usr/local/bin/aw-hayabusa doctorreturned OK;- isolated empty-drop dry-run returned
no zip packages in drop dir; - production queue after rollout:
incoming_zip=0,DROP_COUNT=0,aw-hayabusa-drop.path=active,aw-hayabusa-drop.service=inactive; - stale staging residue from
2026-06-20was moved, not deleted, to/opt/hayabusa/quarantine/staging-stale-20260624T190739Z/withreason.json; - after cleanup:
staged_dirs=0,archived_packages=74,archived_payloads=74.
2026-06-24: Windows collector guard service child watchdog
Статус: implemented locally, static checks passed, deployed on RDP host.
Проблема:
- Windows service
AWatchRusCollectorGuardмог оставаться в состоянииrunning, когда дочернийaw-windows-telemetry.exe collector-guardуже отсутствовал; - SCM recovery не срабатывал, потому что сам service wrapper не падал.
Что изменено:
AWatchRusCollectorGuardService.csтеперь подписывается наProcess.Exited;- при неожиданном выходе child-процесса wrapper делает bounded restart;
- restart budget: 5 child restarts за 600 секунд, задержка 5 секунд;
- при исчерпании бюджета wrapper завершает service с ошибкой, чтобы Windows Service Control Manager применил recovery actions;
- installer включает
sc.exe failureflag <service> 1, чтобы recovery actions применялись к service failures, а не только к crash-путям; ActivityWatch Recoveryостаётся fallback/bootstrap задачей и не отключается.
Safety guardrails:
- штатный
Stop-Service/shutdown выставляетstopping=true, поэтому child exit во время остановки не считается аварией; - wrapper не меняет collector mode, bucket names, event schema и AW API;
- service-level recovery ограничен существующим
sc.exe failurebudget.
Проверки:
pwsh -NoProfile -Command '<compile AWatchRusCollectorGuardService.cs through Add-Type>'
pwsh -NoProfile -Command '<parse install-collector-guard-service.ps1>'
powershell -NoProfile -ExecutionPolicy Bypass -File windows/install-collector-guard-service.ps1
Get-Service AWatchRusCollectorGuard
Get-Content C:\ProgramData\AWatch-rus\logs\collector-guard-service.log -Tail 20
Результат локальной проверки:
AWatchRusCollectorGuardService.cscompiled through PowerShellAdd-Type;windows/install-collector-guard-service.ps1parsed with PowerShell parser;- live install/restart validation still requires Windows/RDP deployment window.
Live rollout evidence:
- deployed on RDP host on
2026-06-24; - previous service source, installer and exe were backed up under
C:\ProgramData\AWatch-rus\backup\collector-guard-service-20260624T190827Z; - installer completed with
Runtime: rust,Mode: enforce; - SCM
failureflagis enabled:FAILURE_ACTIONS_ON_NONCRASH_FAILURES: TRUE; - controlled fault-injection killed only the child
aw-windows-telemetry.exe collector-guard; - wrapper observed child exit, attempted bounded restarts, SCM recovery restarted wrapper after budget exhaustion, and child stabilized;
- final validation after one guard loop: service
Running,CHILD_COUNT=1, childaw-windows-telemetry.exe, latest rust guard cyclestatus=ok.
Live validation после деплоя:
- убить только child
aw-windows-telemetry.exe collector-guard; - убедиться, что service остаётся running и child перезапущен;
- повторить child crash больше 5 раз за 600 секунд в тестовом окне;
- убедиться, что service перешёл через SCM recovery, а не остался
running/no child.
2026-06-24: contour resilience check
Статус: implemented locally, shell syntax/repo-mode passed, live AW server check passed.
Проблема:
- отдельные исправления легко потерять при deploy/drift;
- CI не проверял, что poison-package isolation и child watchdog реально присутствуют в коде и документации;
- live-проверки должны оставаться read-only и не маскировать production сбой.
Что добавлено:
scripts/detmir_resilience_check.sh;--repoрежим для CI-safe проверки hardening-файлов, паттернов и docs;--liveрежим для read-only проверки локального AW/Hayabusa host:activitywatch-server,aw-worktime-api, AW/api/0/info, failed systemd units, Hayabusaincoming/drop/quarantine, SQLite DB/WAL size;RUN_RESILIENCE_CHECK=1hook вscripts/run_awatch_contour_check.sh;DETMIR_RESILIENCE_STRICT_SECRETS=1режим, который fail'ит literalansible_password/ansible_become_passwordв private inventory без вывода значений.
Safety guardrails:
- check не рестартует сервисы, не двигает очереди, не пишет в production dirs;
- secret check печатает только факт наличия literal assignments, не значения;
- live mode запускается явно через
--liveили--all; - GitHub/public CI может использовать только
--repo.
Secret handling update 2026-06-30:
- literal
ansible_passwordиansible_become_passwordудалены из локальногоansible/inventory.ini; aw_serverчитает SSH/sudo secrets изAW_SSH_PASSWORDиAW_SUDO_PASSWORD;proxmoxчитает SSH/sudo secrets изAW_PROXMOX_SSH_PASSWORDиAW_PROXMOX_SUDO_PASSWORD, с fallback наAW_SSH_PASSWORD/AW_SUDO_PASSWORD;aw_windowsчитает WinRM secret изAW_WINRM_PASSWORD;inventory.example.iniбольше не содержит placeholder password-поля.
Проверки:
bash -n scripts/detmir_resilience_check.sh
bash scripts/detmir_resilience_check.sh --repo
Результат локальной проверки:
- shell syntax passed for
scripts/detmir_resilience_check.sh; - shell syntax passed for
scripts/run_awatch_contour_check.sh; - repo-mode passed with
ok=15,fail=0; - repo-mode reported one WARN: literal Ansible password assignments appear to
exist in
ansible/inventory.ini; values are not printed, andDETMIR_RESILIENCE_STRICT_SECRETS=1converts this to fail for private contour gates.
Live AW server result:
bash /tmp/detmir_resilience_check.sh --livepassed on AW server;- result:
ok=9,warn=1,fail=0; - WARN is expected after this rollout: one quarantine
reason.jsonexists for the moved stale Hayabusa staging residue.
2026-06-24: live drift fixes after full contour re-check
Статус: deployed and verified live.
Что было найдено:
- ClickHouse container was healthy by direct SQL checks, but Docker Compose did
not define a container
HEALTHCHECK; because of thataw-1c-clickhouse-health.servicefailed withdocker healthcheck is not configured. detmir-autoused the default public gateway URL for portal checks when/etc/detmir/detmir-check.envdid not setDETMIR_PORTAL_URL; protected public/readyz,/versionand/metricsreturned legitimate401.detmir-portal-prewarm.servicehadcurl --max-time 60, but a cold/api/reportsbuild on the live contour can take more than 60 seconds.aw-rus-healthd-rustused the default 20 second wrapper timeout; under concurrent checksdlp-health-check --jsoncould be killed mid-output and be reported asinvalid JSON output.
Что изменено:
clickhouse-1c/docker-compose.ymlnow defines a ClickHouse clientHEALTHCHECK, deployed to/opt/activitywatch/clickhouse-1c/docker-compose.yml;- production
/etc/detmir/detmir-check.envnow containsDETMIR_PORTAL_URL=http://127.0.0.1:8720andDETMIR_GATEWAY_HOST=127.0.0.1; ops/systemd/detmir-portal-prewarm.serviceis now tracked in the repo and deployed withcurl --max-time 180andTimeoutStartSec=210;- production
/etc/activitywatch/aw-server.envandaw-server/aw-server.env.examplenow setAW_RUS_HEALTH_WRAPPER_TIMEOUT_SECONDS=90.
Verification:
check-aw-full.sh:FRESH=8,STALE=0,DEAD=0;detmir-checkthrough the production env file:ok=true,service_failures=0;detmir-auto.service,awatch-contour-daily-check.service,awatch-contour-weekly-check.service:status=0/SUCCESS;detmir-portal-prewarm.service:status=0/SUCCESS;aw-1c-clickhouse-health.service:status=0/SUCCESS, Docker state(healthy);aw-rus-healthd.service:status=0/SUCCESS, failed systemd units on AW server and Proxmox are zero.
2026-06-25: portal cold-start prewarm after service restart
Статус: deployed and verified live at the time, then superseded by the fail-soft hot-path boundary below.
Что было найдено:
- после ручного
systemctl restart detmir-portalпервый/api/reports?role=managerможет выполнять холодный расчет дольше 120 секунд; detmir-portal-prewarm.timerдержит cache теплым каждые 30 минут, но не запускается немедленно при ручном рестарте портала.- одного prewarm недостаточно, если каждый пользовательский
/api/reportsзаново запускает тяжелую генерацию отчета.
Что изменено:
- добавлен tracked drop-in
ops/systemd/detmir-portal.service.d/30-prewarm-after-start.conf; - production drop-in
/etc/systemd/system/detmir-portal.service.d/30-prewarm-after-start.confзапускаетdetmir-portal-prewarm.serviceчерезsystemctl --no-blockпосле каждого старта портала; - prewarm остается best-effort: портал стартует независимо, а тяжелый
/api/reportsпрогревается в фоне. - в
detmir-portalдобавлен short-lived in-process report cache с TTL 120 секунд и защитой от stampede: первый report-запрос строит payload, следующие report endpoints в окне TTL отдают тот же payload без повторной генерации. - в
/metricsдобавлены отдельные счетчики report-cache:awatch_report_requests_total,awatch_report_cache_hits_total,awatch_report_cache_misses_total. Старыйawatch_reports_generated_totalостается счетчиком успешно завершенных тяжелых генераций отчета, а не счетчиком HTTP-запросов.
Verification:
/healthz:200;/readyz:200,status=ready;- prewarm after restart:
status=0/SUCCESS; - cold
/api/reports?role=managerafter expired cache:200, около63s; - warm
/api/reports?role=manager:200, около0.34..0.35sв трех последовательных запросах; awatch_reports_generated_totalне вырос после трех warm report-запросов;awatch_report_requests_totalрастет на report endpoints, аawatch_report_cache_hits_totalрастет на warm cache-запросах;- во время cold/prewarm сборки
awatch_report_requests_totalпоказывает входящие report-запросы до ожидания cache lock, аawatch_reports_generated_totalрастет только после готового payload; workforce_operations.summaryиworkforce_operations.rowsдоступны в JSON;- browser smoke: блок
Операционная загрузкаотрисован, строки сотрудников видны, console errors/warnings отсутствуют.
Superseded note:
- restart-triggered external prewarm reduced warm-cache latency, but it also kept a heavy full-report job coupled to service restart;
- after the DLP/hot-path phase 1 change, the preferred production behavior is
immediate
warming/STALEAPI response from the portal itself, not a mandatory heavyExecStartPostprewarm after every restart; - legacy drop-ins
/etc/systemd/system/detmir-portal.service.d/20-prod-timeout.confand/etc/systemd/system/detmir-portal.service.d/30-prewarm-after-start.confare now treated as stale deployment residue and are removed byansible/deploy_detmir_portal.yml.
2026-06-25: current state and first DLP hot-path boundary
Статус: phase 1 implemented, targeted Rust tests passed, deployed once on the DetMir portal host and API-smoke verified. Follow-up production cleanup of stale restart-prewarm drop-ins is pending until DetMir VPN handshake is stable again.
Фактический runtime:
- production
detmir-portalbinary:653b22b0fbf29a22f7de42ade7b689490b1de16fa07e785e4e0efd3078e7a3bc; - deploy command used:
ansible-playbook -i inventory.ini deploy_detmir_portal.yml --limit proxmox -e detmir_portal_bind_override=0.0.0.0:8720 -e detmir_portal_dlp_module_enabled_override=false; /healthz:status=okafter deploy;/readyz:status=readyafter deploy;/api/reports:ok=true,cache_status=warming,modules.dlp.enabled=false,modules.dlp.hot_path=false;/api/operator:cache_status=warming,summary.severity=STALE,modules.dlp.status=disabled,incidents=0;- server log:
/api/operatorreturned200withlatency_ms=49; - browser smoke after restart:
loadStatus=STALE, progress100%,LOADING=false,EMPTY=false,ERROR=false.
Что это означает:
- первичное зависание портала устранено на уровне UX/cache/stale fallback;
/api/operatorno longer waits for the cold full snapshot and can return a boundedwarmingpayload;- тяжелая генерация полного отчета/snapshot все еще может быть дорогой во время cold/prewarm;
- DLP/security enrichment has a first runtime boundary out of the Workforce hot
path: phase 1 used
DETMIR_PORTAL_DLP_MODULE_ENABLED=false; the current DetMir production default keeps DLP runtime disabled/core_only, whilelightremains an explicit operator re-enable profile after resource check; - текущее состояние зафиксировано отдельно:
docs/DETMIR_CURRENT_STATE_RU.md.
Архитектурное решение для следующего шага:
- Workforce core должен оставаться быстрым и доступным без DLP;
- DLP evidence, endpoint signals, screenshots, case review, heavy correlation and forensics enrichment должны стать optional module;
- prewarm не должен обязательно выполнять heavy DLP path;
- Security/Forensics views при отключенной DLP должны показывать disabled-state, а не ломать portal readiness.
Реализованная первая граница:
- CLI/env flag:
--dlp-module-enabled/DETMIR_PORTAL_DLP_MODULE_ENABLED; - DetMir production default после resource hardening:
false/core_only, чтобы обычный deploy/recovery не возвращал DLP нагрузку на Proxmox, AW, ClickHouse, InfluxDB и Grafana; lightдопускается только как явное operator re-enable действие после resource check; приlightосновной portal snapshot не читает тяжелые incident/case/review/audit DLP state, а evidence/case/exporter path остается выключенным;- Ansible deploy parameter:
detmir_portal_dlp_module_enabled_override.
Проверено локально:
cargo test -p detmir-portal --locked;cargo clippy -p detmir-portal --all-targets --locked -- -D warnings.
Deployment cleanup status:
ansible/deploy_detmir_portal.ymlnow removes stale restart-prewarm drop-ins:20-prod-timeout.confand30-prewarm-after-start.conf;- repeat production deploy of that cleanup is pending because the DetMir
pfSense-gate-UDP4-1194-vpn_prog10-configtunnel later failed TLS handshake to178.178.98.83:1194; - do not claim final production prewarm cleanup until
systemctl cat detmir-portalno longer showsExecStartPostprewarm.
Ограничения:
- это не удаление DLP collectors;
- это не claim, что production DLP decoupling уже завершен без live smoke;
- это не registry release evidence;
- GitHub/GitHub Actions не являются primary registry build contour.
2026-06-30: DLP disabled/core_only default, load guard and rollback
Статус: implemented in repository defaults/scripts/docs, deployed on live DetMir contour and verified manually.
Что изменено:
- DetMir production defaults переведены в
AW_DLP_ENABLED=falseиAW_DLP_PROFILE=core_only; aw_dlp_enabled=false,aw_dlp_influx_enabled=false;- lightweight collector остается подключаемым, но не стартует по умолчанию;
- heavy DLP component flags в production defaults остаются выключены;
detmir_portal_dlp_module_enabled_override=falseпоказывает честный disabled-state в портале без heavy evidence/case path;- добавлен
scripts/detmir_dlp_load_guard.sh; detmir-dlp-load-guard.timerконтролирует load/RAM/iowait и при перегрузе переводит DLP вcore_only;- Ansible DLP tasks больше не имеют DLP-heavy default
true; scripts/detmir_dlp_runtime_control.shполучил профилиcore_only,light,on_demand,full;- перед каждым
set-profileсохраняется rollback-снимок systemd active/enabled состояния DLP units; rollbackвосстанавливает предыдущее состояние DLP units без изменения retention и без запуска Loki CT.
Эксплуатационная позиция:
- Loki CT отключён намеренно для снижения нагрузки на Proxmox VM/LXC;
- Loki не является обязательной зависимостью Workforce/Worktime/AW core;
- DLP не удалён: lightweight-сбор нужен для UEBA, а тяжелый runtime не должен возвращаться обычным deploy/recovery;
- Hayabusa/Velociraptor findings остаются отдельным optional security layer через Security Finding Inbox / ClickHouse и не требуют Loki.
Runbook:
docs/DLP_RESOURCE_PROFILES_RU.md;docs/DLP_OPTIONAL_RUNTIME_RU.md.
2026-06-24: fail-closed timeout hardening after manual live run
Статус: implemented locally, targeted Rust tests passed, deployed and verified live.
Что было найдено ручным прогоном:
- при деградации
activitywatch-serverзапросы/api/0/bucketsи отдельные bucket event endpoints могли занимать 15-30 секунд; detmir-checkмог зависнуть без общего дедлайна, а штатные daily/weekly checks оставались вactivating;- timeout в
detmir-checkубивал shell, но мог оставитьdetmir-dlp/sshхвост, который удерживал stdout pipe; detmir-dlpне имел собственного SSH timeout;- прямой
dlp-health-check --jsonна AW server мог зависать дольше ожиданий; aw-worktime-autoheal-rustсчитал ошибкой timeout чтения response body после POST backfill, хотя ActivityWatch уже мог применить запись.
Что изменено:
detmir-checkполучил общий watchdogDETMIR_CHECK_OVERALL_TIMEOUT_SECONDSи env-настройкиDETMIR_SERVICE_TIMEOUT_SECONDS,DETMIR_BUCKET_TIMEOUT_SECONDS,DETMIR_DLP_TIMEOUT_SECONDS;- production
/etc/detmir/detmir-check.envнастроен на:DETMIR_SERVICE_TIMEOUT_SECONDS=35,DETMIR_BUCKET_TIMEOUT_SECONDS=35,DETMIR_DLP_TIMEOUT_SECONDS=120,DETMIR_CHECK_OVERALL_TIMEOUT_SECONDS=300; detmir-checkиdetmir-autoубивают timed-out child process group, чтобы не оставлять shell/SSH/DLP хвосты;detmir-dlpполучил bounded SSH timeout и больше не выносит SSH child в отдельную process group, чтобы parent timeout мог убить всю ветку;dlp-health-checkполучил общий self-timeoutAW_DLP_HEALTH_OVERALL_TIMEOUT_SECONDSс default 120 секунд;aw-worktime-autoheal-rustдля POST events проверяет HTTP status и не читает response body, потому что body не нужен для backfill evidence.
Safety guardrails:
- изменения не меняют AW API schema, bucket names, UI или product workflow;
- timeout failure остается красным, но больше не оставляет активные процессы и lock poisoning;
- production timeouts расширены только до фактической live latency, общий deadline остается bounded;
- remote DLP и worktime autoheal не публикуют secrets/PII в logs сверх уже существующих operational identifiers.
Проверки:
cargo test --manifest-path adk-rust/Cargo.toml \
-p detmir-check -p detmir-auto -p detmir-dlp -p dlp-health-check \
-p worktime-autoheal
cargo build --manifest-path adk-rust/Cargo.toml --release \
-p detmir-check -p detmir-auto -p detmir-dlp -p dlp-health-check \
-p worktime-autoheal
Live verification:
dlp-health-check --json:ok=22,warn=0,fail=0, elapsed 17s;aw-worktime-autoheal.service: success, postedafk=28,win=28;aw-rus-healthd.service: success,ok=13,warn=1,fail=0;detmir-checkthrough production env:rc=0, elapsed 19s;detmir-auto.service:rc=0, elapsed 56s, bucketdead=0,stale=0,ok=8;awatch-contour-daily-check.service:rc=0, elapsed 14s;awatch-contour-weekly-check.service:rc=0, elapsed 136s;check-aw-full.sh:FRESH=8,STALE=0,DEAD=0;- final AW/PVE failed systemd units:
0; - final RDP guard: service
Running, 13 telemetry processes, last guard cyclesstatus=ok problems=0.
2026-06-30: manual collection and analysis smoke after DLP light enablement
Статус: partially green, live fixes applied, one external reachability blocker remains.
Ручной прогон подтвердил:
activitywatch-serverandaw-worktime-apiare active;- Worktime API
/reports/worktime/todayreturns current data for 4 users; - DetMir portal
/portalrenders through browser and no frontend console error was observed for the tested portal pages; /api/managerreturns OK after restoring the portal timeout to 25 seconds;/api/operatorreturns current collection/DLP/Grafana/1C/worktime blocks;- Security Finding Inbox is reachable for
security/adminrole headers and returns ClickHouse backendstatus=ok,open_count=0; - DLP light warehouse is present on the portal host and DLP checks show OK in the operator card;
- Grafana backend is reachable directly at
10.10.10.11:3000/api/health.
Live fixes applied:
- removed stale systemd drop-in
/etc/systemd/system/detmir-portal.service.d/10-detmir-check-env.conf; - restored
/etc/detmir-portal.envtimeout toDETMIR_PORTAL_TIMEOUT_SECONDS=25; - updated
/etc/detmir/detmir-check.envfor the current light profile:DETMIR_DLP_ENABLED=trueandDETMIR_DISABLE_DLP_HEALTH_CHECK=true; - updated
/var/lib/detmir-ai/latest-runto the fresh 2026-06-30detmir-checkJSON so the portal no longer displays the stale 2026-06-25 collection snapshot; - updated Ansible to remove the stale portal timeout override during deploy.
Remaining live blocker:
detmir-checkstill fails by design because RDP host192.168.100.19responds to ICMP, but TCP22and5985time out from the DetMir contour;awatch-contour-daily-check.servicetherefore remains failed withservice_failures=2;- this is not an AW-server, Worktime API, DLP warehouse, ClickHouse, or portal rendering failure. It is the current RDP control/reachability failure.
Grafana note:
- Browser access to Grafana through the gateway is protected by Basic Auth and the current certificate chain is not trusted by the Playwright browser when opened by IP/DNS in this run;
- direct backend health check is green:
http://10.10.10.11:3000/api/health -> 200; - gateway returns
401without credentials, which is expected for the protected dashboard entrypoint.