chore(public): sanitize repository presentation

This commit is contained in:
igor04091968
2026-06-03 08:02:15 +03:00
parent dd3163624b
commit 9fc218dc49
107 changed files with 829 additions and 139257 deletions
+11 -2
View File
@@ -1,6 +1,9 @@
# Local secrets
secrets/deploy.secrets.env
secrets/runtime.env
/secrets/
/private-config/*.env
/private-config/*.local
/ansible/inventory.ini
/codex_history.txt
# Runtime / reports
*.log
@@ -26,3 +29,9 @@ graphify-out/cache/
.planning/
.pssa_run.ps1
data/
# Generated analysis artifacts
/graphify-out/
/.graphify_*.json
/.graphify_*.txt
/.graphify_python/
-11236
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -38,7 +38,7 @@ Keep this file minimal and high-signal: only include facts an agent would otherw
- Do NOT commit secrets (secrets/ are local-only; PRs must not contain real secrets).
- Many scripts assume they run on the target CT or on a Linux admin host with `pct` available. Don't try to run them on macOS without adapting dependencies.
- `aw-server/install_aw_server.sh` expects network access to download the AW release URL provided by AW_SERVER_DOWNLOAD_URL.
- `aw-server/apply_webui_ru_patch.sh` must run after AW webui files are present; it will fail if required bootstrap files under `/root/bootstrap` are missing.
- `aw-server/apply_webui_ru_patch.sh` must run after AW webui files are present; it will fail if required bootstrap files under `<CT_BOOTSTRAP_DIR>` are missing.
- When pushing AW_SERVER env via `push-aw-artifacts.sh` the script will only write `/etc/activitywatch/aw-server.env` if all AW_SERVER_* variables are set; otherwise it warns and skips.
8) PR / commit checklist for agents
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+25 -21
View File
@@ -1,31 +1,25 @@
# AWatch-rus
AWatch-rus помогает спокойно смотреть, что происходит в рабочей среде: кто работал удаленно, сколько было активного времени, какие окна были открыты, были ли события безопасности и не пропали ли данные.
AWatch-rus / DetMir - программный комплекс операционного контроля,
технического аудита и мониторинга корпоративной ИТ-инфраструктуры на базе
ActivityWatch, Rust-сервисов автоматизации, Grafana/Prometheus-витрин и
модулей расследования инцидентов.
Первый экран проекта теперь не про установку и скрипты. Для повседневной работы начинайте с дашбордов.
Проект не позиционируется как сертифицированная DLP/SIEM/EDR/XDR/СЗИ. DLP,
evidence и Hayabusa используются как прикладные модули внутри платформы
операционного контроля и технического аудита.
## Открыть дашборды
## Назначение
Основная страница:
- Контроль доступности и свежести данных ActivityWatch.
- Учет активного времени, RDP-сессий, окон, приложений и рабочих интервалов.
- Витрины Grafana для администратора, оператора ИБ и руководителя.
- Автоматизация runbook-проверок, health-check, SLO и безопасного auto-heal.
- Сбор evidence по инцидентам и аудит действий оператора.
- [Grafana dashboards](http://10.10.10.11:3000/dashboards)
## Что видит оператор
Полезные панели:
- `DetMir ActivityWatch` - общая картина по активности.
- `DetMir: Работа пользователей в RDP` - кто работал, когда и в каких сессиях.
- `DetMir: DLP и ИБ обзор` - копирование, печать, USB, браузеры и другие события безопасности.
- `DetMir: ИБ сводка для руководства` - короткая управленческая сводка без лишних деталей.
- `AW-rus: DLP обзор` - отдельный обзор DLP-потока.
Дополнительные интерфейсы:
- [ActivityWatch Web UI](http://10.10.10.13:5600) - исходные события и детальный просмотр ActivityWatch.
- [Worktime reports](http://10.10.10.13:5610) - отчеты по рабочему времени, если сервис включен.
## Что видно без технических деталей
- Работал ли пользователь за компьютером или в RDP-сессии.
- Работал ли пользователь за компьютером или в удаленной сессии.
- Когда была активность, простой и переключение окон.
- Какие приложения, сайты и процессы чаще всего были в работе.
- Есть ли события, важные для ИБ: копирование, печать, USB, подозрительные сайты.
@@ -41,6 +35,16 @@ AWatch-rus помогает спокойно смотреть, что проис
Обычно это значит одно из трех: выбран слишком узкий период времени, рабочий компьютер давно не присылал события или временно не обновилась витрина в Grafana. Начните с периода `Last 24 hours`, затем переходите к техническим разделам ниже.
## Поставка и регистрация
- [Позиционирование для реестра российского ПО](docs/DETMIR_RUSSIAN_SOFTWARE_REGISTRY_POSITIONING_RU.md)
- [Сведения для подачи в реестр](REGISTER_RU_SOFTWARE.md)
- [Архитектура](docs/ARCHITECTURE_RU.md)
- [Установка](docs/INSTALL_RU.md)
- [Руководство администратора](docs/ADMIN_GUIDE_RU.md)
- [Руководство оператора](docs/OPERATOR_GUIDE_RU.md)
- [Лицензия](LICENSE)
## Техническая документация
Для эксплуатации и настройки:
+117
View File
@@ -0,0 +1,117 @@
# Сведения для подачи в реестр российского ПО
## 1. Назначение ПО
`DetMir` на базе `AWatch-rus` - программный комплекс операционного контроля,
технического аудита и мониторинга ИТ-инфраструктуры.
ПО предназначено для:
- контроля состояния сервисов и endpoint-сборщиков;
- учета пользовательской активности и рабочего времени;
- централизованного технического аудита событий;
- отображения данных в Grafana/портале оператора;
- автоматизации runbook-проверок, SLO-контроля и безопасного реагирования;
- фиксации evidence по прикладным инцидентам и аудита действий оператора.
ПО не заявляется как сертифицированная DLP, SIEM, EDR/XDR или средство защиты
информации. Модули DLP/evidence/Hayabusa рассматриваются как прикладные модули
операционного контроля и расследования событий.
## 2. Класс ПО
Основной целевой класс:
- `09.10 Средства управления ИТ-службой, ИТ-инфраструктурой и ИТ-активами`.
Возможный дополнительный контекст:
- автоматизация регламентов эксплуатации;
- технический аудит;
- мониторинг корпоративной инфраструктуры.
## 3. Правообладатель
Правообладатель: владелец репозитория и программного комплекса `DetMir /
AWatch-rus`.
Перед подачей в реестр рекомендуется оформить отдельный правообладательский
пакет:
- сведения о правообладателе;
- подтверждение авторства собственных модулей;
- перечень сторонних компонентов;
- условия лицензирования и распространения;
- при необходимости - свидетельство Роспатента о регистрации программы для ЭВМ.
## 4. Состав поставки
В состав поставки входят:
- Rust workspace `adk-rust/` с основными runtime helpers;
- Ansible playbooks для установки и обновления серверных компонентов;
- Windows PowerShell collectors и deployment scripts;
- Grafana dashboards и monitoring assets;
- ActivityWatch server customization и RU WebUI patching;
- портал оператора;
- документация администратора, оператора, установки и архитектуры;
- install-kit artifacts для повторяемой поставки.
Индивидуальные production inventory, пароли, токены, домены, IP-адреса и
локальные runtime-файлы не входят в публичную поставку.
## 5. Установка экземпляра
Типовой порядок установки:
1. Подготовить Linux/Proxmox или другой серверный runtime согласно
`docs/INSTALL_RU.md`.
2. Скопировать `private-config/deploy.env.example` в локальный
`private-config/deploy.env` и заполнить параметры конкретного экземпляра.
3. Подготовить Ansible inventory локально на основе
`ansible/inventory.example.ini`.
4. Собрать Rust release artifacts:
```bash
cd adk-rust
cargo build --release --workspace
```
5. Выполнить playbooks установки серверных компонентов и сборщиков.
6. Проверить контур:
```bash
scripts/quality-gate.sh
detmir-check
detmir-status
```
Точные адреса сервисов, домены, учетные данные и токены задаются только в
локальных конфигурационных файлах экземпляра.
## 6. Сторонние компоненты
Основные внешние компоненты:
- ActivityWatch;
- Rust crates ecosystem;
- Grafana;
- Prometheus/InfluxDB exporters and clients;
- Ansible;
- PowerShell/Windows runtime;
- SQLite;
- Hayabusa and related DFIR tooling where enabled.
Детальный перечень ведется в `docs/THIRD_PARTY_LICENSES_RU.md`.
## 7. Ограничения и зависимости
- Для полноценной работы нужны права администратора на устанавливаемых
серверных и endpoint-компонентах.
- Telegram runtime, если используется, остается отдельным Python-компонентом.
- OCR/content-analysis может использовать Python-зависимости для обработки
изображений; основной серверный runtime переведен на Rust-first helpers.
- Сетевые адреса, домены, токены и inventory являются параметрами конкретного
экземпляра и не должны публиковаться в репозитории.
- Продукт не заменяет формально сертифицированные средства защиты информации
без отдельной сертификации и модели угроз.
+6 -6
View File
@@ -19,11 +19,11 @@
Подтвержденный runtime для `DetMir`:
- `10.10.10.13` — основной `AW-rus` server, health, worktime/reporting, DLP server-side services, `Hayabusa` processing.
- `10.10.10.2` — operator/gateway host, Telegram bot, web gateway, часть `1C` analytics runtime.
- `192.168.100.18``SHARKON2025`, Windows/RDP host с collector toolkit.
- `10.10.10.11` — Grafana.
- `10.10.10.1``pfSense`, сетевой perimeter и VPN.
- `<AW_SERVER_HOST>` — основной `AW-rus` server, health, worktime/reporting, DLP server-side services, `Hayabusa` processing.
- `<GATEWAY_HOST>` — operator/gateway host, Telegram bot, web gateway, часть `1C` analytics runtime.
- `<WINDOWS_HOST>``SHARKON2025`, Windows/RDP host с collector toolkit.
- `<GRAFANA_HOST>` — Grafana.
- `<FIREWALL_HOST>``pfSense`, сетевой perimeter и VPN.
Ключевые потоки данных:
@@ -343,7 +343,7 @@ Collector и server-side сервисы проектировались так,
- operator/Codex remote path к Windows host;
- `SSH + powershell.exe` вместо `WSMan` для interactive operations;
- преднастроенный управляемый PowerShell path для `192.168.100.18`.
- преднастроенный управляемый PowerShell path для `<WINDOWS_HOST>`.
## Деплой и эксплуатация
+7 -7
View File
@@ -12,7 +12,7 @@ runbook.
Текущий resume snapshot проекта хранится в
`.ai/runtime/detmir-current-session.md`. Перед продолжением миграции после
перерыва или context reset сначала читать его, затем `RUNBOOK.md` и
`/home/igor/.codex/skills/detmir-rust-migration/references/current-state.md`.
`<OPERATOR_CODEX_HOME>/skills/detmir-rust-migration/references/current-state.md`.
## 1. Целевое состояние
@@ -703,7 +703,7 @@ systemctl is-active tsj-guardian-bot tsj-guardian-watchdog gost-tg
binary `stat`/`copy`, чтобы `CARGO_TARGET_DIR` работал одинаково для
Proxmox/Telegram и AW-server deploy. Добавлен
`scripts/check_detmir_rust_release_artifacts.sh`; проверено
`CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target cargo build
`CARGO_TARGET_DIR=<OPERATOR_HOME>/.cache/detmir-adk-rust-target cargo build
--release --workspace`, artifact check OK, `deploy_aw_server.yml
--syntax-check` OK.
20. `[done]` Прогнать production AW-server deploy contract и закрыть найденные
@@ -938,7 +938,7 @@ systemctl is-active tsj-guardian-bot tsj-guardian-watchdog gost-tg
перезапускались в рамках этого шага;
- artifact check расширен `aw-prune-local-state`.
32. `[done]` Устранить нехватку места на AW server через Proxmox resize:
- CT `203` (`aw-server`, `10.10.10.13`) rootfs расширен через Proxmox
- CT `203` (`aw-server`, `<AW_SERVER_HOST>`) rootfs расширен через Proxmox
`pct resize 203 rootfs +20G`;
- перед resize сохранен config backup:
`/var/lib/detmir-ai/switch-backups/ct203-aw-server.before-rootfs-resize-20260602T054826Z.conf`;
@@ -1076,7 +1076,7 @@ systemctl is-active tsj-guardian-bot tsj-guardian-watchdog gost-tg
чтобы full deploy не затирал рабочие Influx credentials пустыми
значениями;
- полный `ansible-playbook -i inventory.ini deploy_aw_server.yml
-e aw_rust_release_dir=/home/igor/.cache/detmir-adk-rust-target/release`
-e aw_rust_release_dir=<OPERATOR_HOME>/.cache/detmir-adk-rust-target/release`
прошел до конца: `failed=0`, `ok=282`;
- final gates после deploy зеленые: `aw-db-health` OK,
`aw-health-check` OK, `dlp-health-check` `22/0/0`,
@@ -1308,7 +1308,7 @@ systemctl is-active tsj-guardian-bot tsj-guardian-watchdog gost-tg
`dlp_counts={ok:22,warn:0,fail:0}` and `ok_for_operator=true`.
46. `[done]` Перенести Proxmox DetMir contour smoke на Rust-first helper:
- добавлен crate `aw-contour-smoke`;
- `scripts/aw-contour-smoke-10.10.10.2.sh` теперь Rust-first wrapper:
- `scripts/aw-contour-smoke-<GATEWAY_HOST>.sh` теперь Rust-first wrapper:
ищет `AW_CONTOUR_SMOKE_RUST`,
`$CARGO_TARGET_DIR/release/aw-contour-smoke`,
`adk-rust/target/release/aw-contour-smoke`,
@@ -1545,7 +1545,7 @@ systemctl is-active tsj-guardian-bot tsj-guardian-watchdog gost-tg
`/usr/local/bin/detmir-portal`, `detmir-portal.service`,
bind `127.0.0.1:8720`;
- внешний route добавлен в существующий nginx gateway:
`https://dm.iri1968.dpdns.org/portal/`;
`https://<PUBLIC_GATEWAY_FQDN>/portal/`;
- UI содержит вкладки `Оператор`, `Руководитель`, `Владелец`,
`Инциденты ИБ`;
- API реализованы: `/api/health`, `/api/summary`, `/api/operator`,
@@ -1614,7 +1614,7 @@ systemctl is-active tsj-guardian-bot tsj-guardian-watchdog gost-tg
AW-server evidence-only service, `/usr/local/bin/detmir-portal-evidence`
with `detmir-portal-evidence.service`, because the DLP warehouse lives on
the AW server. Proxmox nginx gateway routes
`/portal/api/dlp/evidence*` to `10.10.10.13:8721`. Current production
`/portal/api/dlp/evidence*` to `<AW_SERVER_HOST>:8721`. Current production
verification: AW evidence API `ok=true`, gateway evidence route
`ok=true`, `db_available=true`, 11 DLP evidence rows returned,
`screenshot_available=0` because current stored rows do not yet contain
+9 -4
View File
@@ -1,12 +1,10 @@
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::process::Command;
use anyhow::{Context, Result, bail};
use clap::Parser;
const PLAYWRIGHT_NODE_MODULES: &str = "/home/igor/.agents/skills/playwright/node_modules";
#[derive(Debug, Parser)]
#[command(
about = "Rust launcher for the ActivityWatch-Russian browser smoke test",
@@ -73,7 +71,14 @@ fn default_node_path(current: Option<&OsStr>) -> Option<OsString> {
if current.is_some_and(|value| !value.is_empty()) {
return None;
}
let path = Path::new(PLAYWRIGHT_NODE_MODULES);
let Some(home) = std::env::var_os("HOME") else {
return None;
};
let path = PathBuf::from(home)
.join(".agents")
.join("skills")
.join("playwright")
.join("node_modules");
if path.is_dir() {
Some(path.as_os_str().to_os_string())
} else {
+1 -1
View File
@@ -16,7 +16,7 @@ const DEFAULT_AW_API: &str = "http://10.10.10.13:5600/api/0";
const DEFAULT_WORKTIME_URL: &str = "http://10.10.10.13:5610";
const DEFAULT_ONE_C_URL: &str = "http://10.10.10.2:8710";
const DEFAULT_HOSTNAME: &str = "SHARKON2025";
const DEFAULT_GATEWAY_HOST: &str = "dm.iri1968.dpdns.org";
const DEFAULT_GATEWAY_HOST: &str = "detmir.example.local";
#[derive(Debug, Parser)]
#[command(about = "Autonomous read-only DetMir contour check from Proxmox.")]
@@ -108,7 +108,7 @@ fn run() -> Result<i32> {
.root
.canonicalize()
.with_context(|| format!("canonicalize root {}", cli.root.display()))?;
let env_file = root.join("secrets/runtime.env");
let env_file = root.join("private-config/runtime.env");
let env_values = read_env_file(&env_file).unwrap_or_default();
let timestamp = cli
.timestamp
@@ -452,7 +452,7 @@ mod tests {
env.insert("AW_WINRM_PASSWORD".to_string(), "hidden".to_string());
let plan = build_plan(
dir.path(),
&dir.path().join("secrets/runtime.env"),
&dir.path().join("private-config/runtime.env"),
&env,
"10.10.10.13",
"igor",
+3 -3
View File
@@ -101,7 +101,7 @@ fn run() -> Result<i32> {
.timestamp
.clone()
.unwrap_or_else(|| Local::now().format("%Y%m%d-%H%M%S").to_string());
let env_file = root.join("secrets/runtime.env");
let env_file = root.join("private-config/runtime.env");
let env_values = read_env_file(&env_file).unwrap_or_default();
let inventory = absolute_path(&root, &cli.inventory);
let log_dir = root.join(".rollout-logs").join(&timestamp);
@@ -609,7 +609,7 @@ mod tests {
env.insert("AW_WINRM_PASSWORD".to_string(), "hidden".to_string());
let plan = build_plan(
dir.path(),
&dir.path().join("secrets/runtime.env"),
&dir.path().join("private-config/runtime.env"),
&env,
&dir.path().join("ansible/inventory.ini"),
&dir.path().join(".rollout-logs/test"),
@@ -645,7 +645,7 @@ mod tests {
create_file(dir.path().join("ansible/post_validate_aw_windows.yml"));
let plan = build_plan(
dir.path(),
&dir.path().join("secrets/runtime.env"),
&dir.path().join("private-config/runtime.env"),
&HashMap::new(),
&dir.path().join("ansible/inventory.ini"),
&dir.path().join(".rollout-logs/test"),
@@ -10,8 +10,6 @@ use sha2::{Digest, Sha256};
use zip::write::SimpleFileOptions;
const KIT_DIR: &str = "install-kit-awindows-20260427-211240";
const SERVER_CONFIG_DIR: &str = "server-configs-192.168.100.18";
const OLD_SERVER_CONFIG_DIR: &str = "server-configs-192.168.100.21";
const README: &str = r#"ActivityWatch DetMir Windows Install Kit
Includes:
@@ -19,10 +17,13 @@ Includes:
- ansible/* (Windows and AW server playbooks, examples, inventory, tasks)
- aw-server/* (server installer, health orchestrator, RU patch loader, host groups, default settings)
- scripts/* (install-kit rebuild/validation, quality gates, browser/web smoke checks)
- server-configs-192.168.100.18/* (working Windows/RDP config snapshots)
Source:
- Local project snapshot at build time.
Customer-specific deployment configs, inventories, passwords, tokens, domains,
IP addresses and runtime snapshots are intentionally excluded from this public
install-kit.
"#;
const ANSIBLE_FILES: &[&str] = &[
@@ -124,7 +125,6 @@ fn run() -> Result<()> {
fn rebuild(root: &Path) -> Result<()> {
let kit = root.join(KIT_DIR);
let preserved_configs = preserve_server_configs(&kit)?;
for name in ["ansible", "aw-server", "windows", "scripts"] {
remove_if_exists(&kit.join(name))?;
}
@@ -139,16 +139,6 @@ fn rebuild(root: &Path) -> Result<()> {
copy_file(root, &kit, rel)?;
}
let server_config_dir = kit.join(SERVER_CONFIG_DIR);
fs::create_dir_all(&server_config_dir)
.with_context(|| format!("create {}", server_config_dir.display()))?;
for (name, bytes) in preserved_configs {
let path = server_config_dir.join(name);
write_file_replace(&path, &bytes).with_context(|| {
format!("restore server config into {}", server_config_dir.display())
})?;
}
write_file_replace(&kit.join("README-INSTALL-KIT.txt"), README.as_bytes())
.with_context(|| format!("write {}", kit.join("README-INSTALL-KIT.txt").display()))?;
write_manifest(root, &kit)?;
@@ -157,32 +147,6 @@ fn rebuild(root: &Path) -> Result<()> {
Ok(())
}
fn preserve_server_configs(kit: &Path) -> Result<Vec<(String, Vec<u8>)>> {
let mut out = std::collections::BTreeMap::new();
for dir in [OLD_SERVER_CONFIG_DIR, SERVER_CONFIG_DIR] {
let path = kit.join(dir);
if !path.is_dir() {
continue;
}
for entry in fs::read_dir(&path).with_context(|| format!("read dir {}", path.display()))? {
let entry = entry.with_context(|| format!("read dir entry {}", path.display()))?;
let entry_path = entry.path();
if entry_path
.file_name()
.and_then(|name| name.to_str())
.is_some_and(|name| name.ends_with(".deployment-config.json"))
&& entry_path.is_file()
{
let name = entry.file_name().to_string_lossy().to_string();
let bytes = fs::read(&entry_path)
.with_context(|| format!("read {}", entry_path.display()))?;
out.insert(name, bytes);
}
}
}
Ok(out.into_iter().collect())
}
fn remove_server_config_dirs(kit: &Path) -> Result<()> {
if !kit.is_dir() {
return Ok(());
@@ -343,23 +307,7 @@ mod tests {
use tempfile::tempdir;
use super::{preserve_server_configs, remove_server_config_dirs};
#[test]
fn preserves_new_server_configs_over_old_duplicates() {
let tmp = tempdir().unwrap();
let kit = tmp.path();
let old = kit.join("server-configs-192.168.100.21");
let new = kit.join("server-configs-192.168.100.18");
fs::create_dir_all(&old).unwrap();
fs::create_dir_all(&new).unwrap();
fs::write(old.join("a.deployment-config.json"), "old").unwrap();
fs::write(new.join("a.deployment-config.json"), "new").unwrap();
let configs = preserve_server_configs(kit).unwrap();
assert_eq!(configs.len(), 1);
assert_eq!(configs[0].0, "a.deployment-config.json");
assert_eq!(configs[0].1, b"new");
}
use super::remove_server_config_dirs;
#[test]
fn removes_server_config_dirs_only() {
@@ -11,7 +11,7 @@ use serde::Serialize;
const DEFAULT_HEARTBEAT_FILE: &str = "/opt/infra-admin/.state/tsj_guardian_heartbeat";
const DEFAULT_SERVICE_NAME: &str = "tsj-guardian-bot.service";
const DEFAULT_GOST_SERVICE_NAME: &str = "gost-tg.service";
const DEFAULT_GOST_PATTERN: &str = "/usr/local/bin/gost -L http+socks5://127.0.0.1:11090 -F socks5+wss://gw.iri1968.dpdns.org:4443";
const DEFAULT_GOST_PATTERN: &str = "/usr/local/bin/gost -L http+socks5://127.0.0.1:11090 -F socks5+wss://gw.example.local:4443";
#[derive(Debug, Parser)]
#[command(about = "TSJ Guardian bot heartbeat watchdog and gost duplicate guard.")]
+1 -1
View File
@@ -248,7 +248,7 @@ Playbook:
- `telegram_allowed_chat_ids`
- `tsj_bot_source_local_path`
3. Убедитесь, что в inventory есть группа `[proxmox]`.
Для текущего контура AW-Rus bot ожидает Proxmox host `10.10.10.2`.
Для текущего контура AW-Rus bot ожидает Proxmox host `<GATEWAY_HOST>`.
Рабочая модель для этого контура: `igor` + `sudo`, а не обязательный `root` login.
4. При необходимости задайте recovery-команды для AW-Rus:
- `tsj_bot_aw_rus_worktime_heal_cmd`
+2 -2
View File
@@ -21,7 +21,7 @@
aw_file_1c_manager_brief_model: gpt-5.3-codex
aw_file_1c_manager_brief_codex_user: igor
aw_file_1c_manager_brief_codex_bin: codex
aw_file_1c_manager_brief_workdir: /home/igor
aw_file_1c_manager_brief_workdir: ~
aw_file_1c_manager_brief_top_limit: 5
aw_file_1c_manager_brief_freshness_hours: 8
aw_file_1c_manager_brief_timeout_sec: 300
@@ -295,7 +295,7 @@
- name: Разрешить Windows upload key для igor
ansible.builtin.lineinfile:
path: /home/igor/.ssh/authorized_keys
path: ~/.ssh/authorized_keys
line: "{{ lookup('file', aw_file_1c_windows_upload_pubkey_path) }}"
create: true
owner: igor
+2 -2
View File
@@ -5,7 +5,7 @@
gather_facts: true
vars:
proxmox_web_gateway_public_hostname: "dm.iri1968.dpdns.org"
proxmox_web_gateway_public_hostname: "detmir.example.local"
proxmox_web_gateway_root: "/var/www/proxmox-web-gateway"
proxmox_web_gateway_site_name: "proxmox-web-gateway.conf"
proxmox_web_gateway_site_path: "/etc/nginx/sites-available/{{ proxmox_web_gateway_site_name }}"
@@ -17,7 +17,7 @@
proxmox_web_gateway_auth_realm: "DetMir operations gateway"
proxmox_web_gateway_auth_user: "detmir"
proxmox_web_gateway_auth_file: "/etc/nginx/proxmox-web-gateway.htpasswd"
proxmox_web_gateway_credentials_file: "/root/proxmox-web-gateway.credentials"
proxmox_web_gateway_credentials_file: "/etc/detmir/proxmox-web-gateway.credentials"
proxmox_web_gateway_routes:
- slug: "proxmox-gui"
title: "Proxmox VE"
+6 -6
View File
@@ -229,7 +229,7 @@
TELEGRAM_PROXY_URL={{ tsj_bot_telegram_proxy_url | default('http://127.0.0.1:11090') }}
AI_CHAT_ENABLED={{ tsj_bot_ai_chat_enabled | default('true') }}
AI_CHAT_TIMEOUT_SEC={{ tsj_bot_ai_chat_timeout_sec | default(1800) }}
AI_CHAT_WORKDIR={{ tsj_bot_ai_chat_workdir | default('/home/igor') }}
AI_CHAT_WORKDIR={{ tsj_bot_ai_chat_workdir | default('~') }}
AI_CHAT_SANDBOX={{ tsj_bot_ai_chat_sandbox | default('workspace-write') }}
CODEX_MODEL={{ tsj_bot_codex_model | default('gpt-5.3-codex') }}
CODEX_FALLBACK_MODELS={{ tsj_bot_codex_fallback_models | default('gpt-5.4-mini') }}
@@ -238,8 +238,8 @@
TMUX_SESSION={{ tsj_bot_tmux_session | default('ai') }}
TMUX_CREATE_IF_MISSING={{ tsj_bot_tmux_create_if_missing | default('false') }}
TMUX_START_COMMAND={{ tsj_bot_tmux_start_command | default('codex') }}
PFSENSE_ENV_PATH={{ tsj_bot_pfsense_env_path | default('/home/igor/.config/tsj-bot/pfsense.env.readonly') }}
PFSENSE_INVENTORY_PATH={{ tsj_bot_pfsense_inventory_path | default('/home/igor/.config/tsj-bot/inventory.md') }}
PFSENSE_ENV_PATH={{ tsj_bot_pfsense_env_path | default('~/.config/tsj-bot/pfsense.env.readonly') }}
PFSENSE_INVENTORY_PATH={{ tsj_bot_pfsense_inventory_path | default('~/.config/tsj-bot/inventory.md') }}
PFSENSE_CHANGE_CONTROL_ENABLED={{ tsj_bot_pfsense_change_control_enabled | default('true') }}
PFSENSE_CHANGE_CONFIRM_TTL_SEC={{ tsj_bot_pfsense_change_confirm_ttl_sec | default(900) }}
OPENVPN_CONFIG_ENABLED={{ tsj_bot_openvpn_config_enabled | default('true') }}
@@ -327,14 +327,14 @@
- { key: "AW_RUS_WINDOWS_POLICY_PATH", value: "{{ tsj_bot_aw_rus_windows_policy_path | default('C:\\ProgramData\\AWatch-rus\\dlp-policy.json') }}" }
- { key: "AW_RUS_WINDOWS_BROWSER_COLLECTOR_PATH", value: "{{ tsj_bot_aw_rus_windows_browser_collector_path | default('C:\\ProgramData\\AWatch-rus\\browser-domains-native-collector.ps1') }}" }
- { key: "AW_RUS_WINDOWS_EMAIL_COLLECTOR_PATH", value: "{{ tsj_bot_aw_rus_windows_email_collector_path | default('C:\\ProgramData\\AWatch-rus\\email-outbound-collector.ps1') }}" }
- { key: "AI_CHAT_WORKDIR", value: "{{ tsj_bot_ai_chat_workdir | default('/home/igor') }}" }
- { key: "AI_CHAT_WORKDIR", value: "{{ tsj_bot_ai_chat_workdir | default('~') }}" }
- { key: "AI_EXEC_USER", value: "{{ tsj_bot_ai_exec_user | default('igor') }}" }
- { key: "INCIDENT_FAILURE_QUORUM_CHECKS", value: "{{ tsj_bot_incident_failure_quorum_checks | default(2) }}" }
- { key: "DETMIR_AI_STATE_FILE", value: "{{ tsj_bot_detmir_ai_state_file | default('/var/lib/detmir-ai/latest-state.json') }}" }
- { key: "TSJ_GUARDIAN_STATUS_BIN", value: "{{ tsj_bot_guardian_status_bin | default('/usr/local/bin/tsj-guardian-status') }}" }
- { key: "TMUX_USER", value: "{{ tsj_bot_tmux_user | default('igor') }}" }
- { key: "PFSENSE_ENV_PATH", value: "{{ tsj_bot_pfsense_env_path | default('/home/igor/.config/tsj-bot/pfsense.env.readonly') }}" }
- { key: "PFSENSE_INVENTORY_PATH", value: "{{ tsj_bot_pfsense_inventory_path | default('/home/igor/.config/tsj-bot/inventory.md') }}" }
- { key: "PFSENSE_ENV_PATH", value: "{{ tsj_bot_pfsense_env_path | default('~/.config/tsj-bot/pfsense.env.readonly') }}" }
- { key: "PFSENSE_INVENTORY_PATH", value: "{{ tsj_bot_pfsense_inventory_path | default('~/.config/tsj-bot/inventory.md') }}" }
notify: Restart tsj bot
- name: Установить systemd unit бота
+3 -3
View File
@@ -13,21 +13,21 @@ aw_server_public_host: "{{ (hostvars[aw_server_inventory_host].ansible_host | de
aw_worktime_report_base: "http://{{ aw_server_public_host }}:5610"
aw_worktime_timezone: "Europe/Moscow"
aw_worktime_influx_enabled: false
aw_worktime_influx_url: "http://10.10.10.10:8086"
aw_worktime_influx_url: "http://<INFLUXDB_HOST>:8086"
aw_worktime_influx_org: "proxmox"
aw_worktime_influx_bucket: "aw_metrics"
aw_worktime_influx_hosts: "SHARKON2025"
aw_worktime_influx_days: "today,yesterday"
aw_worktime_influx_token: ""
aw_dlp_influx_enabled: false
aw_dlp_influx_url: "http://10.10.10.10:8086"
aw_dlp_influx_url: "http://<INFLUXDB_HOST>:8086"
aw_dlp_influx_org: "proxmox"
aw_dlp_influx_bucket: "aw_metrics"
aw_dlp_influx_hosts: "SHARKON2025"
aw_dlp_influx_lookback_days: 30
aw_dlp_influx_event_limit: 2000
aw_dlp_influx_token: ""
aw_monitored_windows_host: "192.168.100.18"
aw_monitored_windows_host: "<WINDOWS_HOST>"
aw_monitored_windows_hostname: "SHARKON2025"
aw_rus_health_worktime_api_base: "http://127.0.0.1:5610"
aw_rus_health_state_dir: "{{ aw_server_data_dir }}/health"
@@ -1,14 +1,14 @@
aw_pfsense_poller_config:
poll_interval_seconds: 60
aw:
server_host: "10.10.10.13"
server_host: "<AW_SERVER_HOST>"
server_port: 5600
hostname: "PFSENSE-EDGE01"
pulse_time_seconds: 120
timeout_seconds: 15
pfsense:
name: "pfSense Edge 01"
host: "10.10.10.1"
host: "<FIREWALL_HOST>"
scheme: "https"
verify_tls: false
timeout_seconds: 15
+18 -18
View File
@@ -3,7 +3,7 @@ telegram_allowed_chat_ids: "123456789"
telegram_default_chat_id: 123456789
# Path on controller (this machine) to source bot script for deployment.
tsj_bot_source_local_path: "/mnt/usb_hdd2/Projects/ActivityWatch-Russian/proxmox/tsj_guardian_bot.py"
tsj_bot_source_local_path: "<PROJECT_ROOT>/proxmox/tsj_guardian_bot.py"
tsj_bot_runtime_root: "/opt/infra-admin"
# Optional bot tuning
@@ -14,11 +14,11 @@ tsj_bot_retry_autorecovery_every_sec: 300
tsj_bot_telegram_proxy_url: "http://127.0.0.1:11090"
tsj_bot_https_proxy_url: "http://127.0.0.1:11090"
tsj_bot_http_proxy_url: "http://127.0.0.1:11090"
tsj_bot_no_proxy: "localhost,127.0.0.1,10.10.10.0/24"
tsj_bot_node_13_host: "10.10.10.13"
tsj_bot_node_16_host: "10.10.10.16"
tsj_bot_node_13_url: "http://10.10.10.13:5600/api/0/info"
tsj_bot_node_16_url: "http://10.10.10.16/"
tsj_bot_no_proxy: "localhost,127.0.0.1,<SERVER_SUBNET_CIDR>"
tsj_bot_node_13_host: "<AW_SERVER_HOST>"
tsj_bot_node_16_host: "<AUX_NODE_HOST>"
tsj_bot_node_13_url: "http://<AW_SERVER_HOST>:5600/api/0/info"
tsj_bot_node_16_url: "http://<AUX_NODE_HOST>/"
tsj_bot_node_16_enabled: "false"
tsj_bot_fs_warn_pct: 85
tsj_bot_fs_crit_pct: 92
@@ -26,13 +26,13 @@ tsj_bot_fs_targets: "host,200,201,202,203"
tsj_bot_fs_exclude_types: "tmpfs,devtmpfs,proc,sysfs,cgroup,cgroup2,overlay,squashfs,nsfs,tracefs,debugfs,securityfs,configfs,fusectl,mqueue,hugetlbfs,ramfs"
tsj_bot_fs_immediate_ai_on_critical: "true"
tsj_bot_ai_escalation_mode: "codex_exec"
tsj_bot_ai_chat_workdir: "/home/igor"
tsj_bot_ai_chat_workdir: "<OPERATOR_HOME>"
tsj_bot_ai_exec_user: "igor"
tsj_bot_tmux_user: "igor"
tsj_bot_pfsense_change_control_enabled: "true"
tsj_bot_pfsense_change_confirm_ttl_sec: 900
tsj_bot_pfsense_env_path: "/home/igor/.config/tsj-bot/pfsense.env.readonly"
tsj_bot_pfsense_inventory_path: "/home/igor/.config/tsj-bot/inventory.md"
tsj_bot_pfsense_env_path: "<OPERATOR_HOME>/.config/tsj-bot/pfsense.env.readonly"
tsj_bot_pfsense_inventory_path: "<OPERATOR_HOME>/.config/tsj-bot/inventory.md"
tsj_bot_openvpn_config_enabled: "true"
tsj_bot_openvpn_config_confirm_ttl_sec: 900
tsj_bot_openvpn_expiry_warn_enabled: "false"
@@ -45,15 +45,15 @@ tsj_bot_update_targets: "auto"
tsj_bot_pfsense_mcp_bearer: "CHANGE_ME"
# AW-Rus + DLP check defaults
tsj_bot_aw_rus_api_base: "http://10.10.10.13:5600/api/0"
tsj_bot_aw_rus_worktime_base: "http://10.10.10.13:5610"
tsj_bot_aw_dlp_policy_api_base: "http://10.10.10.13:5601/api/0"
tsj_bot_aw_rus_api_base: "http://<AW_SERVER_HOST>:5600/api/0"
tsj_bot_aw_rus_worktime_base: "http://<AW_SERVER_HOST>:5610"
tsj_bot_aw_dlp_policy_api_base: "http://<AW_SERVER_HOST>:5601/api/0"
tsj_bot_aw_dlp_policy_actor: "tsj-guardian-bot"
tsj_bot_aw_rus_worktime_heal_cmd: "sshpass -p 'CHANGE_ME' ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no igor@10.10.10.13 'sudo -S /usr/local/bin/aw-worktime-autoheal-rust && sudo -S systemctl reset-failed aw-worktime-ui-bridge.service && sudo -S systemctl start aw-worktime-ui-bridge.service'"
tsj_bot_aw_rus_dlp_heal_cmd: "sshpass -p 'CHANGE_ME' ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no igor@10.10.10.13 'sudo -S systemctl restart activitywatch-server.service && sudo -S systemctl start activitywatch-dlp-aggregator.service || true && sudo -S /usr/local/bin/aw-health-check && sudo -S /usr/local/bin/dlp-health-check'"
tsj_bot_aw_rus_case_api_base: "http://10.10.10.13:5602"
tsj_bot_aw_rus_worktime_heal_cmd: "sshpass -p 'CHANGE_ME' ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no igor@<AW_SERVER_HOST> 'sudo -S /usr/local/bin/aw-worktime-autoheal-rust && sudo -S systemctl reset-failed aw-worktime-ui-bridge.service && sudo -S systemctl start aw-worktime-ui-bridge.service'"
tsj_bot_aw_rus_dlp_heal_cmd: "sshpass -p 'CHANGE_ME' ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no igor@<AW_SERVER_HOST> 'sudo -S systemctl restart activitywatch-server.service && sudo -S systemctl start activitywatch-dlp-aggregator.service || true && sudo -S /usr/local/bin/aw-health-check && sudo -S /usr/local/bin/dlp-health-check'"
tsj_bot_aw_rus_case_api_base: "http://<AW_SERVER_HOST>:5602"
tsj_bot_aw_rus_hayabusa_enabled: "true"
tsj_bot_aw_rus_hayabusa_ssh_cmd: "sshpass -p 'CHANGE_ME' ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no igor@10.10.10.13"
tsj_bot_aw_rus_hayabusa_ssh_cmd: "sshpass -p 'CHANGE_ME' ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no igor@<AW_SERVER_HOST>"
tsj_bot_aw_rus_host: "SHARKON2025"
tsj_bot_aw_rus_primary_user: "USER1"
tsj_bot_aw_rus_stale_sec: 900
@@ -61,8 +61,8 @@ tsj_bot_aw_rus_slo_enabled: "true"
tsj_bot_aw_rus_slo_alert_window: "24h"
tsj_bot_aw_rus_slo_min_samples: 4
tsj_bot_aw_rus_slo_max_age_sec: 90
tsj_bot_aw_rus_slo_summary_cmd: "sshpass -p 'CHANGE_ME' ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no igor@10.10.10.13 'cat /var/lib/activitywatch/slo/aw-slo-summary.json'"
tsj_bot_aw_rus_windows_host: "192.168.100.18"
tsj_bot_aw_rus_slo_summary_cmd: "sshpass -p 'CHANGE_ME' ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no igor@<AW_SERVER_HOST> 'cat /var/lib/activitywatch/slo/aw-slo-summary.json'"
tsj_bot_aw_rus_windows_host: "<WINDOWS_HOST>"
tsj_bot_aw_rus_windows_ssh_user: "Администратор"
tsj_bot_aw_rus_windows_ssh_password: "CHANGE_ME"
tsj_bot_aw_rus_windows_config_path: "C:\\ProgramData\\AWatch-rus\\deployment-config.json"
+1 -1
View File
@@ -6,7 +6,7 @@ aw-ct ansible_host=10.20.30.13 ansible_user=root ansible_port=22
[aw_windows]
# Примечание: в русифицированных Windows часто нужен "Администратор", а не "Administrator".
win-node1 ansible_host=192.168.100.18 ansible_user=Администратор ansible_password=CHANGE_ME ansible_connection=winrm ansible_winrm_transport=ntlm ansible_port=5985 ansible_winrm_server_cert_validation=ignore
win-node1 ansible_host=<WINDOWS_HOST> ansible_user=Администратор ansible_password=CHANGE_ME ansible_connection=winrm ansible_winrm_transport=ntlm ansible_port=5985 ansible_winrm_server_cert_validation=ignore
[aw_pfsense_pollers]
# pfsense-poller1 ansible_host=192.168.100.30 ansible_user=root ansible_port=22
-11
View File
@@ -1,11 +0,0 @@
[proxmox]
pve-detmir ansible_host=10.10.10.2 ansible_user=igor ansible_password=04091968 ansible_connection=ssh ansible_become=true ansible_become_method=sudo ansible_become_password=04091968 ansible_port=22
[aw_server]
aw-prod ansible_host=10.10.10.13 ansible_user=igor ansible_password=04091968 ansible_connection=ssh ansible_become=true ansible_become_method=sudo ansible_become_password=04091968
[grafana]
grafana-main grafana_url=http://10.10.10.11:3000 grafana_validate_tls=false grafana_folder_title=DLP grafana_detmir_folder_uid=efk080s0lfc3ka grafana_pfsense_folder_uid=bfcx6gg70sagwc
[aw_windows]
rdp-prod ansible_host=192.168.100.18 ansible_user=Администратор ansible_password=Sergei2009@ ansible_connection=winrm ansible_winrm_transport=ntlm ansible_port=5985 ansible_winrm_server_cert_validation=ignore
@@ -6,7 +6,7 @@ map $http_upgrade $connection_upgrade {
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name {{ proxmox_web_gateway_public_hostname }} 10.10.10.2 192.168.63.213 _;
server_name {{ proxmox_web_gateway_public_hostname }} 10.10.10.2 <WAN_OR_EXTERNAL_IP> _;
access_log /var/log/nginx/proxmox-web-gateway.access.log;
error_log /var/log/nginx/proxmox-web-gateway.error.log;
@@ -17,7 +17,7 @@ server {
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name {{ proxmox_web_gateway_public_hostname }} 10.10.10.2 192.168.63.213 _;
server_name {{ proxmox_web_gateway_public_hostname }} 10.10.10.2 <WAN_OR_EXTERNAL_IP> _;
access_log /var/log/nginx/proxmox-web-gateway.access.log;
error_log /var/log/nginx/proxmox-web-gateway.error.log;
+1 -1
View File
@@ -45,7 +45,7 @@ AW_EXPECT_START_OF_DAY=00:00
AW_EXPECT_ALWAYS_ACTIVE_PATTERN=aw-watcher-window
AW_EXPECT_LANDINGPAGE=/#/activity/SHARKON2025/view/
AW_HEALTH_STRICT_FILEOPS=0
AW_MONITORED_WINDOWS_HOST=192.168.100.18
AW_MONITORED_WINDOWS_HOST=<WINDOWS_HOST>
AW_MONITORED_WINDOWS_HOSTNAME=SHARKON2025
AW_RUS_HEALTH_WORKTIME_API=http://127.0.0.1:5610
AW_RUS_HEALTH_STATE_DIR=/var/lib/activitywatch/health
-92129
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -7,4 +7,4 @@ export UV_PROJECT_ENVIRONMENT="${UV_PROJECT_ENVIRONMENT:-$HOME/.local/share/uv-e
mkdir -p "$UV_PROJECT_ENVIRONMENT"
cd "$SCRIPT_DIR"
exec /home/igor/.local/bin/uv run main.py
exec ~/.local/bin/uv run main.py
+18 -18
View File
@@ -12,10 +12,10 @@
```text
File 1C / Windows RDP host
-> read-only export / telemetry
-> ClickHouse on 10.10.10.2
-> ClickHouse on <GATEWAY_HOST>
-> detections / cases / timeline / company intelligence
-> manager briefs / recovery briefs / weekly digest
-> Grafana on 10.10.10.11
-> Grafana on <GRAFANA_HOST>
-> browser pages and read-only API
```
@@ -33,14 +33,14 @@ File 1C / Windows RDP host
### Источник
- `192.168.100.18`
- `<WINDOWS_HOST>`
- файловая 1С;
- scheduled task `\ActivityWatch File1C Upload`;
- read-only export без записи в `1Cv8.1CD`.
### Analytics node
- `10.10.10.2`
- `<GATEWAY_HOST>`
- `ClickHouse`;
- ETL/ingest;
- company intelligence refresh;
@@ -51,7 +51,7 @@ File 1C / Windows RDP host
### Visualization
- `10.10.10.11`
- `<GRAFANA_HOST>`
- `Grafana`;
- folder `file-1c`;
- dashboards для audit, detections, timeline, company intelligence.
@@ -95,7 +95,7 @@ File 1C / Windows RDP host
### Browser pages для руководителя
На `10.10.10.2:8710` уже работают human-facing страницы:
На `<GATEWAY_HOST>:8710` уже работают human-facing страницы:
- `/manager/brief`
- `/manager/actions`
@@ -143,7 +143,7 @@ File 1C / Windows RDP host
1. ingest грузит read-only данные;
2. `ClickHouse` строит canonical marts и signals;
3. forecasting layer считает `7/30 day` expectations;
4. local `codex` на `10.10.10.2` превращает это в:
4. local `codex` на `<GATEWAY_HOST>` превращает это в:
- manager brief;
- recovery brief;
- weekly digest;
@@ -174,7 +174,7 @@ File 1C / Windows RDP host
## Что именно уже автоматизировано
На `10.10.10.2` автоматизированы:
На `<GATEWAY_HOST>` автоматизированы:
- ingest cycle;
- post-ingest refresh manager brief;
@@ -217,23 +217,23 @@ File 1C / Windows RDP host
### Grafana
- `http://10.10.10.11:3000/dashboards/f/file-1c/?orgId=1`
- `http://<GRAFANA_HOST>:3000/dashboards/f/file-1c/?orgId=1`
- management board:
- `http://10.10.10.11:3000/d/1c-file-mgmt/1c-file-management-board`
- `http://<GRAFANA_HOST>:3000/d/1c-file-mgmt/1c-file-management-board`
- financial reporting:
- `http://10.10.10.11:3000/d/1c-file-finance/1c-file-financial-reporting`
- `http://<GRAFANA_HOST>:3000/d/1c-file-finance/1c-file-financial-reporting`
- telemetry board:
- `http://10.10.10.11:3000/d/1c-file-telemetry/1c-file-telemetry-board`
- `http://<GRAFANA_HOST>:3000/d/1c-file-telemetry/1c-file-telemetry-board`
- company intelligence:
- `http://10.10.10.11:3000/d/1c-file-companies/1c-file-company-intelligence`
- `http://<GRAFANA_HOST>:3000/d/1c-file-companies/1c-file-company-intelligence`
### Manager UI
- `http://10.10.10.2:8710/manager/brief`
- `http://10.10.10.2:8710/manager/changes`
- `http://10.10.10.2:8710/manager/trends/weekly`
- `http://10.10.10.2:8710/manager/digest/weekly`
- `http://10.10.10.2:8710/manager/recovery`
- `http://<GATEWAY_HOST>:8710/manager/brief`
- `http://<GATEWAY_HOST>:8710/manager/changes`
- `http://<GATEWAY_HOST>:8710/manager/trends/weekly`
- `http://<GATEWAY_HOST>:8710/manager/digest/weekly`
- `http://<GATEWAY_HOST>:8710/manager/recovery`
### API
+1 -1
View File
@@ -134,7 +134,7 @@ Endpoints:
Что делает:
- собирает live context по портфелю компаний из `ClickHouse`;
- вызывает локальный `codex exec` на `10.10.10.2` от пользователя `codex`;
- вызывает локальный `codex exec` на `<GATEWAY_HOST>` от пользователя `codex`;
- требует structured JSON по schema, а не свободный текст;
- рендерит итог в `latest.json` и `latest.md`;
- при сбое `codex` даёт deterministic fallback, чтобы контур не оставался пустым.
+32 -32
View File
@@ -31,27 +31,27 @@
### 2.1 Узлы
- `192.168.100.18`
- `<WINDOWS_HOST>`
- Windows / RDP host с файловой 1С
- источник `read-only` telemetry/export
- `10.10.10.2`
- `<GATEWAY_HOST>`
- backend узел file-1C analytics
- `ClickHouse`
- ETL/ingest
- detections
- cases
- proof-check
- `10.10.10.11`
- `<GRAFANA_HOST>`
- production `Grafana`
- готовые dashboards
- `10.10.10.13`
- `<AW_SERVER_HOST>`
- основной `AW-rus` сервер
- в file-1C pipeline не является обязательным runtime-компонентом
### 2.2 Поток данных
```text
Windows file 1C host (192.168.100.18)
Windows file 1C host (<WINDOWS_HOST>)
├─ ibases.v8i inventory
├─ 1Cv8.1CD file metadata
├─ 1Cv8Log metadata
@@ -60,7 +60,7 @@ Windows file 1C host (192.168.100.18)
export-upload-file-1c-telemetry.ps1
↓ scp
10.10.10.2 /opt/activitywatch/clickhouse-1c/landing/*
<GATEWAY_HOST> /opt/activitywatch/clickhouse-1c/landing/*
run_ingest_cycle.sh
├─ raw tables
@@ -69,7 +69,7 @@ run_ingest_cycle.sh
├─ detections
└─ cases
Grafana 10.10.10.11
Grafana <GRAFANA_HOST>
```
## 3. Что считается готовым контуром
@@ -77,8 +77,8 @@ Grafana 10.10.10.11
Контур считается рабочим, если одновременно выполняется всё:
1. Windows scheduled task `ActivityWatch File1C Upload` запускается по расписанию.
2. На `10.10.10.2` работает `aw-1c-ingest.timer`.
3. На `10.10.10.2` работает `aw-1c-proofcheck.timer`.
2. На `<GATEWAY_HOST>` работает `aw-1c-ingest.timer`.
3. На `<GATEWAY_HOST>` работает `aw-1c-proofcheck.timer`.
4. `ClickHouse` содержит живые строки в:
- `documents`
- `reglog_events`
@@ -87,18 +87,18 @@ Grafana 10.10.10.11
- `entity_timeline`
- `detections`
- `cases`
5. В `Grafana` на `10.10.10.11` dashboards открываются и смотрят в datasource `clickhouse-1c`.
5. В `Grafana` на `<GRAFANA_HOST>` dashboards открываются и смотрят в datasource `clickhouse-1c`.
## 4. Каталоги и артефакты
### 4.1 На Windows `192.168.100.18`
### 4.1 На Windows `<WINDOWS_HOST>`
- `C:\ProgramData\AWatch-rus\deployment-config.json`
- `C:\ProgramData\AWatch-rus\export-upload-file-1c-telemetry.ps1`
- `C:\ProgramData\AWatch-rus\logs\file1c-telemetry.log`
- `C:\ProgramData\AWatch-rus\ssh\awops_ed25519`
### 4.2 На backend `10.10.10.2`
### 4.2 На backend `<GATEWAY_HOST>`
- root:
- `/opt/activitywatch/clickhouse-1c`
@@ -114,7 +114,7 @@ Grafana 10.10.10.11
- `/opt/activitywatch/clickhouse-1c/etl/config.yml`
- `/opt/activitywatch/clickhouse-1c/.venv`
### 4.3 systemd units на `10.10.10.2`
### 4.3 systemd units на `<GATEWAY_HOST>`
- `aw-1c-ingest.service`
- `aw-1c-ingest.timer`
@@ -123,17 +123,17 @@ Grafana 10.10.10.11
## 5. Развёртывание с нуля
### 5.1 Backend на `10.10.10.2`
### 5.1 Backend на `<GATEWAY_HOST>`
Playbook:
- [ansible/deploy_file_1c_analytics.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_file_1c_analytics.yml)
- [ansible/deploy_file_1c_analytics.yml](<PROJECT_ROOT>/ansible/deploy_file_1c_analytics.yml)
Команда:
```bash
ansible-playbook -i /mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/inventory.ini \
/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_file_1c_analytics.yml
ansible-playbook -i <PROJECT_ROOT>/ansible/inventory.ini \
<PROJECT_ROOT>/ansible/deploy_file_1c_analytics.yml
```
Что делает:
@@ -145,17 +145,17 @@ ansible-playbook -i /mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/invento
- включает `aw-1c-ingest.timer`;
- включает `aw-1c-proofcheck.timer`.
### 5.2 Windows uploader на `192.168.100.18`
### 5.2 Windows uploader на `<WINDOWS_HOST>`
Playbook:
- [ansible/deploy_file_1c_windows_telemetry.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_file_1c_windows_telemetry.yml)
- [ansible/deploy_file_1c_windows_telemetry.yml](<PROJECT_ROOT>/ansible/deploy_file_1c_windows_telemetry.yml)
Команда:
```bash
ansible-playbook -i /mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/inventory.ini \
/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_file_1c_windows_telemetry.yml
ansible-playbook -i <PROJECT_ROOT>/ansible/inventory.ini \
<PROJECT_ROOT>/ansible/deploy_file_1c_windows_telemetry.yml
```
Что делает:
@@ -164,7 +164,7 @@ ansible-playbook -i /mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/invento
- обновляет `deployment-config.json`;
- создаёт/обновляет scheduled task `ActivityWatch File1C Upload`.
### 5.3 Production Grafana на `10.10.10.11`
### 5.3 Production Grafana на `<GRAFANA_HOST>`
Grafana уже должна содержать:
@@ -180,7 +180,7 @@ Grafana уже должна содержать:
См.:
- [docs/1C_GRAFANA_DEPLOYMENT_RU.md](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/docs/1C_GRAFANA_DEPLOYMENT_RU.md)
- [docs/1C_GRAFANA_DEPLOYMENT_RU.md](<PROJECT_ROOT>/docs/1C_GRAFANA_DEPLOYMENT_RU.md)
## 6. Обязательный post-step на Windows
@@ -196,7 +196,7 @@ Grafana уже должна содержать:
### 6.2 Команда переключения principal
На `192.168.100.18`:
На `<WINDOWS_HOST>`:
```cmd
schtasks /Change /TN "\ActivityWatch File1C Upload" /RU "SHARKON2025\Администратор" /RP "<LOCAL_ADMIN_PASSWORD>"
@@ -417,11 +417,11 @@ AW_1C_ROOT=/opt/activitywatch/clickhouse-1c /opt/activitywatch/clickhouse-1c/ops
## 14. Связанные файлы
- [clickhouse-1c/README.md](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/README.md)
- [clickhouse-1c/etl/load_1c_exports.py](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/etl/load_1c_exports.py)
- [clickhouse-1c/ops/run_ingest_cycle.sh](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/ops/run_ingest_cycle.sh)
- [clickhouse-1c/ops/check_ingest_freshness.sh](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/ops/check_ingest_freshness.sh)
- [ansible/deploy_file_1c_analytics.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_file_1c_analytics.yml)
- [ansible/deploy_file_1c_windows_telemetry.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_file_1c_windows_telemetry.yml)
- [windows/export-upload-file-1c-telemetry.ps1](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/windows/export-upload-file-1c-telemetry.ps1)
- [docs/wiki/File-1C-Analytics.md](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/docs/wiki/File-1C-Analytics.md)
- [clickhouse-1c/README.md](<PROJECT_ROOT>/clickhouse-1c/README.md)
- [clickhouse-1c/etl/load_1c_exports.py](<PROJECT_ROOT>/clickhouse-1c/etl/load_1c_exports.py)
- [clickhouse-1c/ops/run_ingest_cycle.sh](<PROJECT_ROOT>/clickhouse-1c/ops/run_ingest_cycle.sh)
- [clickhouse-1c/ops/check_ingest_freshness.sh](<PROJECT_ROOT>/clickhouse-1c/ops/check_ingest_freshness.sh)
- [ansible/deploy_file_1c_analytics.yml](<PROJECT_ROOT>/ansible/deploy_file_1c_analytics.yml)
- [ansible/deploy_file_1c_windows_telemetry.yml](<PROJECT_ROOT>/ansible/deploy_file_1c_windows_telemetry.yml)
- [windows/export-upload-file-1c-telemetry.ps1](<PROJECT_ROOT>/windows/export-upload-file-1c-telemetry.ps1)
- [docs/wiki/File-1C-Analytics.md](<PROJECT_ROOT>/docs/wiki/File-1C-Analytics.md)
+11 -11
View File
@@ -19,14 +19,14 @@
Рабочий каталог:
- `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c`
- `<PROJECT_ROOT>/grafana-1c`
Подготовка env:
```bash
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c
cp /mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/.env.example \
/mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/.env
cd <PROJECT_ROOT>/grafana-1c
cp <PROJECT_ROOT>/grafana-1c/.env.example \
<PROJECT_ROOT>/grafana-1c/.env
```
Обязательно изменить:
@@ -38,29 +38,29 @@ cp /mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/.env.example \
Используйте шаблон под вашу СУБД:
- PostgreSQL: `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/sql/postgres_views_template.sql`
- MS SQL: `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/sql/mssql_views_template.sql`
- PostgreSQL: `<PROJECT_ROOT>/grafana-1c/sql/postgres_views_template.sql`
- MS SQL: `<PROJECT_ROOT>/grafana-1c/sql/mssql_views_template.sql`
После адаптации шаблона под фактические таблицы 1С создайте views в БД.
Быстрое профилирование схемы 1С (PostgreSQL):
```bash
sh /mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/tools/discover_postgres_1c.sh \
sh <PROJECT_ROOT>/grafana-1c/tools/discover_postgres_1c.sh \
"postgres://user:pass@db-host:5432/db?sslmode=disable"
```
Проверка KPI views перед запуском:
```bash
sh /mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/tools/validate_kpi_views.sh \
sh <PROJECT_ROOT>/grafana-1c/tools/validate_kpi_views.sh \
"postgres://user:pass@db-host:5432/db?sslmode=disable"
```
## 4. Запуск стека
```bash
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c
cd <PROJECT_ROOT>/grafana-1c
docker compose up -d
```
@@ -87,7 +87,7 @@ curl -fsS http://127.0.0.1:9090/-/healthy
E2E health-check:
```bash
sh /mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/tools/check_pipeline.sh
sh <PROJECT_ROOT>/grafana-1c/tools/check_pipeline.sh
```
## 6. KPI и алерты
@@ -109,7 +109,7 @@ sh /mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/tools/check_pipeline.
Файл правил:
- `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/grafana-1c/prometheus/alerts.yml`
- `<PROJECT_ROOT>/grafana-1c/prometheus/alerts.yml`
## 7. Эксплуатационный минимум
@@ -5,14 +5,14 @@
## Источники
- `tmux` session `codex`, scrollback выгружен в `/tmp/codex-tmux-last24.txt`
- текущий worktree `git status` в `/mnt/usb_hdd2/Projects/ActivityWatch-Russian`
- текущий worktree `git status` в `<PROJECT_ROOT>`
- live-проверки на:
- `10.10.10.2` Proxmox
- `10.10.10.11` Grafana
- `10.10.10.12` Loki/Alloy
- `10.10.10.13` aw-server
- `10.10.10.1` pfSense
- `192.168.100.18` Windows RDP host
- `<GATEWAY_HOST>` Proxmox
- `<GRAFANA_HOST>` Grafana
- `<AUX_SERVICE_HOST>` Loki/Alloy
- `<AW_SERVER_HOST>` aw-server
- `<FIREWALL_HOST>` pfSense
- `<WINDOWS_HOST>` Windows RDP host
## Важная оговорка
@@ -25,12 +25,12 @@
### 1. Восстановление ActivityWatch-Russian
Симптом:
- на `10.10.10.13:5600` UI не обновлялся для `SHARKON2025`;
- на `<AW_SERVER_HOST>:5600` UI не обновлялся для `SHARKON2025`;
- `aw-server` был жив, но stale были `aw-watcher-afk`, `aw-watcher-window`, `aw-worktime-sessions`.
Действия:
- проверен `aw-server` и свежесть bucket’ов;
- через WinRM на `192.168.100.18` проверены процессы, tasks и recovery-скрипты;
- через WinRM на `<WINDOWS_HOST>` проверены процессы, tasks и recovery-скрипты;
- запущены:
- `ActivityWatch Recovery`
- `ActivityWatch Launch [SHARKON2025_user5]`
@@ -56,10 +56,10 @@
- тесты обновлены и прогнаны.
Затронутые файлы:
- [proxmox/tsj_guardian_bot.py](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/proxmox/tsj_guardian_bot.py)
- [proxmox/test_tsj_guardian_bot.py](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/proxmox/test_tsj_guardian_bot.py)
- [ansible/deploy_tsj_guardian_bot_proxmox.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_tsj_guardian_bot_proxmox.yml)
- [ansible/group_vars/proxmox-bot.example.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/group_vars/proxmox-bot.example.yml)
- [proxmox/tsj_guardian_bot.py](<PROJECT_ROOT>/proxmox/tsj_guardian_bot.py)
- [proxmox/test_tsj_guardian_bot.py](<PROJECT_ROOT>/proxmox/test_tsj_guardian_bot.py)
- [ansible/deploy_tsj_guardian_bot_proxmox.yml](<PROJECT_ROOT>/ansible/deploy_tsj_guardian_bot_proxmox.yml)
- [ansible/group_vars/proxmox-bot.example.yml](<PROJECT_ROOT>/ansible/group_vars/proxmox-bot.example.yml)
Проверка:
- `python3 -m py_compile proxmox/tsj_guardian_bot.py proxmox/test_tsj_guardian_bot.py`
@@ -76,36 +76,36 @@
- переключены:
- `AI_EXEC_USER=igor`
- `TMUX_USER=igor`
- `AI_CHAT_WORKDIR=/home/igor`
- `AI_CHAT_WORKDIR=<OPERATOR_HOME>`
- добавлены настраиваемые:
- `PFSENSE_ENV_PATH`
- `PFSENSE_INVENTORY_PATH`
- создан `igor`-readable bundle:
- `/home/igor/.config/tsj-bot/pfsense.env.readonly`
- `/home/igor/.config/tsj-bot/inventory.md`
- `<OPERATOR_HOME>/.config/tsj-bot/pfsense.env.readonly`
- `<OPERATOR_HOME>/.config/tsj-bot/inventory.md`
Итог:
- диалоговая техподдержка и AI-эскалация в боте работают от `igor`;
- bot-side pfSense/inventory контекст больше не зависит от старого `codex`-домика.
### 4. Исправлен сетевой доступ `10.10.10.2 -> 192.168.100.18`
### 4. Исправлен сетевой доступ `<GATEWAY_HOST> -> <WINDOWS_HOST>`
Root cause:
- на `pfSense 10.10.10.1`, интерфейс `opt1/MGMT`:
- allow rule для `10.10.10.2 -> 192.168.100.18:22` был ниже `block all`;
- allow rule для `10.10.10.2 -> 10.10.10.1:2022` был ниже `block all`;
- rule для `10.10.10.2 -> 192.168.100.18:5985` отсутствовал.
- на `pfSense <FIREWALL_HOST>`, интерфейс `opt1/MGMT`:
- allow rule для `<GATEWAY_HOST> -> <WINDOWS_HOST>:22` был ниже `block all`;
- allow rule для `<GATEWAY_HOST> -> <FIREWALL_HOST>:2022` был ниже `block all`;
- rule для `<GATEWAY_HOST> -> <WINDOWS_HOST>:5985` отсутствовал.
Сделано:
- подняты нужные allow rules выше `block all`;
- добавлено недостающее правило на `5985`.
Итог:
- с `10.10.10.2` подтвержден доступ на:
- `10.10.10.1:2022`
- `192.168.100.18:22`
- `192.168.100.18:5985`
- SSH вход на `192.168.100.18` под `Администратор` был подтвержден.
- с `<GATEWAY_HOST>` подтвержден доступ на:
- `<FIREWALL_HOST>:2022`
- `<WINDOWS_HOST>:22`
- `<WINDOWS_HOST>:5985`
- SSH вход на `<WINDOWS_HOST>` под `Администратор` был подтвержден.
### 5. Убрано ложное сообщение “автолечение невозможно”
@@ -135,8 +135,8 @@ Root cause:
Проблема была не в Grafana, а в цепочке `pfSense -> Alloy -> Loki`.
Сделано:
- на `10.10.10.1` поднят `syslogd`;
- на `10.10.10.12` в Alloy для pfSense syslog включен правильный формат `rfc3164`;
- на `<FIREWALL_HOST>` поднят `syslogd`;
- на `<AUX_SERVICE_HOST>` в Alloy для pfSense syslog включен правильный формат `rfc3164`;
- отключен stale docker self-scrape path, забивавший `loki.write` старыми batch’ами;
- перезапущен `alloy`.
@@ -149,19 +149,19 @@ Root cause:
Проблема:
- не обновлялись данные в `1C File - Operations Health`.
Сделано на `192.168.100.18`:
Сделано на `<WINDOWS_HOST>`:
- exporter больше не падает на недоступных `ibases.v8i`;
- `export-upload-file-1c-telemetry.ps1` научен брать `remoteKeyPath` из `deployment-config.json`;
- рабочий ключ закреплен как `C:\Users\USER1\.ssh\awops_ed25519`;
- исправлены права к `file1c-telemetry-state.json`.
Сделано на `10.10.10.2`:
Сделано на `<GATEWAY_HOST>`:
- прогнан ingest;
- `proofcheck` выведен в green.
Затронутые файлы:
- [windows/export-upload-file-1c-telemetry.ps1](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/windows/export-upload-file-1c-telemetry.ps1)
- [ansible/deploy_file_1c_windows_telemetry.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_file_1c_windows_telemetry.yml)
- [windows/export-upload-file-1c-telemetry.ps1](<PROJECT_ROOT>/windows/export-upload-file-1c-telemetry.ps1)
- [ansible/deploy_file_1c_windows_telemetry.yml](<PROJECT_ROOT>/ansible/deploy_file_1c_windows_telemetry.yml)
Итог:
- `1C File - Operations Health` снова обновляется;
@@ -198,9 +198,9 @@ Live-итог:
Сделано:
- добавлен SQL слой:
- [clickhouse-1c/clickhouse/init/05_financial_reporting.sql](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/clickhouse/init/05_financial_reporting.sql)
- [clickhouse-1c/clickhouse/init/05_financial_reporting.sql](<PROJECT_ROOT>/clickhouse-1c/clickhouse/init/05_financial_reporting.sql)
- добавлен dashboard:
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-financial-reporting.json](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/grafana/provisioning/dashboards/files/1c-financial-reporting.json)
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-financial-reporting.json](<PROJECT_ROOT>/clickhouse-1c/grafana/provisioning/dashboards/files/1c-financial-reporting.json)
- обновлен gateway route:
- `go/file1c-finance`
@@ -211,7 +211,7 @@ Live-итог:
### 12. Проведено расследование production-source для `postings`
Что подтверждено на `192.168.100.18`:
Что подтверждено на `<WINDOWS_HOST>`:
- готового `toolkit`/REST/service под postings нет;
- порт `6003` и типовые service-порты не слушаются;
- текущий Windows upload path шлет только telemetry/snapshot, без `postings`.
@@ -221,9 +221,9 @@ Live-итог:
- COMConnector в user-token path;
- интерактивные scheduled tasks под `USER1`;
- явные 1С-креды:
- `Администратор / Sergei2009@`
- `user / Sergei2009@`
- `user1 / Sergei2009@`
- `Администратор / <WINDOWS_PASSWORD>`
- `user / <WINDOWS_PASSWORD>`
- `user1 / <WINDOWS_PASSWORD>`
Итог:
- blocker остался прежним: нужен реальный пользователь 1С с read-only доступом;
@@ -233,7 +233,7 @@ Live-итог:
Сделано:
- добавлен новый dashboard:
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-telemetry-board.json](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/grafana/provisioning/dashboards/files/1c-telemetry-board.json)
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-telemetry-board.json](<PROJECT_ROOT>/clickhouse-1c/grafana/provisioning/dashboards/files/1c-telemetry-board.json)
- добавлена ссылка на него из `1C File - Management Board`;
- добавлен gateway route:
- `go/file1c-telemetry`
@@ -241,12 +241,12 @@ Live-итог:
Live-итог:
- в Grafana зарегистрирован `uid=1c-file-telemetry`;
- все 1C dashboards лежат в folder `1C File Analytics`;
- `https://10.10.10.2/go/file1c-telemetry` редиректит на новый board.
- `https://<GATEWAY_HOST>/go/file1c-telemetry` редиректит на новый board.
### 14. Live-путь `1C File Analytics` в Grafana был приведен к устойчивому состоянию
Выяснилось:
- file-based provisioning на `10.10.10.11` не был основной точкой для 1C dashboards;
- file-based provisioning на `<GRAFANA_HOST>` не был основной точкой для 1C dashboards;
- текущие `file-1c` dashboards жили в DB Grafana.
Сделано:
@@ -264,19 +264,19 @@ Live-итог:
## Файлы, которые точно редактировались в этом окне по данным tmux
- [proxmox/tsj_guardian_bot.py](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/proxmox/tsj_guardian_bot.py)
- [proxmox/test_tsj_guardian_bot.py](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/proxmox/test_tsj_guardian_bot.py)
- [ansible/deploy_tsj_guardian_bot_proxmox.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_tsj_guardian_bot_proxmox.yml)
- [ansible/group_vars/proxmox-bot.example.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/group_vars/proxmox-bot.example.yml)
- [windows/export-upload-file-1c-telemetry.ps1](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/windows/export-upload-file-1c-telemetry.ps1)
- [ansible/deploy_file_1c_windows_telemetry.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_file_1c_windows_telemetry.yml)
- [clickhouse-1c/clickhouse/init/05_financial_reporting.sql](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/clickhouse/init/05_financial_reporting.sql)
- [ansible/deploy_proxmox_web_gateway.yml](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_proxmox_web_gateway.yml)
- [proxmox/tsj_guardian_bot.py](<PROJECT_ROOT>/proxmox/tsj_guardian_bot.py)
- [proxmox/test_tsj_guardian_bot.py](<PROJECT_ROOT>/proxmox/test_tsj_guardian_bot.py)
- [ansible/deploy_tsj_guardian_bot_proxmox.yml](<PROJECT_ROOT>/ansible/deploy_tsj_guardian_bot_proxmox.yml)
- [ansible/group_vars/proxmox-bot.example.yml](<PROJECT_ROOT>/ansible/group_vars/proxmox-bot.example.yml)
- [windows/export-upload-file-1c-telemetry.ps1](<PROJECT_ROOT>/windows/export-upload-file-1c-telemetry.ps1)
- [ansible/deploy_file_1c_windows_telemetry.yml](<PROJECT_ROOT>/ansible/deploy_file_1c_windows_telemetry.yml)
- [clickhouse-1c/clickhouse/init/05_financial_reporting.sql](<PROJECT_ROOT>/clickhouse-1c/clickhouse/init/05_financial_reporting.sql)
- [ansible/deploy_proxmox_web_gateway.yml](<PROJECT_ROOT>/ansible/deploy_proxmox_web_gateway.yml)
Новые dashboard JSON, подтвержденные live-выкладкой:
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-financial-reporting.json](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/grafana/provisioning/dashboards/files/1c-financial-reporting.json)
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-management-board.json](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/grafana/provisioning/dashboards/files/1c-management-board.json)
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-telemetry-board.json](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/clickhouse-1c/grafana/provisioning/dashboards/files/1c-telemetry-board.json)
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-financial-reporting.json](<PROJECT_ROOT>/clickhouse-1c/grafana/provisioning/dashboards/files/1c-financial-reporting.json)
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-management-board.json](<PROJECT_ROOT>/clickhouse-1c/grafana/provisioning/dashboards/files/1c-management-board.json)
- [clickhouse-1c/grafana/provisioning/dashboards/files/1c-telemetry-board.json](<PROJECT_ROOT>/clickhouse-1c/grafana/provisioning/dashboards/files/1c-telemetry-board.json)
## Проверки, которые были явно пройдены
+19 -19
View File
@@ -11,7 +11,7 @@ Read-only MVP выполнен и развернут:
- Rust crate: `adk-rust/crates/detmir-portal`;
- production service: `detmir-portal.service` на Proxmox;
- bind: `127.0.0.1:8720`;
- gateway route: `https://dm.iri1968.dpdns.org/portal/`;
- gateway route: `https://<PUBLIC_GATEWAY_FQDN>/portal/`;
- API: `/api/health`, `/api/summary`, `/api/operator`, `/api/manager`,
`/api/owner`, `/api/incidents`, `/api/links`;
- UI tabs: `Оператор`, `Руководитель`, `Владелец`, `Инциденты ИБ`;
@@ -51,11 +51,11 @@ baseline и раздела `Phase 8: Post-MVP Enhancements`.
- `detmir-status --json` на Proxmox;
- `detmir-check --json` на Proxmox, включая `grafana-data`;
- `detmir-grafana-check` в Grafana CT 201;
- AW Worktime API на `10.10.10.13:5610`;
- ActivityWatch API на `10.10.10.13:5600`;
- AW Worktime API на `<AW_SERVER_HOST>:5610`;
- ActivityWatch API на `<AW_SERVER_HOST>:5600`;
- DLP health/case/policy services на AW server;
- 1C analytics API на `10.10.10.2:8710`;
- внешний gateway `https://dm.iri1968.dpdns.org/`;
- 1C analytics API на `<GATEWAY_HOST>:8710`;
- внешний gateway `https://<PUBLIC_GATEWAY_FQDN>/`;
- nginx Basic Auth на gateway.
## Целевая архитектура MVP
@@ -87,7 +87,7 @@ Bind:
External route через существующий nginx gateway:
```text
https://dm.iri1968.dpdns.org/portal/
https://<PUBLIC_GATEWAY_FQDN>/portal/
```
Почему Proxmox host:
@@ -291,7 +291,7 @@ sudo -n /usr/sbin/pct exec 201 -- cat /var/lib/detmir-grafana-check/latest.json
Основной URL:
```text
http://10.10.10.13:5610/reports/worktime/today
http://<AW_SERVER_HOST>:5610/reports/worktime/today
```
Правило:
@@ -317,9 +317,9 @@ ssh aw-server 'sudo -n /usr/local/bin/dlp-health-check --json'
Минимум:
```text
http://10.10.10.2:8710/api/health
http://10.10.10.2:8710/manager/brief
http://10.10.10.2:8710/manager/actions
http://<GATEWAY_HOST>:8710/api/health
http://<GATEWAY_HOST>:8710/manager/brief
http://<GATEWAY_HOST>:8710/manager/actions
```
Если `/manager/brief` HTML, для MVP не парсить его глубоко. Дать link и health
@@ -494,11 +494,11 @@ MVP read-only.
Команды:
```bash
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
cd <PROJECT_ROOT>
git status --short
export CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target
export CARGO_TARGET_DIR=<OPERATOR_HOME>/.cache/detmir-adk-rust-target
cd ansible
export no_proxy='localhost,127.0.0.1,192.168.100.18,10.10.10.13,10.10.10.2,10.10.10.0/24,192.168.100.0/24'
export no_proxy='localhost,127.0.0.1,<WINDOWS_HOST>,<AW_SERVER_HOST>,<GATEWAY_HOST>,<SERVER_SUBNET_CIDR>,<ENDPOINT_SUBNET_CIDR>'
export NO_PROXY="$no_proxy"
ansible proxmox -i inventory.ini -m shell -a 'detmir-status --json'
ansible proxmox -i inventory.ini -m shell -a 'detmir-check --json'
@@ -548,9 +548,9 @@ Acceptance:
```bash
cd adk-rust
cargo fmt --all -- --check
CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target cargo test -p detmir-portal
CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target cargo clippy -p detmir-portal --all-targets -- -D warnings
CARGO_TARGET_DIR=/home/igor/.cache/detmir-adk-rust-target cargo build --release -p detmir-portal
CARGO_TARGET_DIR=<OPERATOR_HOME>/.cache/detmir-adk-rust-target cargo test -p detmir-portal
CARGO_TARGET_DIR=<OPERATOR_HOME>/.cache/detmir-adk-rust-target cargo clippy -p detmir-portal --all-targets -- -D warnings
CARGO_TARGET_DIR=<OPERATOR_HOME>/.cache/detmir-adk-rust-target cargo build --release -p detmir-portal
```
## Phase 2: Backend Aggregation
@@ -717,13 +717,13 @@ Acceptance:
```bash
systemctl is-active detmir-portal
curl -fsS http://127.0.0.1:8720/api/health
curl -k -I -H 'Host: dm.iri1968.dpdns.org' https://127.0.0.1/portal/
curl -k -I -H 'Host: <PUBLIC_GATEWAY_FQDN>' https://127.0.0.1/portal/
```
External:
```text
https://dm.iri1968.dpdns.org/portal/
https://<PUBLIC_GATEWAY_FQDN>/portal/
```
## Phase 6: Integrate Into Health Gates
@@ -795,7 +795,7 @@ MVP is done only when all are true:
- portal serves HTML and JSON locally;
- portal deployed as systemd service on Proxmox;
- gateway URL works:
`https://dm.iri1968.dpdns.org/portal/`;
`https://<PUBLIC_GATEWAY_FQDN>/portal/`;
- browser screenshots checked desktop and mobile;
- no secrets in HTML/JSON/journald;
- `detmir-status` stays OK after deployment;
+3 -3
View File
@@ -2,7 +2,7 @@
## Что это
Канонический путь для интерактивной PowerShell-работы с `DetMir` Windows-хостом `192.168.100.18` из Linux/Codex.
Канонический путь для интерактивной PowerShell-работы с `DetMir` Windows-хостом `<WINDOWS_HOST>` из Linux/Codex.
Это не замена `WinRM` в Ansible. Разделение теперь такое:
@@ -13,7 +13,7 @@
Проверено на `2026-05-26`:
- host: `192.168.100.18`
- host: `<WINDOWS_HOST>`
- product: `Windows Server 2025 Datacenter Evaluation`
- release: `24H2`
- build: `10.0.26100.32690`
@@ -77,7 +77,7 @@ detmir-win-shell
Назначение:
- `detmir-win-test` — быстрый smoke-test удалённого PowerShell;
- `detmir-win-ps` — выполнить PowerShell-скрипт на `192.168.100.18`;
- `detmir-win-ps` — выполнить PowerShell-скрипт на `<WINDOWS_HOST>`;
- `detmir-win-shell` — открыть raw SSH shell на Windows-хост;
- `detmir-win-ssh` — выполнить произвольную SSH-команду одной строкой;
- `detmir-win-target` — показать текущий target.
+4 -4
View File
@@ -89,12 +89,12 @@
| Зона | Пример | Уровень доверия |
|---|---|---|
| Endpoint/RDP | `192.168.100.18` | Доверенный источник сигналов, но допускается риск локального вмешательства. |
| AW server | `10.10.10.13` | Основной trusted data/control plane для AW/DLP/worktime. |
| Proxmox/operator | `10.10.10.2` | Операторский gateway, portal, Telegram, automation entrypoint. |
| Endpoint/RDP | `<WINDOWS_HOST>` | Доверенный источник сигналов, но допускается риск локального вмешательства. |
| AW server | `<AW_SERVER_HOST>` | Основной trusted data/control plane для AW/DLP/worktime. |
| Proxmox/operator | `<GATEWAY_HOST>` | Операторский gateway, portal, Telegram, automation entrypoint. |
| Grafana/data | Grafana/Influx/ClickHouse | Витрина и аналитика, не первичный источник доказательств. |
| Laptop/operator shell | рабочая станция владельца | Удобный admin-клиент, но не обязательный runtime. |
| External access | `dm.iri1968.dpdns.org` | Доступ только через gateway/auth/reverse proxy. |
| External access | `<PUBLIC_GATEWAY_FQDN>` | Доступ только через gateway/auth/reverse proxy. |
Ключевой принцип: production-контур должен работать автономно на серверах.
Ноутбук не является обязательной частью runtime.
+23 -23
View File
@@ -48,28 +48,28 @@
| Узел | Роль |
|---|---|
| `10.10.10.1` | `pfSense`, firewall, VPN, ACL, OpenVPN export target |
| `10.10.10.2` | `Proxmox/DetMirAuto`, web gateway, Telegram bot, operator entrypoint |
| `10.10.10.13` | основной `AW-rus` server, health, worktime/reporting, `Hayabusa` server-side processing |
| `192.168.100.18` | `SHARKON2025`, Windows/RDP host, collectors, worktime session path, EVTX export |
| `<FIREWALL_HOST>` | `pfSense`, firewall, VPN, ACL, OpenVPN export target |
| `<GATEWAY_HOST>` | `Proxmox/DetMirAuto`, web gateway, Telegram bot, operator entrypoint |
| `<AW_SERVER_HOST>` | основной `AW-rus` server, health, worktime/reporting, `Hayabusa` server-side processing |
| `<WINDOWS_HOST>` | `SHARKON2025`, Windows/RDP host, collectors, worktime session path, EVTX export |
Практический вывод:
- серверный путь `AW-rus` сейчас должен считаться `10.10.10.13`;
- операторский и gateway-контур должен считаться `10.10.10.2`;
- Windows production-host для `DetMir` сейчас `192.168.100.18`, а не старые упоминания `192.168.100.21`.
- серверный путь `AW-rus` сейчас должен считаться `<AW_SERVER_HOST>`;
- операторский и gateway-контур должен считаться `<GATEWAY_HOST>`;
- Windows production-host для `DetMir` сейчас `<WINDOWS_HOST>`, а не старые упоминания `<OLD_WINDOWS_HOST>`.
### 2.1 Runtime snapshot после полной проверки 2026-05-28
Проверка выполнялась как production-contour test, а не только как HTTP ping.
Покрыты:
- `AW-rus` API/WebUI на `10.10.10.13:5600`;
- worktime/management API на `10.10.10.13:5610`;
- Windows/RDP host `192.168.100.18` через WinRM/SSH/Scheduled Tasks;
- `1C/file analytics` backend на `10.10.10.2:8710`;
- Proxmox/nginx gateway на `10.10.10.2`;
- Grafana на `10.10.10.11:3000`;
- `AW-rus` API/WebUI на `<AW_SERVER_HOST>:5600`;
- worktime/management API на `<AW_SERVER_HOST>:5610`;
- Windows/RDP host `<WINDOWS_HOST>` через WinRM/SSH/Scheduled Tasks;
- `1C/file analytics` backend на `<GATEWAY_HOST>:8710`;
- Proxmox/nginx gateway на `<GATEWAY_HOST>`;
- Grafana на `<GRAFANA_HOST>:3000`;
- browser smoke через Playwright по operator-facing страницам.
Фактический результат после стабилизации:
@@ -79,7 +79,7 @@
| `./check-aw-full.sh` | `FRESH=8 STALE=0 DEAD=0` |
| `aw-rus-healthd.py --json` | `ok=13 warn=0 fail=0` |
| `dlp-health-check --json` | `ok=20 warn=0 fail=0` |
| `systemctl --failed` на `10.10.10.13` | `0 loaded units listed` |
| `systemctl --failed` на `<AW_SERVER_HOST>` | `0 loaded units listed` |
| Playwright browser smoke | `14/14` страниц открылись |
| Grafana authenticated API/UI smoke | login OK, `19` dashboards в `/api/search`, все ключевые `1C File`/`DetMir` dashboards открылись |
| Grafana datasource health | `OK` для `clickhouse-1c`, `InfluxDB-AW`, `loki`, Proxmox/pfSense Influx datasources |
@@ -224,7 +224,7 @@
| Функция | Где реализована |
|---|---|
| EVTX export на Windows | `windows` runtime/export scripts |
| Intake на сервере | `10.10.10.13`, drop/inbox flow |
| Intake на сервере | `<AW_SERVER_HOST>`, drop/inbox flow |
| Processing/reporting | `aw-hayabusa`, `/opt/hayabusa`, server-side services |
| Bounded integration с AW-rus | `docs/hayabusa-aw-rus-integration-2026-05-14.md` |
| Operator guidance | `docs/hayabusa-operator-ib-guide-2026-05-14.md`, `docs/runbook.md` |
@@ -254,12 +254,12 @@
Базовые входы:
- `https://10.10.10.2/` — gateway;
- `https://10.10.10.2/go/proxmox-gui` — Proxmox GUI;
- `https://10.10.10.2/go/file1c-brief` — management/file-1C brief;
- `https://10.10.10.2/go/file1c-actions` — actions;
- `http://10.10.10.13:5600/api/0/info` — AW-rus API health;
- `http://10.10.10.13:5610/reports/worktime/management` — management reporting API.
- `https://<GATEWAY_HOST>/` — gateway;
- `https://<GATEWAY_HOST>/go/proxmox-gui` — Proxmox GUI;
- `https://<GATEWAY_HOST>/go/file1c-brief` — management/file-1C brief;
- `https://<GATEWAY_HOST>/go/file1c-actions` — actions;
- `http://<AW_SERVER_HOST>:5600/api/0/info` — AW-rus API health;
- `http://<AW_SERVER_HOST>:5610/reports/worktime/management` — management reporting API.
Telegram bot `DetMirAuto` обязан покрывать:
@@ -347,8 +347,8 @@ Telegram bot `DetMirAuto` обязан покрывать:
Практическая схема такая:
- использовать agent-описания из `/home/igor/.codex/agents/gsd-*` как действующее ядро исполнителей;
- вернуть orchestrator-skills из `/home/igor/.codex/skills_disabled/2026-05-21-current-prune/` для верхнеуровневого workflow;
- использовать agent-описания из `<OPERATOR_CODEX_HOME>/agents/gsd-*` как действующее ядро исполнителей;
- вернуть orchestrator-skills из `<OPERATOR_CODEX_HOME>/skills_disabled/2026-05-21-current-prune/` для верхнеуровневого workflow;
- hooks `gsd-phase-boundary.sh`, `gsd-statusline.js`, `gsd-workflow-guard.js` держать как сервисную обвязку, а не как замену основному процессу.
Минимум к восстановлению как orchestrator layer:
+48 -48
View File
@@ -6,22 +6,22 @@
## 0) Структура проекта (полные пути)
- `/home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env`
- `/home/igor/tmp/AWatch-rus/proxmox/create-ct.sh`
- `/home/igor/tmp/AWatch-rus/proxmox/push-aw-artifacts.sh`
- `/home/igor/tmp/AWatch-rus/aw-server/install_aw_server.sh`
- `/home/igor/tmp/AWatch-rus/aw-server/apply_webui_ru_patch.sh`
- `/home/igor/tmp/AWatch-rus/windows/deploy-single-user.ps1`
- `/home/igor/tmp/AWatch-rus/windows/deploy-domain-users.ps1`
- `/home/igor/tmp/AWatch-rus/windows/deploy-ensemble.ps1`
- `/home/igor/tmp/AWatch-rus/windows/hardening-recovery.ps1`
- `/home/igor/tmp/AWatch-rus/windows/validate-deployment.ps1`
- `/home/igor/tmp/AWatch-rus/windows/browser-domains-native-collector.ps1`
- `/home/igor/tmp/AWatch-rus/windows/dlp-endpoint-signals-collector.ps1`
- `/home/igor/tmp/AWatch-rus/ansible/deploy_aw_server.yml`
- `/home/igor/tmp/AWatch-rus/ansible/provision_proxmox_ct_and_deploy_aw.yml`
- `/home/igor/tmp/AWatch-rus/ansible/provision_proxmox_ct_matrix_and_deploy_aw.yml`
- `/home/igor/tmp/AWatch-rus/ansible/deploy_aw_windows.yml`
- `<PROJECT_ROOT>/private-config/deploy.env`
- `<PROJECT_ROOT>/proxmox/create-ct.sh`
- `<PROJECT_ROOT>/proxmox/push-aw-artifacts.sh`
- `<PROJECT_ROOT>/aw-server/install_aw_server.sh`
- `<PROJECT_ROOT>/aw-server/apply_webui_ru_patch.sh`
- `<PROJECT_ROOT>/windows/deploy-single-user.ps1`
- `<PROJECT_ROOT>/windows/deploy-domain-users.ps1`
- `<PROJECT_ROOT>/windows/deploy-ensemble.ps1`
- `<PROJECT_ROOT>/windows/hardening-recovery.ps1`
- `<PROJECT_ROOT>/windows/validate-deployment.ps1`
- `<PROJECT_ROOT>/windows/browser-domains-native-collector.ps1`
- `<PROJECT_ROOT>/windows/dlp-endpoint-signals-collector.ps1`
- `<PROJECT_ROOT>/ansible/deploy_aw_server.yml`
- `<PROJECT_ROOT>/ansible/provision_proxmox_ct_and_deploy_aw.yml`
- `<PROJECT_ROOT>/ansible/provision_proxmox_ct_matrix_and_deploy_aw.yml`
- `<PROJECT_ROOT>/ansible/deploy_aw_windows.yml`
---
@@ -39,11 +39,11 @@
Скопируйте шаблон:
```bash
cp /home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env.example \
/home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env
cp <PROJECT_ROOT>/private-config/deploy.env.example \
<PROJECT_ROOT>/private-config/deploy.env
```
Заполните в файле `/home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env`:
Заполните в файле `<PROJECT_ROOT>/private-config/deploy.env`:
- все `CT_*` параметры контейнера;
- все `AW_SERVER_*` параметры сервера;
@@ -59,14 +59,14 @@ cp /home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env.example \
Подготовьте:
- `/home/igor/tmp/AWatch-rus/ansible/inventory.ini`
- `/home/igor/tmp/AWatch-rus/ansible/group_vars/all.yml`
- `/home/igor/tmp/AWatch-rus/ansible/group_vars/proxmox.yml`
- `<PROJECT_ROOT>/ansible/inventory.ini`
- `<PROJECT_ROOT>/ansible/group_vars/all.yml`
- `<PROJECT_ROOT>/ansible/group_vars/proxmox.yml`
Запуск:
```bash
cd /home/igor/tmp/AWatch-rus/ansible
cd <PROJECT_ROOT>/ansible
ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml
```
@@ -81,7 +81,7 @@ ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml
Для массового режима (несколько CT):
```bash
cd /home/igor/tmp/AWatch-rus/ansible
cd <PROJECT_ROOT>/ansible
ansible-playbook -i inventory.ini provision_proxmox_ct_matrix_and_deploy_aw.yml
```
@@ -90,47 +90,47 @@ ansible-playbook -i inventory.ini provision_proxmox_ct_matrix_and_deploy_aw.yml
На узле Proxmox:
```bash
cd /home/igor/tmp/AWatch-rus
/home/igor/tmp/AWatch-rus/proxmox/create-ct.sh
cd <PROJECT_ROOT>
<PROJECT_ROOT>/proxmox/create-ct.sh
```
По умолчанию читается:
- `/home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env`
- `<PROJECT_ROOT>/private-config/deploy.env`
При необходимости можно передать другой путь:
```bash
/home/igor/tmp/AWatch-rus/proxmox/create-ct.sh /absolute/path/to/deploy.secrets.env
<PROJECT_ROOT>/proxmox/create-ct.sh /absolute/path/to/deploy.env
```
### 2.2 Загрузить bootstrap-артефакты и env внутрь CT
```bash
cd /home/igor/tmp/AWatch-rus
/home/igor/tmp/AWatch-rus/proxmox/push-aw-artifacts.sh
cd <PROJECT_ROOT>
<PROJECT_ROOT>/proxmox/push-aw-artifacts.sh
```
Скрипт загружает в CT:
- `/root/bootstrap/install_aw_server.sh`
- `/root/bootstrap/apply_webui_ru_patch.sh`
- `/root/bootstrap/activitywatch-server.service`
- `/root/bootstrap/aw-ru-patch.js`
- `/root/bootstrap/aw-sw-cleanup.js`
- `<CT_BOOTSTRAP_DIR>/install_aw_server.sh`
- `<CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh`
- `<CT_BOOTSTRAP_DIR>/activitywatch-server.service`
- `<CT_BOOTSTRAP_DIR>/aw-ru-patch.js`
- `<CT_BOOTSTRAP_DIR>/aw-sw-cleanup.js`
- `/etc/activitywatch/aw-server.env` (из `AW_SERVER_*`)
### 2.3 Установить ActivityWatch Server внутри CT
```bash
pct enter <CT_ID>
bash /root/bootstrap/install_aw_server.sh
bash <CT_BOOTSTRAP_DIR>/install_aw_server.sh
```
### 2.4 Применить RU patch Web UI
```bash
bash /root/bootstrap/apply_webui_ru_patch.sh
bash <CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh
systemctl restart activitywatch-server.service
```
@@ -173,7 +173,7 @@ grep -n 'aw-ru-patch\|aw-sw-cleanup' /opt/activitywatch/webui-ru/index.html
Скопируйте каталог:
- `/home/igor/tmp/AWatch-rus/windows`
- `<PROJECT_ROOT>/windows`
например в:
@@ -361,7 +361,7 @@ vzdump <CT_ID> --mode snapshot --compress zstd --storage <BACKUP_STORAGE>
Конфиги внутри CT:
```bash
pct exec <CT_ID> -- tar -C / -czf /root/activitywatch-config-backup.tgz \
pct exec <CT_ID> -- tar -C / -czf <PRIVATE_BACKUP_DIR>/activitywatch-config-backup.tgz \
etc/activitywatch \
etc/systemd/system/activitywatch-server.service \
opt/activitywatch/webui-ru \
@@ -371,14 +371,14 @@ pct exec <CT_ID> -- tar -C / -czf /root/activitywatch-config-backup.tgz \
### 6.2 Обновление сервера
1. Обновить `AW_SERVER_VERSION` и `AW_SERVER_DOWNLOAD_URL` в
`/home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env`
`<PROJECT_ROOT>/private-config/deploy.env`
2. Выполнить:
```bash
/home/igor/tmp/AWatch-rus/proxmox/push-aw-artifacts.sh
<PROJECT_ROOT>/proxmox/push-aw-artifacts.sh
pct enter <CT_ID>
bash /root/bootstrap/install_aw_server.sh
bash /root/bootstrap/apply_webui_ru_patch.sh
bash <CT_BOOTSTRAP_DIR>/install_aw_server.sh
bash <CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh
systemctl restart activitywatch-server.service
```
@@ -403,7 +403,7 @@ systemctl restart activitywatch-server.service
## 7) Безопасность
- Не хранить реальные секреты вне `/home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env`.
- Не хранить реальные приватные параметры вне `<PROJECT_ROOT>/private-config/deploy.env`.
- Не открывать `5600/tcp` в интернет напрямую.
- Публиковать через VPN или reverse proxy с ограничением доступа.
- Перед изменениями всегда делать backup.
@@ -412,10 +412,10 @@ systemctl restart activitywatch-server.service
## 8) Короткий чек-лист ввода в эксплуатацию
1. Заполнен `/home/igor/tmp/AWatch-rus/secrets/deploy.secrets.env`.
2. Выполнен `/home/igor/tmp/AWatch-rus/proxmox/create-ct.sh`.
3. Выполнен `/home/igor/tmp/AWatch-rus/proxmox/push-aw-artifacts.sh`.
4. В CT выполнены `/root/bootstrap/install_aw_server.sh` и `/root/bootstrap/apply_webui_ru_patch.sh`.
1. Заполнен `<PROJECT_ROOT>/private-config/deploy.env`.
2. Выполнен `<PROJECT_ROOT>/proxmox/create-ct.sh`.
3. Выполнен `<PROJECT_ROOT>/proxmox/push-aw-artifacts.sh`.
4. В CT выполнены `<CT_BOOTSTRAP_DIR>/install_aw_server.sh` и `<CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh`.
5. Сервер API/порт/UI проверены.
6. На Windows выполнен `deploy-domain-users.ps1`.
7. Проверены процессы, задачи и bucket'ы.
+1 -1
View File
@@ -29,7 +29,7 @@ Version-controlled dashboard JSON находятся в каталоге `grafan
1. Подготовьте inventory и vars:
```bash
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
cd <PROJECT_ROOT>
cp ansible/inventory.example.ini ansible/inventory.ini
cp ansible/group_vars/grafana.example.yml ansible/group_vars/grafana.yml
```
+11 -11
View File
@@ -6,17 +6,17 @@
## Что подтверждено по runtime
- `10.10.10.2` (`pve-detmir`, admin host) реально запускает:
- `<GATEWAY_HOST>` (`pve-detmir`, admin host) реально запускает:
- `/usr/local/bin/aw-server-rust --host 0.0.0.0 --port 5600 --webpath /opt/aw-webui-ru`
- `/usr/bin/python3 /opt/aw-pfsense/pfsense-aw-poller.py --config /etc/aw-pfsense/poller.json`
- `10.10.10.1` используется только как API-цель для `pfSense poller`.
- `<FIREWALL_HOST>` используется только как API-цель для `pfSense poller`.
- Значит интеграция `pfSense -> AW` работает через внешний poller, а не через установку чего-либо на сам firewall.
## Что сделано
1. Восстановлена и синхронизирована локальная копия проекта.
- В `/mnt/usb_hdd2/Projects/ActivityWatch-Russian` был поврежден `.git`.
- Источник истины: `/home/igor/tmp/AWatch-rus` с `origin https://github.com/igor04091968/AWatch-rus.git`.
- В `<PROJECT_ROOT>` был поврежден `.git`.
- Источник истины: `<PROJECT_ROOT>` с `origin https://github.com/igor04091968/AWatch-rus.git`.
- Локальная копия приведена к актуальному содержимому `main`.
2. Завершена русификация overview-дашборда Grafana.
@@ -28,28 +28,28 @@
- `socks5://127.0.0.1:1080` активен.
- `sing-box` запущен и пропускает трафик.
4. Подготовлен и развернут Linux-клиент ActivityWatch для `10.10.10.2`.
4. Подготовлен и развернут Linux-клиент ActivityWatch для `<GATEWAY_HOST>`.
- В репозиторий добавлен rollout:
- `scripts/install_aw_linux_client.sh`
- `docs/linux-client.md`
- На `10.10.10.2` под пользователем `admin` установлен bundle `ActivityWatch 0.13.2` в:
- На `<GATEWAY_HOST>` под пользователем `admin` установлен bundle `ActivityWatch 0.13.2` в:
- `~/.local/opt/activitywatch/v0.13.2/activitywatch`
- Созданы:
- `~/.config/activitywatch/aw-client/aw-client.toml` с `10.10.10.13:5600`
- `~/.config/activitywatch/aw-client/aw-client.toml` с `<AW_SERVER_HOST>:5600`
- `~/.config/activitywatch/aw-qt/aw-qt.toml`
- `~/.local/bin/activitywatch-remote-aw`
- `~/.config/autostart/activitywatch-remote-aw.desktop`
- Проверка показала:
- удаленный `AW server` с `10.10.10.2` достижим;
- удаленный `AW server` с `<GATEWAY_HOST>` достижим;
- `aw-qt --no-gui` стартует;
- bucket `aw-watcher-afk_pve-detmir` появился на сервере.
- Текущий blocker:
- на `10.10.10.2` нет активной `X11/GUI` сессии;
- на `<GATEWAY_HOST>` нет активной `X11/GUI` сессии;
- `aw-watcher-window` падает с `DISPLAY environment variable not set`;
- `aw-watcher-afk` падает на `failed to acquire X connection`.
## Зафиксированные выводы
- На текущем этапе `10.10.10.2` является фактическим runtime-хостом для `AW server` и `pfSense poller`.
- На текущем этапе `<GATEWAY_HOST>` является фактическим runtime-хостом для `AW server` и `pfSense poller`.
- Документация должна исходить из host-based сценария как из подтвержденного рабочего контура, а CT/LXC-схему держать как отдельный вариант развертывания.
- Для Linux-клиента на `10.10.10.2` установка завершена, но полноценные watcher-события начнутся только после реального графического логина пользователя.
- Для Linux-клиента на `<GATEWAY_HOST>` установка завершена, но полноценные watcher-события начнутся только после реального графического логина пользователя.
+2 -2
View File
@@ -80,14 +80,14 @@ PowerShell toolkit для клиентской стороны:
- `quality-gate.sh` — базовый preflight,
- инсталляторы Linux-клиента и console/ssh logger режимов.
### `secrets/`
### `private-config/`
Только шаблоны. Реальные секреты в репозиторий не кладутся.
## 3) Как компоненты связаны в потоке
Типовой pipeline:
1. Подготовка параметров (`docs/preparation.md`, `secrets/*.example`).
1. Подготовка параметров (`docs/preparation.md`, `private-config/*.example`).
2. Provisioning контейнера в Proxmox (`proxmox/`).
3. Установка/настройка AW Server (`aw-server/`).
4. Включение автозапуска и проверка (`systemd` + `docs/runbook.md`).
+2 -2
View File
@@ -14,7 +14,7 @@ GUI watcher'ы (`aw-watcher-window`, `aw-watcher-afk`) не требуются.
```bash
cd /path/to/AWatch-rus
sh ./scripts/install_aw_console_ssh_logger.sh \
--server-host 10.10.10.13 \
--server-host <AW_SERVER_HOST> \
--server-port 5600
```
@@ -50,7 +50,7 @@ tail -n 50 ~/.local/state/aw-console-ssh-logger/logs/collector.log
На AW сервере:
```bash
curl -fsS http://10.10.10.13:5600/api/0/buckets | jq -r 'keys[]' | grep -E '^aw-console-commands_|^aw-ssh-sessions_'
curl -fsS http://<AW_SERVER_HOST>:5600/api/0/buckets | jq -r 'keys[]' | grep -E '^aw-console-commands_|^aw-ssh-sessions_'
```
## Ограничения
+10 -10
View File
@@ -3,7 +3,7 @@
## 0. Ansible full-stack вариант (рекомендуется)
```sh
cd /home/igor/tmp/AWatch-rus/ansible
cd <PROJECT_ROOT>/ansible
ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml
```
@@ -12,7 +12,7 @@ ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml
Массовый вариант по матрице CT:
```sh
cd /home/igor/tmp/AWatch-rus/ansible
cd <PROJECT_ROOT>/ansible
ansible-playbook -i inventory.ini provision_proxmox_ct_matrix_and_deploy_aw.yml
```
@@ -21,8 +21,8 @@ ansible-playbook -i inventory.ini provision_proxmox_ct_matrix_and_deploy_aw.yml
На рабочей машине оператора:
```sh
cp proxmox/ct-vars.example.env /root/activitywatch-ct.env
cp aw-server/aw-server.env.example /root/activitywatch-aw.env
cp proxmox/ct-vars.example.env <PRIVATE_CONFIG_DIR>/activitywatch-ct.env
cp aw-server/aw-server.env.example <PRIVATE_CONFIG_DIR>/activitywatch-aw.env
```
Заполнить оба файла реальными значениями вне git.
@@ -33,7 +33,7 @@ cp aw-server/aw-server.env.example /root/activitywatch-aw.env
```sh
cd /path/to/ActivityWatch-Russian
./proxmox/create-ct.sh /root/activitywatch-ct.env
./proxmox/create-ct.sh <PRIVATE_CONFIG_DIR>/activitywatch-ct.env
```
Скрипт:
@@ -42,15 +42,15 @@ cd /path/to/ActivityWatch-Russian
- создаёт Debian 12 CT;
- запускает контейнер;
- выполняет минимальный bootstrap пакетов;
- готовит `/root/bootstrap` для дальнейшей загрузки артефактов.
- готовит `<CT_BOOTSTRAP_DIR>` для дальнейшей загрузки артефактов.
## 3. Загрузить артефакты в CT
На узле Proxmox:
```sh
./proxmox/push-aw-artifacts.sh /root/activitywatch-ct.env
pct push <CT_ID> /root/activitywatch-aw.env /etc/activitywatch/aw-server.env
./proxmox/push-aw-artifacts.sh <PRIVATE_CONFIG_DIR>/activitywatch-ct.env
pct push <CT_ID> <PRIVATE_CONFIG_DIR>/activitywatch-aw.env /etc/activitywatch/aw-server.env
```
В CT будут загружены:
@@ -67,7 +67,7 @@ pct push <CT_ID> /root/activitywatch-aw.env /etc/activitywatch/aw-server.env
```sh
pct enter <CT_ID>
bash /root/bootstrap/install_aw_server.sh
bash <CT_BOOTSTRAP_DIR>/install_aw_server.sh
```
Скрипт установки:
@@ -85,7 +85,7 @@ bash /root/bootstrap/install_aw_server.sh
Внутри CT:
```sh
bash /root/bootstrap/apply_webui_ru_patch.sh
bash <CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh
systemctl restart activitywatch-server.service
```
+3 -3
View File
@@ -15,7 +15,7 @@ SQLite is the default so the collector can be tested without deploying PostgreSQ
```bash
python3 scripts/aggregate_dlp_events.py \
--aw-url http://10.10.10.13:5600/api/0 \
--aw-url http://<AW_SERVER_HOST>:5600/api/0 \
--sqlite-path data/dlp-events.sqlite3 \
--lookback-hours 24
```
@@ -38,7 +38,7 @@ For centralized reporting, pass a DSN through an environment variable instead of
export DLP_AGGREGATOR_POSTGRES_DSN='postgresql://aw_dlp:${PASSWORD}@postgres.internal:5432/aw_dlp'
python3 -m pip install 'psycopg[binary]'
python3 scripts/aggregate_dlp_events.py \
--aw-url http://10.10.10.13:5600/api/0
--aw-url http://<AW_SERVER_HOST>:5600/api/0
```
Minimum database bootstrap:
@@ -71,7 +71,7 @@ Future runs resume from that timestamp with a small overlap window to avoid miss
Cron every minute:
```cron
* * * * * cd /opt/AWatch-rus && /usr/bin/python3 scripts/aggregate_dlp_events.py --aw-url http://10.10.10.13:5600/api/0 >> /var/log/aw-dlp-aggregator.log 2>&1
* * * * * cd /opt/AWatch-rus && /usr/bin/python3 scripts/aggregate_dlp_events.py --aw-url http://<AW_SERVER_HOST>:5600/api/0 >> /var/log/aw-dlp-aggregator.log 2>&1
```
## Example Grafana queries
@@ -1,6 +1,6 @@
# DLP Content Analysis Runtime Status 2026-05-13
This document records the production-verified state of advanced content analysis on `10.10.10.13`.
This document records the production-verified state of advanced content analysis on `<AW_SERVER_HOST>`.
## What is live
+6 -6
View File
@@ -18,7 +18,7 @@ This adds a safe offline pipeline to preload DLP blacklists from static Sigma in
- `scripts/extract_ioc_from_sigma.py` (core extractor)
- `scripts/build_dlp_ioc_from_hayabusa.sh` (wrapper)
## Production (AW server 10.10.10.13)
## Production (AW server <AW_SERVER_HOST>)
IOC enrichment is deployed by `ansible/deploy_aw_server.yml` when `aw_dlp_ioc_enabled=true`.
@@ -27,9 +27,9 @@ IOC enrichment is deployed by `ansible/deploy_aw_server.yml` when `aw_dlp_ioc_en
- refresh interval: `aw_dlp_ioc_refresh_interval` (default `6h`)
- output dir: `/opt/activitywatch/dlp-ioc/output`
- HTTP export via existing AW worktime API (`:5610`):
- `http://10.10.10.13:5610/dlp-ioc/ioc_blacklist.json`
- `http://10.10.10.13:5610/dlp-ioc/ioc_blacklist.csv`
- `http://10.10.10.13:5610/dlp-ioc/ioc_blacklist.sql`
- `http://<AW_SERVER_HOST>:5610/dlp-ioc/ioc_blacklist.json`
- `http://<AW_SERVER_HOST>:5610/dlp-ioc/ioc_blacklist.csv`
- `http://<AW_SERVER_HOST>:5610/dlp-ioc/ioc_blacklist.sql`
Mandatory post-deploy checks in Ansible:
- `ioc_blacklist.json`
@@ -41,7 +41,7 @@ Each file must exist and be non-empty, otherwise deploy fails.
## Run
```bash
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
cd <PROJECT_ROOT>
bash scripts/build_dlp_ioc_from_hayabusa.sh
```
@@ -50,7 +50,7 @@ Optional custom paths:
```bash
bash scripts/build_dlp_ioc_from_hayabusa.sh \
/mnt/usb_hdd1/Projects/hayabusa/rules \
/mnt/usb_hdd2/Projects/ActivityWatch-Russian/data/dlp-ioc
<PROJECT_ROOT>/data/dlp-ioc
```
## Output artifacts
+1 -1
View File
@@ -5,7 +5,7 @@
This document converts the high-level production DLP plan into an execution sequence with explicit phase boundaries, dependencies, deliverables, and acceptance gates.
Source plan:
- [dlp-production-plan-windows-10-19.md](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/docs/dlp-production-plan-windows-10-19.md:1)
- [dlp-production-plan-windows-10-19.md](<PROJECT_ROOT>/docs/dlp-production-plan-windows-10-19.md:1)
## Execution Rule
+1 -1
View File
@@ -2,7 +2,7 @@
## Verified production chain
Verified on `10.10.10.13`:
Verified on `<AW_SERVER_HOST>`:
- `policy engine`
- service: `aw-dlp-policy-engine.service`
+2 -2
View File
@@ -18,10 +18,10 @@
.\email-outbound-collector.ps1
# С явными параметрами
.\email-outbound-collector.ps1 -ServerHost 10.10.10.13 -ServerPort 5600 -Mode outlook
.\email-outbound-collector.ps1 -ServerHost <AW_SERVER_HOST> -ServerPort 5600 -Mode outlook
# Только SMTP мониторинг (без Outlook)
.\email-outbound-collector.ps1 -ServerHost 10.10.10.13 -Mode smtp
.\email-outbound-collector.ps1 -ServerHost <AW_SERVER_HOST> -Mode smtp
```
### Параметры
+1 -1
View File
@@ -221,7 +221,7 @@ WebUI компоненты для:
Для пересборки графа после изменений кода:
```bash
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
cd <PROJECT_ROOT>
graphify .
```
@@ -1,6 +1,6 @@
# Hayabusa Artifact Workflow 2026-05-14
This document records the server-side EVTX intake and archive workflow on `10.10.10.13`.
This document records the server-side EVTX intake and archive workflow on `<AW_SERVER_HOST>`.
## Directories
@@ -24,7 +24,7 @@ Not recommended:
## Operator path
1. Export EVTX package on Windows with `export-evtx-for-hayabusa.ps1`.
2. Transfer the resulting zip package to `10.10.10.13`.
2. Transfer the resulting zip package to `<AW_SERVER_HOST>`.
3. Run one of:
```bash
@@ -48,7 +48,7 @@ Do not run it for every minor signal. It is meant for escalation and investigati
powershell.exe -ExecutionPolicy Bypass -File C:\ProgramData\AWatch-rus\export-evtx-for-hayabusa.ps1
```
2. Transfer the resulting zip package to `10.10.10.13`.
2. Transfer the resulting zip package to `<AW_SERVER_HOST>`.
3. Run server-side processing:
+1 -1
View File
@@ -1,6 +1,6 @@
# Hayabusa Server-Side Runner 2026-05-14
This document records the production runner model for Hayabusa on `10.10.10.13`.
This document records the production runner model for Hayabusa on `<AW_SERVER_HOST>`.
## Install layout
+1 -1
View File
@@ -17,7 +17,7 @@
## Packaging model
- analysis host: `10.10.10.13`
- analysis host: `<AW_SERVER_HOST>`
- install root: `/opt/hayabusa`
- versioned release root: `/opt/hayabusa/releases/v3.9.0`
- active symlink target:
+4 -4
View File
@@ -6,8 +6,8 @@
Подтвержденный целевой кейс:
- Linux desktop/admin host: `10.10.10.2`
- удаленный `AW server`: `10.10.10.13:5600`
- Linux desktop/admin host: `<GATEWAY_HOST>`
- удаленный `AW server`: `<AW_SERVER_HOST>:5600`
## Что делает скрипт
@@ -24,7 +24,7 @@
```bash
cd /path/to/AWatch-rus
sh ./scripts/install_aw_linux_client.sh \
--server-host 10.10.10.13 \
--server-host <AW_SERVER_HOST> \
--server-port 5600
```
@@ -62,7 +62,7 @@ cat ~/.config/activitywatch/aw-qt/aw-qt.toml
Проверка на сервере:
```bash
curl -fsS http://10.10.10.13:5600/api/0/buckets | jq -r 'keys[]' | grep '^aw-watcher-'
curl -fsS http://<AW_SERVER_HOST>:5600/api/0/buckets | jq -r 'keys[]' | grep '^aw-watcher-'
```
## Ограничение
+2 -2
View File
@@ -22,7 +22,7 @@
```bash
cd /path/to/AWatch-rus
sh ./scripts/install_aw_linux_remote_worker.sh \
--server-host 10.10.10.13 \
--server-host <AW_SERVER_HOST> \
--server-port 5600
```
@@ -73,7 +73,7 @@ tail -n 50 ~/.local/state/aw-linux-web-category/logs/collector.log
На AW server:
```bash
curl -fsS http://10.10.10.13:5600/api/0/buckets | jq -r 'keys[]' | \
curl -fsS http://<AW_SERVER_HOST>:5600/api/0/buckets | jq -r 'keys[]' | \
grep -E '^aw-watcher-window_|^aw-watcher-afk_|^aw-console-commands_|^aw-ssh-sessions_|^aw-linux-web-context_|^aw-detmir-web-category_'
```
+3 -3
View File
@@ -3,7 +3,7 @@
`scripts/metagpt-aw-scout.sh` is the safe project wrapper for using the
MetaGPT-configured LLM provider with ActivityWatch-Russian tasks.
Default mode is direct LLM scout through `/home/igor/.metagpt/config2.yaml`.
Default mode is direct LLM scout through `<OPERATOR_HOME>/.metagpt/config2.yaml`.
This avoids MetaGPT Browser/Editor tools, which are too noisy for operational
checklists.
@@ -24,8 +24,8 @@ Use a valid provider key outside git:
export GROQ_API_KEY="gsk_..."
```
The global wrapper `/home/igor/bin/metagpt-lab` can write the key into
`/home/igor/.metagpt/config2.yaml`. The scout script reads that config and does
The global wrapper `<OPERATOR_HOME>/bin/metagpt-lab` can write the key into
`<OPERATOR_HOME>/.metagpt/config2.yaml`. The scout script reads that config and does
not print secrets.
## Presets
+3 -3
View File
@@ -57,11 +57,11 @@
```sh
vzdump <CT_ID> --mode snapshot --compress zstd --storage <BACKUP_STORAGE>
pct exec <CT_ID> -- tar -C / -czf /root/activitywatch-config-backup.tgz \
pct exec <CT_ID> -- tar -C / -czf <PRIVATE_BACKUP_DIR>/activitywatch-config-backup.tgz \
etc/activitywatch etc/systemd/system/activitywatch-server.service opt/activitywatch/webui-ru
curl -sS http://127.0.0.1:5600/api/0/buckets/aw-dlp-review_<HOST>/events?limit=500 > /root/aw-dlp-review-<HOST>.json
curl -sS http://127.0.0.1:5600/api/0/buckets/aw-dlp-rules_<HOST>/events?limit=500 > /root/aw-dlp-rules-<HOST>.json
curl -sS http://127.0.0.1:5600/api/0/buckets/aw-dlp-review_<HOST>/events?limit=500 > <PRIVATE_BACKUP_DIR>/aw-dlp-review-<HOST>.json
curl -sS http://127.0.0.1:5600/api/0/buckets/aw-dlp-rules_<HOST>/events?limit=500 > <PRIVATE_BACKUP_DIR>/aw-dlp-rules-<HOST>.json
```
## Rollback
+10 -10
View File
@@ -12,11 +12,11 @@
Проверенный на `2026-04-27` рабочий контур:
- `10.10.10.2` (`pve-detmir`, admin host) запускает `AW server`:
- `<GATEWAY_HOST>` (`pve-detmir`, admin host) запускает `AW server`:
- `/usr/local/bin/aw-server-rust --host 0.0.0.0 --port 5600 --webpath /opt/aw-webui-ru`
- тот же `10.10.10.2` запускает внешний `pfSense poller`:
- тот же `<GATEWAY_HOST>` запускает внешний `pfSense poller`:
- `/usr/bin/python3 /opt/aw-pfsense/pfsense-aw-poller.py --config /etc/aw-pfsense/poller.json`
- `10.10.10.1` используется как API-цель для poller'а; на сам `pfSense` агент или сервер `AW` не ставятся.
- `<FIREWALL_HOST>` используется как API-цель для poller'а; на сам `pfSense` агент или сервер `AW` не ставятся.
## Bucket'ы
@@ -28,11 +28,11 @@
## Файлы
- [pfsense-aw-poller.py](/home/igor/tmp/AWatch-rus/pfsense/pfsense-aw-poller.py)
- [pfsense-aw-poller.service](/home/igor/tmp/AWatch-rus/pfsense/pfsense-aw-poller.service)
- [pfsense-aw-poller.example.json](/home/igor/tmp/AWatch-rus/pfsense/pfsense-aw-poller.example.json)
- [deploy_aw_pfsense_poller.yml](/home/igor/tmp/AWatch-rus/ansible/deploy_aw_pfsense_poller.yml)
- [pfsense-poller.example.yml](/home/igor/tmp/AWatch-rus/ansible/group_vars/pfsense-poller.example.yml)
- [pfsense-aw-poller.py](<PROJECT_ROOT>/pfsense/pfsense-aw-poller.py)
- [pfsense-aw-poller.service](<PROJECT_ROOT>/pfsense/pfsense-aw-poller.service)
- [pfsense-aw-poller.example.json](<PROJECT_ROOT>/pfsense/pfsense-aw-poller.example.json)
- [deploy_aw_pfsense_poller.yml](<PROJECT_ROOT>/ansible/deploy_aw_pfsense_poller.yml)
- [pfsense-poller.example.yml](<PROJECT_ROOT>/ansible/group_vars/pfsense-poller.example.yml)
## Ручной запуск
@@ -47,7 +47,7 @@ python3 /opt/aw-pfsense/pfsense-aw-poller.py --config /etc/aw-pfsense/poller.jso
## Через Ansible
```bash
cd /home/igor/tmp/AWatch-rus/ansible
cd <PROJECT_ROOT>/ansible
cp group_vars/pfsense-poller.example.yml group_vars/pfsense-poller.yml
ansible-playbook -i inventory.ini deploy_aw_pfsense_poller.yml
```
@@ -56,7 +56,7 @@ Inventory:
```ini
[aw_pfsense_pollers]
aw-poller-01 ansible_host=10.10.10.50
aw-poller-01 ansible_host=<POLLER_HOST>
```
## AW Web
+2 -2
View File
@@ -59,14 +59,14 @@ pct list
## Что подготовить до деплоя
- заполненный `secrets/deploy.secrets.env` (единый файл для CT + AW server);
- заполненный `private-config/deploy.env` (единый файл для CT + AW server);
- согласованный URL релиза `aw-server-rust`;
- решение по публикации: VPN или reverse proxy;
- решение по backup: `vzdump`, snapshot, rsync, NAS или object storage.
## Единый файл секретов
Файл `secrets/deploy.secrets.env` автоматически подхватывается:
Файл `private-config/deploy.env` автоматически подхватывается:
- `proxmox/create-ct.sh`
- `proxmox/push-aw-artifacts.sh`
+29 -29
View File
@@ -4,16 +4,16 @@
### Proxmox web gateway
Если на host `10.10.10.2` развёрнут `nginx` gateway, базовые проверки такие:
Если на host `<GATEWAY_HOST>` развёрнут `nginx` gateway, базовые проверки такие:
```sh
systemctl status nginx --no-pager
nginx -t
curl -I -sS -H 'Host: dm.iri1968.dpdns.org' http://127.0.0.1/
curl -k -fsS -H 'Host: dm.iri1968.dpdns.org' https://127.0.0.1/healthz
curl -k -I -sS -H 'Host: dm.iri1968.dpdns.org' https://127.0.0.1/ | head
curl -k -u "$(awk -F= '/^user=/{u=$2}/^password=/{p=$2}END{print u\":\"p}' /root/proxmox-web-gateway.credentials)" \
-H 'Host: dm.iri1968.dpdns.org' -fsS https://127.0.0.1/ | grep -F 'dm.iri1968.dpdns.org'
curl -I -sS -H 'Host: <PUBLIC_GATEWAY_FQDN>' http://127.0.0.1/
curl -k -fsS -H 'Host: <PUBLIC_GATEWAY_FQDN>' https://127.0.0.1/healthz
curl -k -I -sS -H 'Host: <PUBLIC_GATEWAY_FQDN>' https://127.0.0.1/ | head
curl -k -u "$(awk -F= '/^user=/{u=$2}/^password=/{p=$2}END{print u\":\"p}' <GATEWAY_CREDENTIALS_FILE>)" \
-H 'Host: <PUBLIC_GATEWAY_FQDN>' -fsS https://127.0.0.1/ | grep -F '<PUBLIC_GATEWAY_FQDN>'
```
Playbook для повторного rollout:
@@ -28,24 +28,24 @@ ansible-playbook -i ansible/inventory.ini ansible/deploy_proxmox_web_gateway.yml
Публичная схема:
```text
Internet -> dm.iri1968.dpdns.org -> pfSense WAN 178.178.98.83 -> NAT 80/443 -> nginx 10.10.10.2
Internet -> <PUBLIC_GATEWAY_FQDN> -> pfSense WAN <WAN_IP> -> NAT 80/443 -> nginx <GATEWAY_HOST>
```
Нормальное состояние:
- `https://dm.iri1968.dpdns.org/healthz` -> `200 ok` без auth;
- `https://dm.iri1968.dpdns.org/` без auth -> `401`;
- `http://dm.iri1968.dpdns.org/healthz` -> `301` на HTTPS;
- `https://<PUBLIC_GATEWAY_FQDN>/healthz` -> `200 ok` без auth;
- `https://<PUBLIC_GATEWAY_FQDN>/` без auth -> `401`;
- `http://<PUBLIC_GATEWAY_FQDN>/healthz` -> `301` на HTTPS;
- после Basic Auth:
- `/` -> gateway index;
- `/r/file1c/brief` -> 1C brief;
- `/r/grafana/api/health` -> Grafana health;
- `/r/aw/api/0/info` -> AW server info.
Gateway credential хранится только на `10.10.10.2`:
Gateway credential хранится только на `<GATEWAY_HOST>`:
```sh
sudo cat /root/proxmox-web-gateway.credentials
sudo cat <GATEWAY_CREDENTIALS_FILE>
```
pfSense NAT backup перед автоматической правкой:
@@ -58,13 +58,13 @@ ls -1t /opt/infra-admin/backups/pfsense-gateway-nat-*.json | head
```sh
set -a
. /home/igor/.config/tsj-bot/pfsense.env.readonly
. <OPERATOR_HOME>/.config/tsj-bot/pfsense.env.readonly
set +a
curl -ksS -H "X-API-Key: $PFSENSE_API_KEY" "$PFSENSE_URL/api/v2/firewall/apply"
```
NAT должен содержать `WAN tcp 443 -> 10.10.10.2:443` и `WAN tcp 80 -> 10.10.10.2:80`.
WAN rules должны содержать pass на `10.10.10.2:80` и `10.10.10.2:443`.
NAT должен содержать `WAN tcp 443 -> <GATEWAY_HOST>:443` и `WAN tcp 80 -> <GATEWAY_HOST>:80`.
WAN rules должны содержать pass на `<GATEWAY_HOST>:80` и `<GATEWAY_HOST>:443`.
### На Proxmox
@@ -77,7 +77,7 @@ pct exec <CT_ID> -- curl -fsS http://127.0.0.1:5600/api/0/info
### На host-based инсталляции
Для подтвержденного размещения на `10.10.10.2`:
Для подтвержденного размещения на `<GATEWAY_HOST>`:
```sh
ps -ef | grep -E 'aw-server-rust|pfsense-aw-poller' | grep -v grep
@@ -265,7 +265,7 @@ curl -fsS 'http://127.0.0.1:5610/reports/worktime/management?day=today&departmen
powershell.exe -ExecutionPolicy Bypass -File C:\ProgramData\AWatch-rus\export-upload-hayabusa-to-aw-server.ps1 -HoursBack 6 -CaseId 30
```
2. Сервер `10.10.10.13` сам:
2. Сервер `<AW_SERVER_HOST>` сам:
- примет `zip` и `.meta.json` в `/opt/activitywatch/aw-rus-ops/drop`;
- запустит `aw-hayabusa`;
@@ -293,7 +293,7 @@ curl -fsS http://127.0.0.1:5602/api/0/dlp/cases/30
Цель: подтвердить один реальный путь
- Windows EVTX export
- перенос пакета на `10.10.10.13`
- перенос пакета на `<AW_SERVER_HOST>`
- intake через `aw-hayabusa`
- генерация отчёта
- привязка bounded metadata к операторскому follow-up
@@ -324,7 +324,7 @@ Get-ChildItem 'C:\ProgramData\AWatch-rus\forensics\evtx-exports' |
- `HOST-YYYYMMDD-HHMMSS.zip`
3. Перенести zip на `10.10.10.13` в операторскую рабочую зону.
3. Перенести zip на `<AW_SERVER_HOST>` в операторскую рабочую зону.
4. На `AW-server` проверить раннер:
@@ -463,7 +463,7 @@ curl -fsS 'http://127.0.0.1:5600/api/0/buckets/aw-dlp-incidents_SHARKON2025/even
Цель: подтвердить, что при недоступности AW API события не теряются, а буферизуются в локальной очереди и автоматически отправляются после восстановления связи.
На RDP-хосте (`192.168.100.18`) в PowerShell под администратором:
На RDP-хосте (`<WINDOWS_HOST>`) в PowerShell под администратором:
1) Проверить/обнулить очереди:
@@ -509,7 +509,7 @@ Get-Item $q1,$q2 | Select Name,Length,LastWriteTime
6) Проверка на AW server:
```sh
curl -fsS 'http://10.10.10.13:5600/api/0/buckets/aw-file-operations_10.10.10.13/events?limit=10' | jq '.[0].data'
curl -fsS 'http://<AW_SERVER_HOST>:5600/api/0/buckets/aw-file-operations_<AW_SERVER_HOST>/events?limit=10' | jq '.[0].data'
```
После теста удалить правило:
@@ -520,12 +520,12 @@ Remove-NetFirewallRule -DisplayName 'AWatch WAL Test Block 5600' -ErrorAction Si
### PowerShell MCP на DetMir Windows host
Для `DetMir` Windows host `192.168.100.18` интерактивный путь из Linux/Codex закреплён через `SSH`, а не через `WSMan`.
Для `DetMir` Windows host `<WINDOWS_HOST>` интерактивный путь из Linux/Codex закреплён через `SSH`, а не через `WSMan`.
Быстрый вход:
```bash
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian
cd <PROJECT_ROOT>
bash scripts/install_detmir_powershell_mcp.sh
```
@@ -592,21 +592,21 @@ chmod 600 /tmp/sharkon_ru.auth
3. Запустить recovery task:
```sh
wmiexec.py -nooutput -A /tmp/sharkon_ru.auth 192.168.100.18 \
wmiexec.py -nooutput -A /tmp/sharkon_ru.auth <WINDOWS_HOST> \
"powershell -NoProfile -Command \"Start-ScheduledTask -TaskName 'ActivityWatch Recovery'\""
```
4. Запустить все launch tasks:
```sh
wmiexec.py -nooutput -A /tmp/sharkon_ru.auth 192.168.100.18 \
wmiexec.py -nooutput -A /tmp/sharkon_ru.auth <WINDOWS_HOST> \
"powershell -NoProfile -Command \"Get-ScheduledTask | Where-Object TaskName -like 'ActivityWatch Launch *' | ForEach-Object { Start-ScheduledTask -TaskName \$_.TaskName }\""
```
5. Подождать 10-20 секунд и проверить API на AW server (`10.10.10.13:5600`):
5. Подождать 10-20 секунд и проверить API на AW server (`<AW_SERVER_HOST>:5600`):
```sh
curl -fsS 'http://10.10.10.13:5600/api/0/buckets/aw-watcher-afk_SHARKON2025/events?limit=30' \
curl -fsS 'http://<AW_SERVER_HOST>:5600/api/0/buckets/aw-watcher-afk_SHARKON2025/events?limit=30' \
| jq '{latest:.[0].timestamp, statuses:(group_by(.data.status)|map({status:.[0].data.status,count:length}))}'
```
@@ -644,7 +644,7 @@ journalctl -xeu activitywatch-server.service --no-pager
Повторное применение:
```sh
bash /root/bootstrap/apply_webui_ru_patch.sh
bash <CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh
systemctl restart activitywatch-server.service
```
@@ -675,7 +675,7 @@ systemctl restart activitywatch-server.service
Для повторяемой проверки сертификатов подписантов и встроенных лицензий CryptoPro:
```bash
cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible
cd <PROJECT_ROOT>/ansible
ansible-playbook -i inventory.ini audit_cryptopro_windows.yml
```
+5 -5
View File
@@ -9,20 +9,20 @@
Это отдельный стек для **файловой 1С**, где:
- Windows/RDP host отдаёт только `read-only export/telemetry`;
- `10.10.10.2` принимает данные, грузит их в `ClickHouse`, строит `detections/cases`;
- `10.10.10.11` показывает dashboards в `Grafana`.
- `<GATEWAY_HOST>` принимает данные, грузит их в `ClickHouse`, строит `detections/cases`;
- `<GRAFANA_HOST>` показывает dashboards в `Grafana`.
## Production topology
- `192.168.100.18`
- `<WINDOWS_HOST>`
- файловая 1С
- scheduled task `ActivityWatch File1C Upload`
- `10.10.10.2`
- `<GATEWAY_HOST>`
- `ClickHouse`
- ETL/ingest
- `aw-1c-ingest.timer`
- `aw-1c-proofcheck.timer`
- `10.10.10.11`
- `<GRAFANA_HOST>`
- `Grafana`
- datasource `clickhouse-1c`
- folder `1C File Analytics`
@@ -2,13 +2,13 @@
## 1.2 Обязательные переменные и preflight
После `cc9e4a0` контур Grafana/Influx считается частью базового production path. Перед запуском `ansible/deploy_aw_server.yml` должны быть доступны не только WinRM/SSH секреты, но и write-token'ы InfluxDB для bucket `aw_metrics`.
После `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
source private-config/deploy.env
set +a
```
@@ -14,7 +14,7 @@ aw_dlp_influx_enabled: true
```text
org: proxmox
bucket: aw_metrics
url: http://10.10.10.10:8086
url: http://<INFLUXDB_HOST>:8086
```
Grafana datasource `InfluxDB-AW` читает тот же bucket.
@@ -70,7 +70,7 @@ journalctl -u aw-dlp-influx-exporter.service -n 30 --no-pager
```bash
curl -u "$GRAFANA_USER:$GRAFANA_PASSWORD" \
http://10.10.10.11:3000/api/datasources/uid/influxdb_aw/health
http://<GRAFANA_HOST>:3000/api/datasources/uid/influxdb_aw/health
```
Ожидается:
+3 -3
View File
@@ -4,9 +4,9 @@
## Открыть дашборды
- [Grafana dashboards](http://10.10.10.11:3000/dashboards) - основная страница со всеми панелями.
- [ActivityWatch Web UI](http://10.10.10.13:5600) - детальный просмотр исходных событий.
- [Worktime reports](http://10.10.10.13:5610) - отчеты по рабочему времени, если сервис включен.
- [Grafana dashboards](http://<GRAFANA_HOST>:3000/dashboards) - основная страница со всеми панелями.
- [ActivityWatch Web UI](http://<AW_SERVER_HOST>:5600) - детальный просмотр исходных событий.
- [Worktime reports](http://<AW_SERVER_HOST>:5610) - отчеты по рабочему времени, если сервис включен.
## Что смотреть в первую очередь
+2 -2
View File
@@ -6,7 +6,7 @@ This document defines the Windows-side export path for Hayabusa DFIR enrichment.
Windows hosts do not analyze EVTX locally for this contour.
They export selected event logs into a bounded forensic staging area, and the server-side Hayabusa workflow on `10.10.10.13` analyzes those artifacts later.
They export selected event logs into a bounded forensic staging area, and the server-side Hayabusa workflow on `<AW_SERVER_HOST>` analyzes those artifacts later.
## Export script
@@ -87,5 +87,5 @@ This wrapper:
- output stays outside standard AW buckets
- output stays outside normal DLP screenshot artifacts
- server-side Hayabusa execution happens later on `10.10.10.13`
- server-side Hayabusa execution happens later on `<AW_SERVER_HOST>`
- only bounded Hayabusa metadata returns into the case layer
+2 -2
View File
@@ -189,7 +189,7 @@ Ansible playbook `ansible/deploy_aw_windows.yml` выполняет этот mig
```powershell
.\windows\deploy-domain-users.ps1 `
-ServerHost 10.10.10.13 `
-ServerHost <AW_SERVER_HOST> `
-ServerPort 5600 `
-Domain SHARKON2025 `
-Users user2,user3,user4,user5 `
@@ -203,7 +203,7 @@ Single-user pilot в таком же стиле:
```powershell
.\windows\deploy-single-user.ps1 `
-ServerHost 10.10.10.13 `
-ServerHost <AW_SERVER_HOST> `
-ServerPort 5600 `
-TargetUser 'SHARKON2025\user1' `
-InstallRoot 'C:\Program Files\AWatch-rus\bin' `
+8 -8
View File
@@ -4,13 +4,13 @@
## Полные пути
- `/home/igor/tmp/AWatch-rus/windows/deploy-ensemble.ps1`
- `/home/igor/tmp/AWatch-rus/windows/deploy-domain-users.ps1`
- `/home/igor/tmp/AWatch-rus/windows/deploy-single-user.ps1`
- `/home/igor/tmp/AWatch-rus/windows/hardening-recovery.ps1`
- `/home/igor/tmp/AWatch-rus/windows/validate-deployment.ps1`
- `/home/igor/tmp/AWatch-rus/windows/ActivityWatch.Windows.Common.psm1`
- `/home/igor/tmp/AWatch-rus/windows/ActivityWatch.Windows.Common.psd1`
- `<PROJECT_ROOT>/windows/deploy-ensemble.ps1`
- `<PROJECT_ROOT>/windows/deploy-domain-users.ps1`
- `<PROJECT_ROOT>/windows/deploy-single-user.ps1`
- `<PROJECT_ROOT>/windows/hardening-recovery.ps1`
- `<PROJECT_ROOT>/windows/validate-deployment.ps1`
- `<PROJECT_ROOT>/windows/ActivityWatch.Windows.Common.psm1`
- `<PROJECT_ROOT>/windows/ActivityWatch.Windows.Common.psd1`
## Рекомендованный запуск
@@ -18,7 +18,7 @@
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
C:\Program Files\AWatch-rus\windows\deploy-ensemble.ps1 `
-ServerHost 10.10.10.13 `
-ServerHost <AW_SERVER_HOST> `
-ServerPort 5600 `
-Domain SHARKON2025 `
-Users user1,user2,user3,user4,user5 `
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
/home/igor/.local/share/uv/tools/graphifyy/bin/python3
-101
View File
@@ -1,101 +0,0 @@
# ActivityWatch-Russian Knowledge Graph Report
## Overview
- **Total Nodes**: 404
- **Total Edges**: 933
- **Communities**: 27
- **Source**: AST extraction (code-only corpus)
## Communities by Size
### Community 1 (62 nodes)
- install_kit_awindows_20260427_211240_windows_dlp_endpoint_signals_collector_ps1
- dlp_endpoint_signals_collector_get_deploymentconfig
- dlp_endpoint_signals_collector_write_endpointlog
- dlp_endpoint_signals_collector_invoke_awjsonpost
- dlp_endpoint_signals_collector_ensure_bucket
- ... and 57 more
### Community 2 (56 nodes)
- aw_server_aw_ru_patch_js
- aw_ru_patch_injectstyles
- aw_ru_patch_hidenoisenavigation
- aw_ru_patch_getcurrenthostfromhash
- aw_ru_patch_ispvelikehost
- ... and 51 more
### Community 3 (54 nodes)
- install_kit_awindows_20260427_211240_windows_browser_domains_native_collector_ps1
- browser_domains_native_collector_get_deploymentconfig
- browser_domains_native_collector_write_collectorlog
- browser_domains_native_collector_write_dlpincidentlog
- browser_domains_native_collector_test_domainmatch
- ... and 49 more
### Community 0 (38 nodes)
- scripts_aggregate_dlp_events_py
- aggregate_dlp_events_bucket
- aggregate_dlp_events_awevent
- aggregate_dlp_events_psycopgconnection
- protocol
- ... and 33 more
### Community 5 (34 nodes)
- aw_ru_patch_isdlpsignalbucketroute
- aw_ru_patch_getdlphostfrombucketid
- aw_ru_patch_builddlpkey
- aw_ru_patch_loadbucketevents
- aw_ru_patch_serializerulematch
- ... and 29 more
### Community 4 (34 nodes)
- install_kit_awindows_20260427_211240_windows_email_outbound_collector_ps1
- email_outbound_collector_get_deploymentconfig
- email_outbound_collector_write_collectorlog
- email_outbound_collector_invoke_awjsonpost
- email_outbound_collector_ensure_bucket
- ... and 29 more
### Community 8 (28 nodes)
- aw_ru_patch_replacetext
- aw_ru_patch_walk
- aw_ru_patch_translateattributes
- aw_ru_patch_ishomeroute
- aw_ru_patch_getdefaulthostgroupsconfig
- ... and 23 more
### Community 9 (18 nodes)
- aw_ru_patch_getdlpbucketidfromhash
- aw_ru_patch_generatedlpid
- aw_ru_patch_awapijson
- aw_ru_patch_ensureawbucket
- aw_ru_patch_saveawheartbeat
- ... and 13 more
### Community 10 (14 nodes)
- install_kit_awindows_20260427_211240_windows_migrate_awatch_rus_paths_ps1
- migrate_awatch_rus_paths_copy_directorycontents
- migrate_awatch_rus_paths_copy_ifexists
- migrate_awatch_rus_paths_convert_pathvalue
- migrate_awatch_rus_paths_stop_awatchtaskset
- ... and 9 more
### Community 6 (12 nodes)
- grafana_1c_sql_exporter_collectors_aw_activitywatch_py
- aw_activitywatch_activitywatchexporter
- aw_activitywatch_activitywatchexporter_init
- aw_activitywatch_activitywatchexporter_get_buckets
- aw_activitywatch_activitywatchexporter_get_bucket_events
- ... and 7 more
## File Types
The graph was built from code files including:
- PowerShell scripts (.ps1)
- Python scripts (.py)
- JavaScript patches (.js)
- Configuration files
## Notes
- This is a structural (AST-based) graph showing code relationships
- No semantic extraction was performed (no docs/papers in corpus)
- Communities represent clusters of related functions and modules
-12
View File
@@ -1,12 +0,0 @@
{
"runs": [
{
"date": "2026-05-03T05:54:08.099209+00:00",
"input_tokens": 0,
"output_tokens": 0,
"files": 56
}
],
"total_input_tokens": 0,
"total_output_tokens": 0
}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
@@ -1,15 +1,15 @@
1b776081c24ad8413c2f3e24aff3952949e7786a108a08ef45121536bcae9482 install-kit-awindows-20260427-211240/README-INSTALL-KIT.txt
e973ad9aa3824a6588ce4ef1b80ce3caec0085434a2755f9b657f09fb7435632 install-kit-awindows-20260427-211240/ansible/README.md
856d2467afb4b413ae7833ba55340db01bd807f10d5200752b95cc113758c54e install-kit-awindows-20260427-211240/README-INSTALL-KIT.txt
556a9f7524b61309b00b641495b6daa212115411aa5a6fc82d1537658ac0e719 install-kit-awindows-20260427-211240/ansible/README.md
412bb766bbf0791c3593f38daa771d5d0aa58cc1f2d3c9010fcd4588d0fe87df install-kit-awindows-20260427-211240/ansible/deploy_aw_pfsense_poller.yml
ac091618a6793a9be9b52eeb78267068df16d4f57e0051b9d868813c4a641f35 install-kit-awindows-20260427-211240/ansible/deploy_aw_server.yml
cd09574fd0d55bf62d9d7df757bb206b5184ba9ffdcc200e755700e50cfa41f3 install-kit-awindows-20260427-211240/ansible/deploy_aw_windows.yml
d666eac9d94ad71842e21aaac5d23968a0c2213bb4edab899bf432d7ad417ddf install-kit-awindows-20260427-211240/ansible/group_vars/all.example.yml
a896676303be9a47ed6b0c8cc07deb5a5432aebc97231e801fda985121c539eb install-kit-awindows-20260427-211240/ansible/group_vars/pfsense-poller.example.yml
4b6f658adb98d548eedd10a0d44ff224b4d46a663d8c11e038f18597503f6c27 install-kit-awindows-20260427-211240/ansible/group_vars/all.example.yml
dbaa55e66c65bf7e4e943c8070e53d002d8a794ffcc0593d7a8a07a5f99aa306 install-kit-awindows-20260427-211240/ansible/group_vars/pfsense-poller.example.yml
c5cab36645065815571c99f6d360f910dcccbb54b780c8bfd526a6cdc3684e19 install-kit-awindows-20260427-211240/ansible/group_vars/proxmox-matrix.example.yml
35a33c8a1c75ded5e85c6b79e0b3efde07959ff61ee5f66d83b7e0c2abe87fc5 install-kit-awindows-20260427-211240/ansible/group_vars/proxmox.example.yml
9e4939d2d951870cacab6e42c5bf0ccd03350089dc0d32b9a681948ff96754d2 install-kit-awindows-20260427-211240/ansible/group_vars/windows.example.yml
7189b5205bd25313db54e5be027b0d066199e6ae34ad74be2095a1691adaf5e3 install-kit-awindows-20260427-211240/ansible/install_full_stack.yml
fea0574d7eb98ce24a1e7025afb9837c6241180095d21eaa74892225305d05a3 install-kit-awindows-20260427-211240/ansible/inventory.example.ini
1abe542724e617c285deaef76514d49c83c148ddbee90bc99b800e9049b70444 install-kit-awindows-20260427-211240/ansible/inventory.example.ini
3adda7422ffbbb76be50858f2f1ed6073b6bf9ee0b57283c41d0fabd3e7c7f9e install-kit-awindows-20260427-211240/ansible/provision_proxmox_ct_and_deploy_aw.yml
234932632092226526173b9ef906de2cce961bc95be0f37c878e48d9779e1de7 install-kit-awindows-20260427-211240/ansible/provision_proxmox_ct_matrix_and_deploy_aw.yml
a74a49371e889dc3ea404534a939f32f2dac940d8902d20770590951ab67d532 install-kit-awindows-20260427-211240/ansible/tasks/provision_ct_and_deploy_aw.yml
@@ -21,7 +21,7 @@ ba88cc284d047f521427ac038c266624a6fe8493ce3e79bc27c172a2e70ac54a install-kit-aw
509759461ce0918a2dc839832812cf5f4c77b1cea1e6ffdcab0146e02598df79 install-kit-awindows-20260427-211240/aw-server/aw-ru-patch.js
699f697143f6be588c698bad9a14a45c736fe74f5e4b0e0ea0f48b569c7df396 install-kit-awindows-20260427-211240/aw-server/aw-rus-healthd.service
8ae02b42f4bc33d95268624bae79c2101298b7ec6644553a1e81f7841dda74d8 install-kit-awindows-20260427-211240/aw-server/aw-rus-healthd.timer
28950acbfeed3f3e5729e0227fd96785dd840330ed9b94a3d6ab0a6a855ca5ec install-kit-awindows-20260427-211240/aw-server/aw-server.env.example
7580282be0a3bf057e42ca6f733a64bf0d2f51d096e02a57cde9125064ac04d1 install-kit-awindows-20260427-211240/aw-server/aw-server.env.example
18d038e67b926eca04bec725ed5e6de34b93f8330c3b30a0b07d52eab414bd03 install-kit-awindows-20260427-211240/aw-server/aw-slo-monitor.service
257cdc18f088e8848b1bee69e7f8b99aa860a0f600eebd74365a40ed94aa5ecb install-kit-awindows-20260427-211240/aw-server/aw-slo-monitor.timer
98c0bed353bbda0fa7a69df23f3b008cb0e8e70cdff6cc63330d4caf79fd3280 install-kit-awindows-20260427-211240/aw-server/aw-sw-cleanup.js
@@ -32,16 +32,13 @@ afbb4be301b4940ed9b7671be3441a48d53bee968d8870749442f81c6d066650 install-kit-aw
6de9b272ad732ad174c32398ab8baf5cc8c83be47efe0d6df46c3190b4010680 install-kit-awindows-20260427-211240/aw-server/install_aw_server.sh
aedffecfa24834968742cb2477faef80bf794345275a9679ac12c5a1f609acc2 install-kit-awindows-20260427-211240/aw-server/settings/classes-worktime.json
47c50054515506b72af2d6bca0ae959ca57861803e528991c230611e6a8893d6 install-kit-awindows-20260427-211240/aw-server/settings/views-default.json
4e5b23300ba5c9878b2c8ce6eea65043b7a4c5cb2d14619243cfca6d202aec9f install-kit-awindows-20260427-211240/scripts/aw-webui-browser-smoke.mjs
62980eeebe01d7da243be8535a48f5d41d4eead83cf94015df807111c3d920ab install-kit-awindows-20260427-211240/scripts/aw-webui-browser-smoke.sh
2e728f4632e6564355a580ea1718d41a660dc35595ac38d0ac7fe0dd308dae6a install-kit-awindows-20260427-211240/scripts/aw-webui-browser-smoke.mjs
76a24d19440676d447fac16e4a663f34c3f31d62166a6c326b5bd3754beac0eb install-kit-awindows-20260427-211240/scripts/aw-webui-browser-smoke.sh
6770275fac17607770653a522a64cf5ab31a7a11993b68e7e80a2858c3b8930e install-kit-awindows-20260427-211240/scripts/check_install_kit_vs_repo.sh
4e5bc6ce977e9f5b9e87c393061d5ecac0f90d5e1314e3325093692e5d19965e install-kit-awindows-20260427-211240/scripts/quality-gate.sh
db1a9b0ccd21aec78d8e2aa08dfa28368e5ba6209c57361e6824e85c1af9f6ca install-kit-awindows-20260427-211240/scripts/rebuild_install_kit.sh
38ad2e112796c2fa9bdc1cc2403c679bb896f90ae2b51d6ccc9a9ec103b4dea6 install-kit-awindows-20260427-211240/scripts/validate_install_kit.sh
0b49e6db51d5abcecaeee0b85f186efd4f10d3360cf04e8aea2e4c7d4465dbda install-kit-awindows-20260427-211240/scripts/verify_innosetup_installer.sh
dd2389e9cb199ed86d219120294fdaa64415cfbc683004d5f5db5d52aa758a92 install-kit-awindows-20260427-211240/server-configs-192.168.100.18/awatch-rus-admin.deployment-config.json
5279f9d677faed76a5f0248f9217ecc29eac977ab752552cab852f5b4b6715df install-kit-awindows-20260427-211240/server-configs-192.168.100.18/awatch-rus-u2u5.deployment-config.json
333fe336e51f9c69bd2559d18763da2b83df400fa374e540ed128ffb6765ab7e install-kit-awindows-20260427-211240/server-configs-192.168.100.18/awatch-rus-user1.deployment-config.json
e856d4b411b61dfc11e0a59b59026eff10972a47e7d8b28f6dfe367a2a5e192d install-kit-awindows-20260427-211240/windows/AWatchRusCollectorGuardService.cs
33aa34b89246d6c079ef9afe2f5cd153bd9d5946b69a175ff6fd678c77f61da5 install-kit-awindows-20260427-211240/windows/ActivityWatch.Windows.Common.psd1
6d5a7dd92619bbf972e17e455a7cda65b53c790f6f0ede47e1196246bfe8b1cf install-kit-awindows-20260427-211240/windows/ActivityWatch.Windows.Common.psm1
@@ -51,7 +48,7 @@ f4405a959a52e21185234463887a4fc09ea28e48d2412ac336f9715b46be9cb9 install-kit-aw
5bacbd48fdfc8d0d4479ba1af54cbbfe6057cc654409b385f487962576f4f1db install-kit-awindows-20260427-211240/windows/deploy-ensemble.ps1
6ab4c496220bb46f064cc927a64ea853526a2c814182a32f39b432be6b32fe89 install-kit-awindows-20260427-211240/windows/deploy-single-user.ps1
73f3328cde22798dafa645cdd78d648ccf6425d6577432ae8c95d24daa17dc94 install-kit-awindows-20260427-211240/windows/dlp-endpoint-signals-collector.ps1
161c0ee7e8aa6fa172bf10b6c83f208aa5c8d555b6e6008d1b0a5de6e45d2c9d install-kit-awindows-20260427-211240/windows/dlp-policy.example.json
b97dfbd94201c83f3edd87c7940b058bf85ac64794468b44ab3200dcb1bff3c3 install-kit-awindows-20260427-211240/windows/dlp-policy.example.json
0df53518a43bb1f0af7fdff5b44ba859e797090dd08680b239571d2e8a478d47 install-kit-awindows-20260427-211240/windows/dlp-policy.native-cross-os.example.json
863727465497b474d13d2270d443ff96ccb6076f90a5ce3eb270bdf8088e02dc install-kit-awindows-20260427-211240/windows/email-outbound-collector.ps1
2c0e7a96f32d546ce3ff8da2059259e6e5141c97cefc76bccae4c87c502f00cf install-kit-awindows-20260427-211240/windows/hardening-recovery.ps1
@@ -5,7 +5,10 @@ Includes:
- ansible/* (Windows and AW server playbooks, examples, inventory, tasks)
- aw-server/* (server installer, health orchestrator, RU patch loader, host groups, default settings)
- scripts/* (install-kit rebuild/validation, quality gates, browser/web smoke checks)
- server-configs-192.168.100.18/* (working Windows/RDP config snapshots)
Source:
- Local project snapshot at build time.
Customer-specific deployment configs, inventories, passwords, tokens, domains,
IP addresses and runtime snapshots are intentionally excluded from this public
install-kit.
@@ -248,7 +248,7 @@ Playbook:
- `telegram_allowed_chat_ids`
- `tsj_bot_source_local_path`
3. Убедитесь, что в inventory есть группа `[proxmox]`.
Для текущего контура AW-Rus bot ожидает Proxmox host `10.10.10.2`.
Для текущего контура AW-Rus bot ожидает Proxmox host `<GATEWAY_HOST>`.
Рабочая модель для этого контура: `igor` + `sudo`, а не обязательный `root` login.
4. При необходимости задайте recovery-команды для AW-Rus:
- `tsj_bot_aw_rus_worktime_heal_cmd`
@@ -13,21 +13,21 @@ aw_server_public_host: "{{ (hostvars[aw_server_inventory_host].ansible_host | de
aw_worktime_report_base: "http://{{ aw_server_public_host }}:5610"
aw_worktime_timezone: "Europe/Moscow"
aw_worktime_influx_enabled: false
aw_worktime_influx_url: "http://10.10.10.10:8086"
aw_worktime_influx_url: "http://<INFLUXDB_HOST>:8086"
aw_worktime_influx_org: "proxmox"
aw_worktime_influx_bucket: "aw_metrics"
aw_worktime_influx_hosts: "SHARKON2025"
aw_worktime_influx_days: "today,yesterday"
aw_worktime_influx_token: ""
aw_dlp_influx_enabled: false
aw_dlp_influx_url: "http://10.10.10.10:8086"
aw_dlp_influx_url: "http://<INFLUXDB_HOST>:8086"
aw_dlp_influx_org: "proxmox"
aw_dlp_influx_bucket: "aw_metrics"
aw_dlp_influx_hosts: "SHARKON2025"
aw_dlp_influx_lookback_days: 30
aw_dlp_influx_event_limit: 2000
aw_dlp_influx_token: ""
aw_monitored_windows_host: "192.168.100.18"
aw_monitored_windows_host: "<WINDOWS_HOST>"
aw_monitored_windows_hostname: "SHARKON2025"
aw_rus_health_worktime_api_base: "http://127.0.0.1:5610"
aw_rus_health_state_dir: "{{ aw_server_data_dir }}/health"
@@ -1,14 +1,14 @@
aw_pfsense_poller_config:
poll_interval_seconds: 60
aw:
server_host: "10.10.10.13"
server_host: "<AW_SERVER_HOST>"
server_port: 5600
hostname: "PFSENSE-EDGE01"
pulse_time_seconds: 120
timeout_seconds: 15
pfsense:
name: "pfSense Edge 01"
host: "10.10.10.1"
host: "<FIREWALL_HOST>"
scheme: "https"
verify_tls: false
timeout_seconds: 15
@@ -6,7 +6,7 @@ aw-ct ansible_host=10.20.30.13 ansible_user=root ansible_port=22
[aw_windows]
# Примечание: в русифицированных Windows часто нужен "Администратор", а не "Administrator".
win-node1 ansible_host=192.168.100.18 ansible_user=Администратор ansible_password=CHANGE_ME ansible_connection=winrm ansible_winrm_transport=ntlm ansible_port=5985 ansible_winrm_server_cert_validation=ignore
win-node1 ansible_host=<WINDOWS_HOST> ansible_user=Администратор ansible_password=CHANGE_ME ansible_connection=winrm ansible_winrm_transport=ntlm ansible_port=5985 ansible_winrm_server_cert_validation=ignore
[aw_pfsense_pollers]
# pfsense-poller1 ansible_host=192.168.100.30 ansible_user=root ansible_port=22
@@ -45,7 +45,7 @@ AW_EXPECT_START_OF_DAY=00:00
AW_EXPECT_ALWAYS_ACTIVE_PATTERN=aw-watcher-window
AW_EXPECT_LANDINGPAGE=/#/activity/SHARKON2025/view/
AW_HEALTH_STRICT_FILEOPS=0
AW_MONITORED_WINDOWS_HOST=192.168.100.18
AW_MONITORED_WINDOWS_HOST=<WINDOWS_HOST>
AW_MONITORED_WINDOWS_HOSTNAME=SHARKON2025
AW_RUS_HEALTH_WORKTIME_API=http://127.0.0.1:5610
AW_RUS_HEALTH_STATE_DIR=/var/lib/activitywatch/health
@@ -8,13 +8,14 @@ import { promisify } from "node:util";
const require = createRequire(import.meta.url);
const execFileAsync = promisify(execFile);
const homeDir = process.env.HOME || "";
function loadPlaywright() {
const candidates = [
"playwright",
"playwright-core",
process.env.PLAYWRIGHT_CORE_MODULE,
"/home/igor/.agents/skills/playwright/node_modules/playwright-core",
homeDir ? path.join(homeDir, ".agents/skills/playwright/node_modules/playwright-core") : "",
].filter(Boolean);
const errors = [];
for (const candidate of candidates) {
@@ -104,9 +105,9 @@ function commandInPath(name) {
function findChromiumExecutable(explicitPath) {
return firstExisting([
explicitPath,
"/home/igor/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome",
"/home/igor/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome",
"/home/igor/.cache/rod/browser/chromium-1321438/chrome",
homeDir ? path.join(homeDir, ".cache/ms-playwright/chromium-1217/chrome-linux64/chrome") : "",
homeDir ? path.join(homeDir, ".cache/ms-playwright/chromium-1208/chrome-linux64/chrome") : "",
homeDir ? path.join(homeDir, ".cache/rod/browser/chromium-1321438/chrome") : "",
commandInPath("chromium"),
commandInPath("chromium-browser"),
commandInPath("google-chrome"),
@@ -365,8 +366,8 @@ async function runPageCheckWithRetries(runOnce, spec, maxRetries) {
async function main() {
const requestedEngine = env("AW_BROWSER_SMOKE_ENGINE", "auto");
const playwright = requestedEngine === "chromium-cli" ? null : loadPlaywright();
const awBase = normalizeBase(env("AW_BROWSER_SMOKE_AW_BASE", env("AW_SMOKE_AW_SERVER", "http://10.10.10.13:5600")));
const worktimeBase = normalizeBase(env("AW_BROWSER_SMOKE_WORKTIME_BASE", env("AW_SMOKE_WORKTIME_API", "http://10.10.10.13:5610")));
const awBase = normalizeBase(env("AW_BROWSER_SMOKE_AW_BASE", env("AW_SMOKE_AW_SERVER", "http://127.0.0.1:5600")));
const worktimeBase = normalizeBase(env("AW_BROWSER_SMOKE_WORKTIME_BASE", env("AW_SMOKE_WORKTIME_API", "http://127.0.0.1:5610")));
const host = env("AW_BROWSER_SMOKE_HOST", env("AW_SMOKE_SOURCE_HOSTNAME", "SHARKON2025"));
const timeoutMs = Number(env("AW_BROWSER_SMOKE_TIMEOUT_MS", "20000"));
const settleMs = Number(env("AW_BROWSER_SMOKE_SETTLE_MS", "6000"));
@@ -16,8 +16,8 @@ for rust_bin in "${rust_candidates[@]}"; do
fi
done
if [[ -z "${NODE_PATH:-}" && -d /home/igor/.agents/skills/playwright/node_modules ]]; then
export NODE_PATH=/home/igor/.agents/skills/playwright/node_modules
if [[ -z "${NODE_PATH:-}" && -d "$HOME/.agents/skills/playwright/node_modules" ]]; then
export NODE_PATH="$HOME/.agents/skills/playwright/node_modules"
fi
exec node "$ROOT_DIR/scripts/aw-webui-browser-smoke.mjs" "$@"
@@ -1,58 +0,0 @@
{
"version": 1,
"generatedAtUtc": "2026-04-27T01:14:21.9184268Z",
"server": {
"host": "10.10.10.13",
"port": 5600,
"scheme": "http"
},
"paths": {
"installRoot": "C:\\Program Files\\AWatch-rus\\bin",
"stateRoot": "C:\\ProgramData\\AWatch-rus",
"logsRoot": "C:\\ProgramData\\AWatch-rus\\logs",
"collectorScript": "C:\\ProgramData\\AWatch-rus\\browser-domains-native-collector.ps1",
"endpointCollectorScript": "C:\\ProgramData\\AWatch-rus\\dlp-endpoint-signals-collector.ps1",
"emailCollectorScript": "C:\\ProgramData\\AWatch-rus\\email-outbound-collector.ps1",
"rulesPath": "C:\\ProgramData\\AWatch-rus\\web-category-rules.json",
"policyPath": "C:\\ProgramData\\AWatch-rus\\dlp-policy.json",
"launchScript": "C:\\ProgramData\\AWatch-rus\\launch-watchers.ps1",
"recoveryScript": "C:\\ProgramData\\AWatch-rus\\recovery-loop.ps1"
},
"collector": {
"pollSeconds": 5,
"pulseSeconds": 30
},
"collectors": {
"afkEnabled": true,
"windowEnabled": true
},
"logging": {
"localAgentLogsEnabled": false
},
"incidentCapture": {
"enabled": true,
"screenshotEnabled": true,
"artifactsRoot": "C:\\ProgramData\\AWatch-rus\\incident-artifacts"
},
"sessionEvents": {
"logonEnabled": true,
"bucketPrefix": "aw-session-events"
},
"recovery": {
"intervalSeconds": 180,
"taskName": "ActivityWatch Recovery"
},
"dlp": {
"incidentBucketPrefix": "aw-dlp-incidents",
"enabled": true
},
"package": {
"version": "v0.13.2"
},
"userTasks": [
{
"UserId": "SHARKON2025\\Администратор",
"LaunchTaskName": "ActivityWatch Launch [SHARKON2025_РђРґРјРёРЅРёСЃС_СЂР_С_РѕСЂ]"
}
]
}
@@ -1,70 +0,0 @@
{
"version": 1,
"generatedAtUtc": "2026-04-27T01:09:42.4193209Z",
"server": {
"host": "10.10.10.13",
"port": 5600,
"scheme": "http"
},
"paths": {
"installRoot": "C:\\Program Files\\AWatch-rus\\bin",
"stateRoot": "C:\\ProgramData\\AWatch-rus",
"logsRoot": "C:\\ProgramData\\AWatch-rus\\logs",
"collectorScript": "C:\\ProgramData\\AWatch-rus\\browser-domains-native-collector.ps1",
"endpointCollectorScript": "C:\\ProgramData\\AWatch-rus\\dlp-endpoint-signals-collector.ps1",
"emailCollectorScript": "C:\\ProgramData\\AWatch-rus\\email-outbound-collector.ps1",
"rulesPath": "C:\\ProgramData\\AWatch-rus\\web-category-rules.json",
"policyPath": "C:\\ProgramData\\AWatch-rus\\dlp-policy.json",
"launchScript": "C:\\ProgramData\\AWatch-rus\\launch-watchers.ps1",
"recoveryScript": "C:\\ProgramData\\AWatch-rus\\recovery-loop.ps1"
},
"collector": {
"pollSeconds": 5,
"pulseSeconds": 30
},
"collectors": {
"afkEnabled": true,
"windowEnabled": true
},
"logging": {
"localAgentLogsEnabled": false
},
"incidentCapture": {
"enabled": true,
"screenshotEnabled": true,
"artifactsRoot": "C:\\ProgramData\\AWatch-rus\\incident-artifacts"
},
"sessionEvents": {
"logonEnabled": true,
"bucketPrefix": "aw-session-events"
},
"recovery": {
"intervalSeconds": 180,
"taskName": "ActivityWatch Recovery"
},
"dlp": {
"incidentBucketPrefix": "aw-dlp-incidents",
"enabled": true
},
"package": {
"version": "v0.13.2"
},
"userTasks": [
{
"UserId": "SHARKON2025\\user2",
"LaunchTaskName": "ActivityWatch Launch [SHARKON2025_user2]"
},
{
"UserId": "SHARKON2025\\user3",
"LaunchTaskName": "ActivityWatch Launch [SHARKON2025_user3]"
},
{
"UserId": "SHARKON2025\\user4",
"LaunchTaskName": "ActivityWatch Launch [SHARKON2025_user4]"
},
{
"UserId": "SHARKON2025\\user5",
"LaunchTaskName": "ActivityWatch Launch [SHARKON2025_user5]"
}
]
}
@@ -1,58 +0,0 @@
{
"version": 1,
"generatedAtUtc": "2026-04-27T01:09:38.9519788Z",
"server": {
"host": "10.10.10.13",
"port": 5600,
"scheme": "http"
},
"paths": {
"installRoot": "C:\\Program Files\\AWatch-rus\\bin",
"stateRoot": "C:\\ProgramData\\AWatch-rus",
"logsRoot": "C:\\ProgramData\\AWatch-rus\\logs",
"collectorScript": "C:\\ProgramData\\AWatch-rus\\browser-domains-native-collector.ps1",
"endpointCollectorScript": "C:\\ProgramData\\AWatch-rus\\dlp-endpoint-signals-collector.ps1",
"emailCollectorScript": "C:\\ProgramData\\AWatch-rus\\email-outbound-collector.ps1",
"rulesPath": "C:\\ProgramData\\AWatch-rus\\web-category-rules.json",
"policyPath": "C:\\ProgramData\\AWatch-rus\\dlp-policy.json",
"launchScript": "C:\\ProgramData\\AWatch-rus\\launch-watchers.ps1",
"recoveryScript": "C:\\ProgramData\\AWatch-rus\\recovery-loop.ps1"
},
"collector": {
"pollSeconds": 5,
"pulseSeconds": 30
},
"collectors": {
"afkEnabled": true,
"windowEnabled": true
},
"logging": {
"localAgentLogsEnabled": false
},
"incidentCapture": {
"enabled": true,
"screenshotEnabled": true,
"artifactsRoot": "C:\\ProgramData\\AWatch-rus\\incident-artifacts"
},
"sessionEvents": {
"logonEnabled": true,
"bucketPrefix": "aw-session-events"
},
"recovery": {
"intervalSeconds": 180,
"taskName": "ActivityWatch Recovery"
},
"dlp": {
"incidentBucketPrefix": "aw-dlp-incidents",
"enabled": true
},
"package": {
"version": "v0.13.2"
},
"userTasks": [
{
"UserId": "SHARKON2025\\user1",
"LaunchTaskName": "ActivityWatch Launch [SHARKON2025_user1]"
}
]
}
@@ -116,7 +116,7 @@
},
"ioc": {
"enabled": true,
"source": "http://10.10.10.13:5610/dlp-ioc/ioc_blacklist.json",
"source": "http://aw-server.example.local:5610/dlp-ioc/ioc_blacklist.json",
"format": "hayabusa_sigma_v1",
"refreshMinutes": 360
}
+4
View File
@@ -0,0 +1,4 @@
*.env
*.local
!.gitignore
!*.example
@@ -1,4 +1,4 @@
# Copy to deploy.secrets.env and fill real values.
# Copy to deploy.env and fill real values.
PVE_NODE=pve-example
CT_ID=203
+2 -2
View File
@@ -898,7 +898,7 @@ class CodexExecSafetyTests(unittest.TestCase):
def test_codex_exec_does_not_forward_bearer_to_sudo(self):
bot = object.__new__(MODULE.TSJGuardianBot)
bot.ai_exec_user = "igor"
bot.ai_chat_workdir = "/home/igor"
bot.ai_chat_workdir = "~"
bot.ai_chat_sandbox = "workspace-write"
bot.codex_model = "gpt-test"
captured = {}
@@ -916,7 +916,7 @@ class CodexExecSafetyTests(unittest.TestCase):
self.assertEqual(rc, 1)
self.assertIn("401 Unauthorized", out)
self.assertEqual(reply, "")
self.assertEqual(captured["cwd"], "/home/igor")
self.assertEqual(captured["cwd"], "~")
self.assertEqual(captured["env_extra"], {})
self.assertNotIn("--preserve-env=PFSENSE_MCP_BEARER", captured["argv"])
self.assertNotIn("secret-token", " ".join(captured["argv"]))
+3 -3
View File
@@ -341,8 +341,8 @@ class TSJGuardianBot:
BTN_AI_CHAT_ALIASES = ("AI чат", "Чат с поддержкой", "Техподдержка", "Тех поддержка")
BTN_OVPN_CERTS_ALIASES = ("OpenVPN certs", "OpenVPN cert", "OpenVPN серты", "OpenVPN сертификат")
INFRA_ADMIN_ROOT = "/opt/infra-admin"
PFSENSE_ENV_PATH = "/home/igor/.config/tsj-bot/pfsense.env.readonly"
PFSENSE_INVENTORY_PATH = "/home/igor/.config/tsj-bot/inventory.md"
PFSENSE_ENV_PATH = "~/.config/tsj-bot/pfsense.env.readonly"
PFSENSE_INVENTORY_PATH = "~/.config/tsj-bot/inventory.md"
HUMAN_OPERATOR_STYLE = (
"Ты отвечаешь оператору как реальный инженер техподдержки проекта DetMir. "
@@ -468,7 +468,7 @@ class TSJGuardianBot:
self.fs_immediate_ai_on_critical = env_bool("FS_IMMEDIATE_AI_ON_CRITICAL", True)
self.ai_chat_enabled = env_bool("AI_CHAT_ENABLED", True)
self.ai_chat_timeout_sec = env_int("AI_CHAT_TIMEOUT_SEC", 1800)
self.ai_chat_workdir = os.getenv("AI_CHAT_WORKDIR", "/home/igor").strip()
self.ai_chat_workdir = os.getenv("AI_CHAT_WORKDIR", "~").strip()
self.ai_chat_sandbox = os.getenv("AI_CHAT_SANDBOX", "workspace-write").strip() or "workspace-write"
self.openvpn_cert_check_timeout_sec = max(30, env_int("OPENVPN_CERT_CHECK_TIMEOUT_SEC", 240))
self.openvpn_expiry_warn_timeout_sec = max(30, env_int("OPENVPN_EXPIRY_WARN_TIMEOUT_SEC", 120))
+1 -1
View File
@@ -5,7 +5,7 @@ HEARTBEAT_FILE="${HEARTBEAT_FILE:-/opt/infra-admin/.state/tsj_guardian_heartbeat
MAX_AGE_SEC="${MAX_AGE_SEC:-180}"
SERVICE_NAME="${SERVICE_NAME:-tsj-guardian-bot.service}"
GOST_SERVICE_NAME="${GOST_SERVICE_NAME:-gost-tg.service}"
GOST_DUP_PATTERN="${GOST_DUP_PATTERN:-/usr/local/bin/gost -L http+socks5://127.0.0.1:11090 -F socks5+wss://gw.iri1968.dpdns.org:4443}"
GOST_DUP_PATTERN="${GOST_DUP_PATTERN:-/usr/local/bin/gost -L http+socks5://127.0.0.1:11090 -F socks5+wss://gw.example.local:4443}"
dedupe_gost_instances() {
local main_pid
+1 -1
View File
@@ -5,7 +5,7 @@ set -uo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SMOKE_ENV_FILE="${AW_SMOKE_ENV_FILE:-}"
for env_candidate in "$REPO_ROOT/secrets/runtime.env" "$HOME/.config/aw-contour-smoke.env" "$SMOKE_ENV_FILE"; do
for env_candidate in "$REPO_ROOT/private-config/runtime.env" "$HOME/.config/aw-contour-smoke.env" "$SMOKE_ENV_FILE"; do
if [ -n "$env_candidate" ] && [ -f "$env_candidate" ]; then
# Load local credentials and site-specific overrides without committing them.
# Later files override earlier defaults.
+7 -6
View File
@@ -8,13 +8,14 @@ import { promisify } from "node:util";
const require = createRequire(import.meta.url);
const execFileAsync = promisify(execFile);
const homeDir = process.env.HOME || "";
function loadPlaywright() {
const candidates = [
"playwright",
"playwright-core",
process.env.PLAYWRIGHT_CORE_MODULE,
"/home/igor/.agents/skills/playwright/node_modules/playwright-core",
homeDir ? path.join(homeDir, ".agents/skills/playwright/node_modules/playwright-core") : "",
].filter(Boolean);
const errors = [];
for (const candidate of candidates) {
@@ -104,9 +105,9 @@ function commandInPath(name) {
function findChromiumExecutable(explicitPath) {
return firstExisting([
explicitPath,
"/home/igor/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome",
"/home/igor/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome",
"/home/igor/.cache/rod/browser/chromium-1321438/chrome",
homeDir ? path.join(homeDir, ".cache/ms-playwright/chromium-1217/chrome-linux64/chrome") : "",
homeDir ? path.join(homeDir, ".cache/ms-playwright/chromium-1208/chrome-linux64/chrome") : "",
homeDir ? path.join(homeDir, ".cache/rod/browser/chromium-1321438/chrome") : "",
commandInPath("chromium"),
commandInPath("chromium-browser"),
commandInPath("google-chrome"),
@@ -365,8 +366,8 @@ async function runPageCheckWithRetries(runOnce, spec, maxRetries) {
async function main() {
const requestedEngine = env("AW_BROWSER_SMOKE_ENGINE", "auto");
const playwright = requestedEngine === "chromium-cli" ? null : loadPlaywright();
const awBase = normalizeBase(env("AW_BROWSER_SMOKE_AW_BASE", env("AW_SMOKE_AW_SERVER", "http://10.10.10.13:5600")));
const worktimeBase = normalizeBase(env("AW_BROWSER_SMOKE_WORKTIME_BASE", env("AW_SMOKE_WORKTIME_API", "http://10.10.10.13:5610")));
const awBase = normalizeBase(env("AW_BROWSER_SMOKE_AW_BASE", env("AW_SMOKE_AW_SERVER", "http://127.0.0.1:5600")));
const worktimeBase = normalizeBase(env("AW_BROWSER_SMOKE_WORKTIME_BASE", env("AW_SMOKE_WORKTIME_API", "http://127.0.0.1:5610")));
const host = env("AW_BROWSER_SMOKE_HOST", env("AW_SMOKE_SOURCE_HOSTNAME", "SHARKON2025"));
const timeoutMs = Number(env("AW_BROWSER_SMOKE_TIMEOUT_MS", "20000"));
const settleMs = Number(env("AW_BROWSER_SMOKE_SETTLE_MS", "6000"));

Some files were not shown because too many files have changed in this diff Show More