standkit 0.7.0__tar.gz → 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {standkit-0.7.0/standkit.egg-info → standkit-0.8.0}/PKG-INFO +15 -10
- {standkit-0.7.0 → standkit-0.8.0}/README.md +14 -9
- {standkit-0.7.0 → standkit-0.8.0}/docs/BACKLOG.md +14 -4
- {standkit-0.7.0 → standkit-0.8.0}/docs/CHANGELOG.md +158 -0
- standkit-0.8.0/docs/COOKBOOK_LINUX.md +1199 -0
- standkit-0.8.0/docs/GAPs/GAP-001-registry-fields-out-of-hub-form.md +70 -0
- standkit-0.8.0/docs/GAPs/GAP-002-http-probe-down-not-explained.md +72 -0
- standkit-0.8.0/docs/GAPs/GAP-003-redis-endpoint-in-extra.md +79 -0
- standkit-0.8.0/docs/GAPs/GAP-004-cookbook-hub-register-form.md +81 -0
- standkit-0.8.0/docs/GAPs/GAP-005-cookbook-hub-side-secrets.md +68 -0
- standkit-0.8.0/docs/GAPs/GAP-006-log-dir-case-and-separator.md +101 -0
- standkit-0.8.0/docs/GAPs/GAP-007-agent-paths-raw-traceback.md +92 -0
- standkit-0.8.0/docs/GAPs/GAP-008-agent-cert-trust-on-hub.md +80 -0
- standkit-0.8.0/docs/GAPs/README.md +57 -0
- {standkit-0.7.0 → standkit-0.8.0}/docs/HOSTING.md +2 -1
- standkit-0.8.0/docs/README.md +65 -0
- {standkit-0.7.0 → standkit-0.8.0}/docs/REMOTE_STANDS.md +7 -1
- {standkit-0.7.0 → standkit-0.8.0}/docs/ROADMAP.md +2 -1
- standkit-0.8.0/docs/research/companion-v2-cicd-thin-agent.md +101 -0
- {standkit-0.7.0 → standkit-0.8.0}/projects.sample.json +12 -0
- {standkit-0.7.0 → standkit-0.8.0}/pyproject.toml +1 -1
- {standkit-0.7.0 → standkit-0.8.0}/standkit/__init__.py +1 -1
- standkit-0.8.0/standkit/health.py +556 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit/hosting.py +11 -5
- {standkit-0.7.0 → standkit-0.8.0}/standkit/logs.py +177 -1
- {standkit-0.7.0 → standkit-0.8.0}/standkit/models.py +113 -1
- {standkit-0.7.0 → standkit-0.8.0/standkit.egg-info}/PKG-INFO +15 -10
- {standkit-0.7.0 → standkit-0.8.0}/standkit.egg-info/SOURCES.txt +14 -0
- standkit-0.8.0/standkit_agent/__main__.py +487 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_agent/server.py +75 -1
- standkit-0.8.0/standkit_hub/client.py +411 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/logs_browser.py +128 -21
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/server.py +69 -7
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/app.js +82 -7
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/cookbook.html +866 -175
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/index.html +69 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/style.css +30 -0
- standkit-0.8.0/tests/test_agent_startup_preflight.py +842 -0
- standkit-0.8.0/tests/test_health.py +728 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hosting.py +69 -0
- standkit-0.8.0/tests/test_hub_client_tls.py +403 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_logs_browser.py +209 -1
- standkit-0.8.0/tests/test_hub_register.py +597 -0
- standkit-0.8.0/tests/test_logs.py +490 -0
- standkit-0.8.0/tests/test_models.py +477 -0
- standkit-0.7.0/standkit/health.py +0 -267
- standkit-0.7.0/standkit_agent/__main__.py +0 -192
- standkit-0.7.0/standkit_hub/client.py +0 -225
- standkit-0.7.0/tests/test_health.py +0 -319
- standkit-0.7.0/tests/test_hub_register.py +0 -298
- standkit-0.7.0/tests/test_logs.py +0 -220
- standkit-0.7.0/tests/test_models.py +0 -258
- {standkit-0.7.0 → standkit-0.8.0}/LICENSE +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/MANIFEST.in +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/SECURITY.md +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/docs/ARCHITECTURE.md +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/docs/adr/0001-hosting-backends.md +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/docs/adr/0002-k8s-backend.md +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/docs/adr/0003-remote-log-browsing.md +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/docs/adr/0004-iis-site-scoped-lifecycle.md +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/setup.cfg +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit/adopt.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit/lifecycle.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit/platform.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit/registry.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit/secrets.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit.egg-info/dependency_links.txt +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit.egg-info/entry_points.txt +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit.egg-info/requires.txt +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit.egg-info/top_level.txt +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_agent/__init__.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_agent/audit.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_agent/security.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/__init__.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/__main__.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/agent_control.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/assets/bpmkit-icon.ico +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/assets/icon.png +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/config.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/poller.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/redis_min.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/security.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/shortcut.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/bpmkit-logo-dark.svg +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/bpmkit-logo.svg +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/favicon.png +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/favicon.svg +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/standkit_hub/web/manifest.webmanifest +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_adopt.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_agent_security.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_agent_server_integration.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_agent_control.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_config.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_fast_paint.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_pwa_and_compact.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_redis_min.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_server.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_shortcut.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_hub_single_instance.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_lifecycle.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_no_window.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_registry.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_registry_resolver.py +0 -0
- {standkit-0.7.0 → standkit-0.8.0}/tests/test_secrets.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: standkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Свободное ядро (MIT) для управления жизненным циклом локальных и удалённых стендов BPMSoft: headless start/stop/restart, health-пробы, логи, реестр стендов. Часть экосистемы BPMkit.
|
|
5
5
|
Author: standkit contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -120,8 +120,9 @@ TLS, TLS 1.2+/mTLS, скоупы control/readonly, lockout по IP, аудит.
|
|
|
120
120
|
pip install standkit
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
Обновление — `pip install -U standkit`.
|
|
124
|
-
|
|
123
|
+
Обновление — `pip install -U standkit`. Конкретная версия (в том числе откат) —
|
|
124
|
+
`pip install "standkit==0.6.1"`; полный список выпусков — на
|
|
125
|
+
[PyPI](https://pypi.org/project/standkit/).
|
|
125
126
|
|
|
126
127
|
Запуск дашборда:
|
|
127
128
|
|
|
@@ -146,14 +147,18 @@ BPMkitStand использует тот же реестр, что и MCP BPMkit
|
|
|
146
147
|
|
|
147
148
|
## Документация проекта
|
|
148
149
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
- [docs/CHANGELOG.md](docs/CHANGELOG.md) — история изменений по версиям.
|
|
152
|
-
- [docs/BACKLOG.md](docs/BACKLOG.md) — честный список «упомянуто в коде, но не реализовано» (заделы/заглушки) со ссылками на код.
|
|
153
|
-
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) · [docs/HOSTING.md](docs/HOSTING.md) · [docs/REMOTE_STANDS.md](docs/REMOTE_STANDS.md) · [SECURITY.md](SECURITY.md)
|
|
154
|
-
- Решения (ADR): [0001 — hosting backends](docs/adr/0001-hosting-backends.md) · [0002 — k8s backend](docs/adr/0002-k8s-backend.md) · [0003 — браузинг логов удалённых стендов (предложено)](docs/adr/0003-remote-log-browsing.md) · [0004 — IIS: жизненный цикл по Site](docs/adr/0004-iis-site-scoped-lifecycle.md)
|
|
150
|
+
**Карта всех документов — [docs/README.md](docs/README.md)**: кому, о чём и когда открывать.
|
|
151
|
+
Коротко:
|
|
155
152
|
|
|
156
|
-
|
|
153
|
+
| Документ | Для кого |
|
|
154
|
+
|---|---|
|
|
155
|
+
| [**Кукбук**](standkit_hub/web/cookbook.html) — обзор, установка, дашборд, реестр, хостинг, агент, безопасность, траблшутинг. Один standalone-файл: в работающем диспетчере открывается кнопкой «?» в шапке, без него — прямо с диска в браузере | оператор |
|
|
156
|
+
| [docs/COOKBOOK_LINUX.md](docs/COOKBOOK_LINUX.md) — пошаговое развёртывание агента на Linux: pipx/venv, реестр, секреты, systemd, TLS/mTLS, разбор типичных ошибок с реальными сообщениями | администратор |
|
|
157
|
+
| [docs/REMOTE_STANDS.md](docs/REMOTE_STANDS.md) · [docs/HOSTING.md](docs/HOSTING.md) · [SECURITY.md](SECURITY.md) | оператор / администратор |
|
|
158
|
+
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) · [docs/adr/](docs/adr/) · [docs/CHANGELOG.md](docs/CHANGELOG.md) | разработчик |
|
|
159
|
+
| [docs/ROADMAP.md](docs/ROADMAP.md) — крупные работы · [docs/BACKLOG.md](docs/BACKLOG.md) — заглушки и заделы в коде · [docs/GAPs/](docs/GAPs/README.md) — код прав, а сценарий оператора ломается | планирование |
|
|
160
|
+
|
|
161
|
+
> Статус: `standkit` — молодой проект (0.8.x). Ядро/агент/хаб работоспособны, но
|
|
157
162
|
> ряд возможностей — это **каркас/заделы** (например, глубокие пробы БД/Redis,
|
|
158
163
|
> транспорты ssh/winrm, живая приёмка Docker/k8s/IIS). Что именно ещё не
|
|
159
164
|
> дописано — прозрачно перечислено в [docs/BACKLOG.md](docs/BACKLOG.md).
|
|
@@ -96,8 +96,9 @@ TLS, TLS 1.2+/mTLS, скоупы control/readonly, lockout по IP, аудит.
|
|
|
96
96
|
pip install standkit
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
Обновление — `pip install -U standkit`.
|
|
100
|
-
|
|
99
|
+
Обновление — `pip install -U standkit`. Конкретная версия (в том числе откат) —
|
|
100
|
+
`pip install "standkit==0.6.1"`; полный список выпусков — на
|
|
101
|
+
[PyPI](https://pypi.org/project/standkit/).
|
|
101
102
|
|
|
102
103
|
Запуск дашборда:
|
|
103
104
|
|
|
@@ -122,14 +123,18 @@ BPMkitStand использует тот же реестр, что и MCP BPMkit
|
|
|
122
123
|
|
|
123
124
|
## Документация проекта
|
|
124
125
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
- [docs/CHANGELOG.md](docs/CHANGELOG.md) — история изменений по версиям.
|
|
128
|
-
- [docs/BACKLOG.md](docs/BACKLOG.md) — честный список «упомянуто в коде, но не реализовано» (заделы/заглушки) со ссылками на код.
|
|
129
|
-
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) · [docs/HOSTING.md](docs/HOSTING.md) · [docs/REMOTE_STANDS.md](docs/REMOTE_STANDS.md) · [SECURITY.md](SECURITY.md)
|
|
130
|
-
- Решения (ADR): [0001 — hosting backends](docs/adr/0001-hosting-backends.md) · [0002 — k8s backend](docs/adr/0002-k8s-backend.md) · [0003 — браузинг логов удалённых стендов (предложено)](docs/adr/0003-remote-log-browsing.md) · [0004 — IIS: жизненный цикл по Site](docs/adr/0004-iis-site-scoped-lifecycle.md)
|
|
126
|
+
**Карта всех документов — [docs/README.md](docs/README.md)**: кому, о чём и когда открывать.
|
|
127
|
+
Коротко:
|
|
131
128
|
|
|
132
|
-
|
|
129
|
+
| Документ | Для кого |
|
|
130
|
+
|---|---|
|
|
131
|
+
| [**Кукбук**](standkit_hub/web/cookbook.html) — обзор, установка, дашборд, реестр, хостинг, агент, безопасность, траблшутинг. Один standalone-файл: в работающем диспетчере открывается кнопкой «?» в шапке, без него — прямо с диска в браузере | оператор |
|
|
132
|
+
| [docs/COOKBOOK_LINUX.md](docs/COOKBOOK_LINUX.md) — пошаговое развёртывание агента на Linux: pipx/venv, реестр, секреты, systemd, TLS/mTLS, разбор типичных ошибок с реальными сообщениями | администратор |
|
|
133
|
+
| [docs/REMOTE_STANDS.md](docs/REMOTE_STANDS.md) · [docs/HOSTING.md](docs/HOSTING.md) · [SECURITY.md](SECURITY.md) | оператор / администратор |
|
|
134
|
+
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) · [docs/adr/](docs/adr/) · [docs/CHANGELOG.md](docs/CHANGELOG.md) | разработчик |
|
|
135
|
+
| [docs/ROADMAP.md](docs/ROADMAP.md) — крупные работы · [docs/BACKLOG.md](docs/BACKLOG.md) — заглушки и заделы в коде · [docs/GAPs/](docs/GAPs/README.md) — код прав, а сценарий оператора ломается | планирование |
|
|
136
|
+
|
|
137
|
+
> Статус: `standkit` — молодой проект (0.8.x). Ядро/агент/хаб работоспособны, но
|
|
133
138
|
> ряд возможностей — это **каркас/заделы** (например, глубокие пробы БД/Redis,
|
|
134
139
|
> транспорты ssh/winrm, живая приёмка Docker/k8s/IIS). Что именно ещё не
|
|
135
140
|
> дописано — прозрачно перечислено в [docs/BACKLOG.md](docs/BACKLOG.md).
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
поведения за ним нет (или оно возвращает заглушку).
|
|
10
10
|
|
|
11
11
|
Порядок дорожной карты — см. [ROADMAP.md](ROADMAP.md). Остаточная безопасность
|
|
12
|
-
агента — `SECURITY.md` §6.
|
|
12
|
+
агента — `SECURITY.md` §6. Отдельный список **гэпов** (код работает как задумано,
|
|
13
|
+
но сценарий оператора всё равно ломается: настройка недоступна, отказ не объяснён,
|
|
14
|
+
рецепт не описан) — [GAPs/](GAPs/README.md).
|
|
13
15
|
|
|
14
16
|
## Транспорты подключения к стенду
|
|
15
17
|
|
|
@@ -28,11 +30,19 @@
|
|
|
28
30
|
|------|--------|-----------------|
|
|
29
31
|
| Глубокая проба БД (`SELECT 1` через psycopg2/pyodbc) | заглушка, всегда `SKIPPED`; флаг `deep_db` из хаба не передаётся | `standkit/health.py::db_deep_check`, параметр `check_stand(deep_db=…)` |
|
|
30
32
|
| Глубокая проба Redis (`PING` через redis-py) | заглушка, всегда `SKIPPED` | `standkit/health.py::redis_deep_check`, `check_stand(deep_redis=…)` |
|
|
31
|
-
| `stand_scheme` / `verify_tls` в форме регистрации дашборда | поля есть в реестре и в пробе, но форма регистрации построена по фиксированному белому списку полей — задать схему можно только правкой `projects.json` | `standkit_hub/server.py::_REGISTER_ALLOWED_FIELDS`, `standkit_hub/web/app.js::_REGISTER_FIELD_NAMES` |
|
|
32
33
|
| `last_deploy` (состояние последнего деплоя) | всегда `UNKNOWN`, источник данных не определён, в UI не выводится | `standkit/health.py::check_stand` (комментарий `last_deploy`), `standkit/models.py::StandStatus.last_deploy` |
|
|
33
34
|
|
|
34
35
|
Рабочие пробы (без заглушек): процесс (pid/бэкенд), HTTP, БД/Redis по **открытому
|
|
35
|
-
TCP-порту** — их достаточно для дашборда.
|
|
36
|
+
TCP-порту** — их достаточно для дашборда. Причина отказа HTTP-пробы и состояние
|
|
37
|
+
Redis теперь объясняются словами (`details['http_reason']` / `['redis_reason']`),
|
|
38
|
+
а не только цветом.
|
|
39
|
+
|
|
40
|
+
**Снято отсюда в 0.8.0** (было в этом разделе, закрыто — см. [GAPs/](GAPs/README.md)):
|
|
41
|
+
`stand_scheme`/`verify_tls` и `redis_host`/`redis_port` в форме регистрации
|
|
42
|
+
([GAP-001](GAPs/GAP-001-registry-fields-out-of-hub-form.md),
|
|
43
|
+
[GAP-003](GAPs/GAP-003-redis-endpoint-in-extra.md)), причина отказа HTTP-пробы
|
|
44
|
+
([GAP-002](GAPs/GAP-002-http-probe-down-not-explained.md)), регистр имени
|
|
45
|
+
каталога логов ([GAP-006](GAPs/GAP-006-log-dir-case-and-separator.md)).
|
|
36
46
|
|
|
37
47
|
## Жизненный цикл (kestrel)
|
|
38
48
|
|
|
@@ -77,7 +87,7 @@ TCP-порту** — их достаточно для дашборда.
|
|
|
77
87
|
|
|
78
88
|
| Пункт | Статус |
|
|
79
89
|
|------|--------|
|
|
80
|
-
| **Агент на Linux** | **первая живая установка 18.08.2026** — Ubuntu 24.04
|
|
90
|
+
| **Агент на Linux** | **первая живая установка 18.08.2026** — Ubuntu 24.04, стенд в Docker за self-signed HTTPS: установка через pipx, регистрация стенда из Python (`Registry.add_existing`), секреты через `STANDKIT_SECRET__*`, служба systemd, проверка API токеном. Вскрыла: жёсткую схему `http://` в HTTP-пробе (строка выше), отсутствие CLI регистрации (строка выше) и набор типовых ошибок оператора (PEP 668, забытый префикс секрета, владелец `agent.env`, `stand_host=0.0.0.0`, чтение реестра только при старте) — всё разобрано в кукбуке |
|
|
81
91
|
| **Docker** бэкенд (одиночный контейнер + compose) | **живая приёмка проведена 17.08.2026** на Docker Engine 29.6.1: 50 проверок основного цикла (start/stop/restart по фактическому `State.StartedAt`, логи, health, идемпотентность, негативы, работа без `docker` в PATH) + 6 проверок граничных состояний (paused, crash-loop, exited, подстрочные имена сервисов, кириллица в логах). Вскрыла два ложных «стенд жив» — исправлены в этой же ветке (см. CHANGELOG) |
|
|
82
92
|
| **k8s** бэкенд | **живая приёмка проведена 17.08.2026** на кластере k3s 1.30 (k3d): 28 проверок — scale/rollout restart с проверкой пересоздания подов, `readyReplicas`, `k8s_replicas`, логи, NodePort-проба, негативы по деплойменту/namespace/контексту/PATH. Вскрыла ложное «жив» при нуле реплик — исправлено |
|
|
83
93
|
| **IIS** бэкенд | **живая приёмка проведена 17.08.2026** на настоящем стенде BPMSoft 1.9.1.2 (.NET Framework + PostgreSQL) в IIS 10 / .NET Framework 4.8: сайт `iis19` (порт 5081) + вложенное приложение `/0` + сайт-сосед на ТОМ ЖЕ пуле; 66 живых проверок (окружение и автодетект 13, жизненный цикл site-scoped 17, `w3wp` 7, логи 4, отсутствие elevation 10 + 4 кросс-платформенных, ручки хаба 6, граничные состояния канала управления 5). Вскрыла 4 дефекта (пул при автодетекте, `state:Unknown`, ложный диагноз «нет прав», логи в подпапках-датах) — исправлены в этой же ветке, см. CHANGELOG |
|
|
@@ -3,6 +3,163 @@
|
|
|
3
3
|
Формат — [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/); версии —
|
|
4
4
|
[SemVer](https://semver.org/lang/ru/). Даты — 2026 год.
|
|
5
5
|
|
|
6
|
+
## [0.8.0] — 2026-08-18
|
|
7
|
+
|
|
8
|
+
> ⚙️ **Требуется действие оператора.** Ничего не ломается при обновлении, но
|
|
9
|
+
> часть улучшений включается полями реестра: `agent_ca` (доверие сертификату
|
|
10
|
+
> агента), `logs_dir` (нестандартный каталог логов), `redis_host`/`redis_port`
|
|
11
|
+
> (адрес Redis). Все они теперь задаются из формы «Зарегистрировать стенд» —
|
|
12
|
+
> править `projects.json` руками не нужно.
|
|
13
|
+
|
|
14
|
+
### Добавлено
|
|
15
|
+
|
|
16
|
+
- **Форма «Зарегистрировать стенд» перестала быть уже модели.** В белые списки
|
|
17
|
+
полей (`standkit_hub/web/app.js::_REGISTER_FIELD_NAMES` и
|
|
18
|
+
`standkit_hub/server.py::_REGISTER_ALLOWED_FIELDS`) и в разметку добавлены
|
|
19
|
+
`stand_scheme`, `verify_tls`, `redis_host`, `redis_port`, `logs_dir`,
|
|
20
|
+
`agent_ca`, `agent_verify_tls`. Чекбокс «Проверять сертификат» виден только
|
|
21
|
+
при схеме `https`; поля скрытого условного блока на сервер не уходят вовсе, а
|
|
22
|
+
булев чекбокс отправляется настоящим `true`/`false` — раньше «выключено»
|
|
23
|
+
приезжало как отсутствующее поле и молча давало дефолт `true`
|
|
24
|
+
([GAP-001](GAPs/GAP-001-registry-fields-out-of-hub-form.md)).
|
|
25
|
+
- **Причина отказа HTTP-пробы.** `standkit/health.py` получил `http_probe()` и
|
|
26
|
+
`HttpProbeResult`; распознаются отказ соединения, таймаут, DNS, ошибка
|
|
27
|
+
TLS-рукопожатия, непрошедший проверку сертификат, 5xx и «ответ не по
|
|
28
|
+
протоколу HTTP». Диагноз с фактическим URL кладётся в
|
|
29
|
+
`StandStatus.details["http_reason"]` — по образцу `process_reason` — и
|
|
30
|
+
показывается подсказкой к ячейке HTTP в дашборде (пунктирное подчёркивание =
|
|
31
|
+
причина есть). Для самого частого случая выдаётся рецепт: «похоже, стенд за
|
|
32
|
+
TLS: задайте `stand_scheme=https` (и `verify_tls=false` для self-signed)».
|
|
33
|
+
Автодетект схемы сознательно не делался — разбор в
|
|
34
|
+
[GAP-002](GAPs/GAP-002-http-probe-down-not-explained.md).
|
|
35
|
+
- **`redis_host` / `redis_port` — поля модели `Stand`**, а не нетипизированные
|
|
36
|
+
ключи `extra`. Пара валидируется целиком (половина пары — явная ошибка, а не
|
|
37
|
+
молчаливый `unknown`), поля есть в форме и в `projects.sample.json`. В
|
|
38
|
+
дашборде различаются «адрес Redis не задан в реестре» и «Redis не отвечает на
|
|
39
|
+
…» ([GAP-003](GAPs/GAP-003-redis-endpoint-in-extra.md)).
|
|
40
|
+
- **`agent_ca` / `agent_verify_tls` — доверие сертификату агента со стороны
|
|
41
|
+
хаба.** `standkit_hub/client.py` строит SSL-контекст явно
|
|
42
|
+
(`ssl.create_default_context(cafile=…)`), снятие проверки действует только
|
|
43
|
+
для `https://`-адресов. Самоподписанный сертификат агента больше не требует
|
|
44
|
+
`SSL_CERT_FILE`, заданной до старта хаба
|
|
45
|
+
([GAP-008](GAPs/GAP-008-agent-cert-trust-on-hub.md)).
|
|
46
|
+
- **`logs_dir`** — явное указание каталога логов стенда в реестре, для
|
|
47
|
+
нестандартной раскладки ([GAP-006](GAPs/GAP-006-log-dir-case-and-separator.md)).
|
|
48
|
+
- **Preflight путей у агента.** `standkit_agent` проверяет доступность
|
|
49
|
+
`run_dir`, `log_dir` и файла аудита **до** печати «слушаю …» и до открытия
|
|
50
|
+
сокета. Шаблон `standkit-agent.service` задаёт все три пути явно и объясняет
|
|
51
|
+
комментарием, почему это обязательно для сервисного аккаунта, созданного с
|
|
52
|
+
`--no-create-home` ([GAP-007](GAPs/GAP-007-agent-paths-raw-traceback.md)).
|
|
53
|
+
- **[docs/README.md](README.md) — карта документации:** кому какой документ, чем
|
|
54
|
+
различаются ROADMAP / BACKLOG / GAPs и куда заводить новую находку.
|
|
55
|
+
- **`docs/COOKBOOK_LINUX.md` — кукбук развёртывания агента на Linux.** Пошагово:
|
|
56
|
+
PEP 668 и установка через pipx / venv в `/opt`, реестр по явному пути,
|
|
57
|
+
секреты в файле окружения, первый запуск, проверка API, служба systemd с
|
|
58
|
+
выделенным сервисным аккаунтом, TLS и mTLS, сетевой периметр, эксплуатация
|
|
59
|
+
(ротация токена, lockout, смена порта контейнера, аудит). Все команды и все
|
|
60
|
+
сообщения об ошибках сняты с живого прогона на Ubuntu 24.04, а не составлены
|
|
61
|
+
по памяти. Отдельные разделы — таблица типичных проблем, клиент на Windows
|
|
62
|
+
(`curl.exe` / `Invoke-RestMethod`) и чек-лист приёмки.
|
|
63
|
+
- **Кукбук дополнен разделом «Подключение из дашборда оператора»** по итогам
|
|
64
|
+
живой проверки контура между машинами (дашборд на Windows ↔ агент на Linux):
|
|
65
|
+
запись реестра оператора с `transport=agent`, токен на стороне оператора,
|
|
66
|
+
доверие сертификату агента и подтверждённая обратная совместимость хаба 0.6.1
|
|
67
|
+
с агентом 0.7.0.
|
|
68
|
+
- **`docs/research/companion-v2-cicd-thin-agent.md` — заявка на трек
|
|
69
|
+
исследования** «CI/CD через тонкого агента»: что уже даёт текущий контракт
|
|
70
|
+
агента, три варианта границы бесплатного и платного слоя, список того, что
|
|
71
|
+
придётся спроектировать (долгие операции, идемпотентность, доставка
|
|
72
|
+
артефакта, версия стенда, откат, права), риски и порядок дешёвых проверок.
|
|
73
|
+
Решения не приняты — документ фиксирует развилки.
|
|
74
|
+
- **`docs/GAPs/` — реестр гэпов.** Отдельный от бэклога список случаев, где код
|
|
75
|
+
работает по спецификации, а сценарий оператора всё равно ломается: настройку
|
|
76
|
+
негде задать, отказ не объяснён, рецепт не описан. Заведены восемь пунктов по
|
|
77
|
+
итогам живой приёмки 18.08.2026 — и **все восемь закрыты в этом же выпуске**;
|
|
78
|
+
файлы оставлены с разделом «Как закрыт».
|
|
79
|
+
|
|
80
|
+
### Исправлено
|
|
81
|
+
|
|
82
|
+
- **Каталог логов не находился на Linux.** Имя подкаталога искалось жёсткой
|
|
83
|
+
строкой `"logs"`, а BPMSoft раскладывает логи в `Logs`; на Windows это годами
|
|
84
|
+
прощала регистронезависимая ФС. Резолв вынесен в
|
|
85
|
+
`standkit/logs.py::find_logs_subdir` / `stand_logs_dir`: сравнение по
|
|
86
|
+
`casefold()` через `os.scandir`, точное совпадение регистра в приоритете,
|
|
87
|
+
никакой жёсткой замены `"logs"` → `"Logs"`. Общей функцией пользуются и хаб,
|
|
88
|
+
и `IisBackend.read_logs`. Фиксы Windows/IIS — подпапки-даты,
|
|
89
|
+
`iis_stdout_log_dir`, рекурсивный обход — не тронуты
|
|
90
|
+
([GAP-006](GAPs/GAP-006-log-dir-case-and-separator.md)).
|
|
91
|
+
- **Пути POSIX-стендов больше не показываются с обратными слэшами.** Путь
|
|
92
|
+
удалённого стенда собирался `pathlib.Path` на Windows-хабе, и в сообщение
|
|
93
|
+
уезжало `\mnt\composers\…` — теперь для POSIX-путей используется
|
|
94
|
+
`PurePosixPath`.
|
|
95
|
+
- **Для `transport=agent` хаб не врёт «каталог не найден».** Каталог логов
|
|
96
|
+
живёт на файловой системе хоста стенда, локальная проверка о нём ничего не
|
|
97
|
+
знает — сообщение говорит это прямо (`logs_unavailable_reason`).
|
|
98
|
+
- **`BadStatusLine` больше не вылетает из HTTP-пробы наружу.** В перехват
|
|
99
|
+
добавлен `http.client.HTTPException`: он не наследуется от `OSError` и мимо
|
|
100
|
+
прежнего `except` проходил насквозь.
|
|
101
|
+
- **Агент не падает сырым traceback на служебном запуске.** `PermissionError`
|
|
102
|
+
на каталоге логов/аудита, отсутствующий `$HOME` у сервисного аккаунта и
|
|
103
|
+
занятый порт превращаются в одну понятную строку с путём, пользователем и
|
|
104
|
+
нужным флагом, код возврата `1`. Строка «слушаю …» больше не печатается
|
|
105
|
+
раньше фактического старта
|
|
106
|
+
([GAP-007](GAPs/GAP-007-agent-paths-raw-traceback.md)).
|
|
107
|
+
- **`CERTIFICATE_VERIFY_FAILED` больше не показывается как «агент недоступен».**
|
|
108
|
+
Различаются недоверенный CA, несовпадение имени с CN/SAN сертификата и
|
|
109
|
+
ненайденный файл `agent_ca` — у каждого свой рецепт
|
|
110
|
+
([GAP-008](GAPs/GAP-008-agent-cert-trust-on-hub.md)).
|
|
111
|
+
- **«слушаю …» печатается после фактической привязки сокета.** `run_server`
|
|
112
|
+
получил колбэк `on_ready`, который зовётся после bind/listen (и после
|
|
113
|
+
`wrap_socket` при TLS). Раньше на занятом порту оператор видел «слушаю …»,
|
|
114
|
+
а следом отказ — журнал читался как «стартовал и сразу упал».
|
|
115
|
+
- **Каталог логов находится и там, где нет права листинга.** Резолв сначала
|
|
116
|
+
пробует прямой путь (достаточно права прохода `--x`, как было до 0.8.0) и
|
|
117
|
+
только потом идёт в `os.scandir` за регистронезависимым поиском: каталог
|
|
118
|
+
стенда с правами `0711` перестал давать ложное «каталог не найден».
|
|
119
|
+
Отсутствие прав отличается от отсутствия каталога и в тексте сообщения.
|
|
120
|
+
- **Путь Windows-стенда на Linux-хабе** больше не собирается в смесь
|
|
121
|
+
разделителей (`C:\BPMSoft\stand/logs`) — зеркальный случай к фиксу выше.
|
|
122
|
+
- **IPv6-адрес в тексте причины HTTP-пробы** сохраняет скобки: URL из подсказки
|
|
123
|
+
снова можно скопировать в браузер.
|
|
124
|
+
- **Windows: агент больше не занимает уже слушаемый порт.** У
|
|
125
|
+
`ThreadingHTTPServer` включён `SO_REUSEADDR`, и на Windows это разрешает
|
|
126
|
+
второму процессу занять УЖЕ слушаемый порт — bind проходит, `EADDRINUSE` не
|
|
127
|
+
возникает, два агента оказываются на одном порту, а входящие соединения
|
|
128
|
+
распределяются между ними непредсказуемо. Для агента, который по этому порту
|
|
129
|
+
запускает и останавливает процессы, тихое раздвоение недопустимо. Перед
|
|
130
|
+
bind'ом на Windows выполняется проба «кто-то уже слушает?», и занятый порт
|
|
131
|
+
даёт тот же понятный отказ, что и на Linux. `SO_REUSEADDR` при этом не
|
|
132
|
+
отключается — иначе на Windows ломался бы быстрый перезапуск службы
|
|
133
|
+
(соединения в TIME_WAIT). Та же грабля для дашборда была разобрана раньше,
|
|
134
|
+
см. `standkit_hub.server.probe_hub_instance`.
|
|
135
|
+
|
|
136
|
+
### Изменено
|
|
137
|
+
|
|
138
|
+
- **Кукбук — вёрстка и читабельность.** Таблица траблшутинга больше не
|
|
139
|
+
обрезается на десктопе (третья колонка — та, ради которой её читают — была не
|
|
140
|
+
видна ни в одной строке); липкая шапка перестала прятать навигацию и заголовки
|
|
141
|
+
разделов на узких экранах; сетки `g2`/`g3`/`g4` дают заявленное число колонок;
|
|
142
|
+
раскрытая плитка не растягивает соседей в пустые коробки; длинные `<code>` и
|
|
143
|
+
команды не вылезают за плитку и не вызывают горизонтальный скролл страницы;
|
|
144
|
+
контраст доведён до WCAG AA в обеих темах без потери фирменных цветов.
|
|
145
|
+
Сплошные абзацы разобраны на плитки, таблицы и шаги: блоков длиннее пяти
|
|
146
|
+
строк подряд в одну колонку не осталось.
|
|
147
|
+
- **Кукбук — версия 1.3.** Разбор формы регистрации поле за полем, врезка про
|
|
148
|
+
то, что при `transport=agent` пробы и старт/стоп делает агент по своей записи
|
|
149
|
+
реестра, раздел «Токен агента живёт в двух местах» (сторона хаба, формула
|
|
150
|
+
имени переменной, грабля «переменная задаётся до старта хаба»), подсказки
|
|
151
|
+
причин в колонках HTTP и Redis, каталог логов и регистр имени, Redis как поля
|
|
152
|
+
реестра, шесть новых строк в таблице траблшутинга и три новых разбора
|
|
153
|
+
(отказы старта агента под systemd, недоверенный сертификат агента,
|
|
154
|
+
«`http: down`, а стенд живой»).
|
|
155
|
+
- **Установка и обновление — только PyPI.** Из README, `docs/REMOTE_STANDS.md`
|
|
156
|
+
и кукбука убраны команды вида `pip install "git+https://…"`: пакет
|
|
157
|
+
опубликован на [PyPI](https://pypi.org/project/standkit/), конкретная версия
|
|
158
|
+
и откат ставятся `pip install "standkit==<версия>"`.
|
|
159
|
+
- Примеры в кукбуке анонимизированы: реальное имя стенда заказчика заменено на
|
|
160
|
+
`stand-a` во всех вхождениях, включая производные ссылки на секреты и имена
|
|
161
|
+
переменных окружения. Репозиторий публичный, это правило для новых примеров.
|
|
162
|
+
|
|
6
163
|
## [0.7.0] — 2026-08-18
|
|
7
164
|
|
|
8
165
|
### Добавлено
|
|
@@ -335,6 +492,7 @@
|
|
|
335
492
|
- Первый публичный релиз ядра `standkit` + агента `standkit_agent` + веб-дашборда
|
|
336
493
|
`standkit_hub` на PyPI; фронт-README, `docs/REMOTE_STANDS.md`, скриншоты.
|
|
337
494
|
|
|
495
|
+
[0.8.0]: https://pypi.org/project/standkit/0.8.0/
|
|
338
496
|
[0.7.0]: https://pypi.org/project/standkit/0.7.0/
|
|
339
497
|
[0.6.1]: https://pypi.org/project/standkit/0.6.1/
|
|
340
498
|
[0.6.0]: https://pypi.org/project/standkit/0.6.0/
|