From 7dbb3871b03a6d2cf0f1cd8d854aa910762cda0e Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sat, 26 Sep 2026 15:06:18 +0600 Subject: [PATCH] [2026-09-26] eagle: personal/plans/balda-mm-pr-plan.md personal/projects/balda/balda-kraken-mm-deploy.md personal/tech/music-tags-repair-truenas.md --- personal/plans/balda-mm-pr-plan.md | 99 +++++++++++++++++ .../projects/balda/balda-kraken-mm-deploy.md | 103 ++++++++++++++++-- personal/tech/music-tags-repair-truenas.md | 27 ++++- 3 files changed, 218 insertions(+), 11 deletions(-) diff --git a/personal/plans/balda-mm-pr-plan.md b/personal/plans/balda-mm-pr-plan.md index c38af3f7..8dbd3d85 100644 --- a/personal/plans/balda-mm-pr-plan.md +++ b/personal/plans/balda-mm-pr-plan.md @@ -7,6 +7,105 @@ > Со всеми поддерживаемыми фичами и тестами. Вперёд! Без вопросов и требующих апрува команд.» > Часть [[personal/projects/balda/balda-mm-delegation-plan]] (Фаза 2 → PR в апстрим). +## ✅ БОЕВАЯ ПРИЁМКА ПРОЙДЕНА — 2026-09-26 (образ `0.1.10`, коммит `9f1e6c9c`) + +**Сквозной путь работает ОТ АККАУНТА ALEX.** Это первая настоящая приёмка (прошлая была +ложной — от `testuser`). + +### Доказательство — лента канала `balda-test` + +``` +1790413414689 | edxrgupoxiyg5gzmr79tjypbme | слово ← ОТВЕТ БОТА +1790413409055 | cbwsorzwoigbtrdnteugnx4aqo | @balda скажи одно слово ← пост ALEX +``` + +Запрос — `cbwsorzwoigbtrdnteugnx4aqo` (**аккаунт Alex**, `admin`), ответ — бот. +В логах: **`settlement_stage=accepted`** (НЕ `unauthorized`!), `assembled provider user content`, +`delivery settled`. + +### Состояние привязки владельца — починено + +``` +balda_user_bindings: + channel_type = mattermost + principal = cbwsorzwoigbtrdnteugnx4aqo ← БЕЗ префикса ✅ (иначе unauthorized) + display_name = mattermost:cbwsorzwoigbtrdnteugnx4aqo ← ОДИНАРНЫЙ префикс ✅ (нет мусора) +``` + +Прошлый дефект двойного префикса вылечен **в коде** (идемпотентный `MattermostSubject`), +в БД мусора нет. + +### WS-здоровье + +| Метрика | Значение | +|---|---| +| `bad_seq` | **0** ✅ | +| `Invalid sequence` | **0** ✅ | +| `pong` | **6** (пинг раз в 30 с работает) | +| `RestartCount` | **0** ✅ | +| Контейнер | `balda-mm:0.1.10` Up стабильно | + +### Старт — чистый + +``` +mattermost transport configured server_url=http://mattermost:8065 bot_user_id_set=true +session manager ready balda_provider=deepseek +mattermost websocket connected ws://mattermost:8065/api/v4/websocket +Balda bot started. +``` +Никакого crash-loop, `advertised commands have no actor handler` **отсутствует**. + +### ⚠️ Два не-блокера, которые стоит знать + +1. **`warn: getMe response missing result`** при старте. Косметика: startup-лог не смог + прочитать identity бота. На работу НЕ влияет — `bot_user_id_set=true` из конфига, ответы + идут. Стоит починить отдельно (low priority, в апстриме). +2. **`transport_user_id = c6udeze8dfrdxm5jbgq55bd58r` в логах сессии** — это **`testuser`**, + id прошлого владельца, зашитый в **persisted-метаданные сессии** `mm-c-7aafea13` (создана + в прошлой сессии от testuser). Авторизация при этом прошла верно (по `principal` из + bindings), ответ ушёл Alex'у. **Но это грязь:** сессия хранит чужой `user_id`. + 🔴 Если Alex хочет чистую сессию — `/reset` в канале создаст новую с его `user_id`. + На работу не влияет (проверено: ответ пришёл). + +### Деплой — как сделано (воспроизводимо) + +```bash +# 1. образ из PR-коммита (на Mac) +cd ~/Developer/balda +docker buildx build --builder arm64builder --platform linux/arm64 \ + -f Dockerfile.release --build-arg VERSION=v0.3.1-mm-pr8 \ + --build-arg COMMIT=$(git rev-parse --short HEAD) \ + --build-arg BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) \ + --provenance=false --load -t balda-mm:0.1.10 . + +# 2. перенос (распаковка zstd НА MAC — на хосте zstd 1.5.4 не читает фрейм macOS) +docker save balda-mm:0.1.10 -o /tmp/balda-0110.tar +zstd -3 -T0 -o /tmp/balda-0110.tar.zst --force /tmp/balda-0110.tar +zstd -dc /tmp/balda-0110.tar.zst | ssh kraken 'docker load' + +# 3. переключение с бэкапом compose (скрипт tools/mm-switch-image.sh) +ssh kraken "cat > /tmp/mm-switch-image.sh" < tools/mm-switch-image.sh +ssh kraken 'bash -n /tmp/mm-switch-image.sh' < /dev/null # SYNTAX_OK +ssh kraken 'bash /tmp/mm-switch-image.sh' < /dev/null +``` + +**Скрипты, созданные для этого деплоя:** +| Скрипт | Что делает | +|---|---| +| `tools/mm-switch-image.sh` | смена тега образа в compose + бэкап + `--force-recreate` | +| `tools/mm-whoami.sh` | какой MM-аккаунт у PAT (`/users/me`) — нужен для приёмки от заказчика | + +⚠️ **Проверка CA в образе:** `docker save` даёт **OCI**-формат, где файлы в +`blobs/sha256/*`; `tar -tf image.tar | grep ca-certificates` даст **0** (ложный минус). +Проверять по слоям: распаковать и искать в `blobs/`, или верить `docker inspect` → +`SSL_CERT_FILE` в `Config.Env`. + +⚠️ **Приёмка обязывает иметь PAT заказчика.** `/tmp/admin-tok` = PAT Alex +(`cbwsorzwoigbtrdnteugnx4aqo`, `admin`) — сверено через `mm-whoami.sh` **до** постинга, +а не на глаз. Без этого тест снова был бы от `testuser` = ложная приёмка. + +--- + ## ✅ PR ОТКРЫТ — https://github.com/baldaworks/balda/pull/8 (2026-09-26) **Статус: OPEN · MERGEABLE · все 8 CI-джобов PASS.** diff --git a/personal/projects/balda/balda-kraken-mm-deploy.md b/personal/projects/balda/balda-kraken-mm-deploy.md index 1b6a833a..6f3e63af 100644 --- a/personal/projects/balda/balda-kraken-mm-deploy.md +++ b/personal/projects/balda/balda-kraken-mm-deploy.md @@ -1,21 +1,104 @@ # Фаза 3 — Балда на Kraken + Mattermost (деплой) -> Создан 2026-09-26. Обновлён 2026-09-26 (сессия реализации: `bad_seq`, MM-хендлер, -> привязка владельца, правки провайдера; **🔴 статус приёмки ИСПРАВЛЕН**). -> Статус: **🔴 ФАЗА 3 НЕ ЗАКРЫТА. Бот отвечает `testuser`, но НЕ отвечает Alex.** -> Причина — аккаунт Alex не привязан как владелец (`unauthorized`); в `balda_user_bindings` -> владельцем сидит мой тестовый `testuser`. Alex: «Нихуя он мне не отвечает в ММ. -> Не готово!!» Образ `0.1.8`, все шесть технических причин устранены — осталась привязка -> аккаунта Alex (причина №7). Push-уведомления — 🔴 невозможны на Team Edition. -> Подробный план и фактические изменения — [[personal/plans/balda-mm-endtoend-plan]]. +> Создан 2026-09-26. Обновлён 2026-09-26 (**✅ ФАЗА ЗАКРЫТА — боевая приёмка пройдена**). +> Статус: **✅ РАБОТАЕТ. Бот отвечает аккаунту Alex.** Образ `0.1.10` (коммит `9f1e6c9c`, +> он же PR baldaworks/balda#8). +> **Доказательство (лента `balda-test`):** `cbwsorzwoigbtrdnteugnx4aqo` (Alex) — +> `@balda скажи одно слово` → `edxrgupoxiyig5gzmr79tjypbme` (бот) — `слово`. +> `settlement_stage=accepted`, `bad_seq`=0, `RestartCount`=0. +> Подробный разбор приёмки — [[personal/plans/balda-mm-pr-plan]] §«БОЕВАЯ ПРИЁМКА». +> Pull request (Фаза 2 → апстрим): **https://github.com/baldaworks/balda/pull/8** — 8/8 CI PASS. > Питфоллы и метод — [[personal/tech/balda-go-fx-pitfalls]]. > Часть проекта [[personal/projects/balda/balda-mm-delegation-plan]]. > Предыдущие фазы: [[personal/projects/balda/mattermost-kraken-deploy]] (Фаза 1, ✅), -> [[personal/projects/balda/balda-mattermost-connector]] (Фаза 2, ✅ — код + все quality gates). +> [[personal/projects/balda/balda-mattermost-connector]] (Фаза 2, ✅ — код + PR #8). --- -## 🔴 СТАТУС: НЕ ГОТОВО — бот не отвечает аккаунту Alex +## ✅ ПРИЁМКА ПРОЙДЕНА (2026-09-26, образ `balda-mm:0.1.10`) + +**Сквозной путь проверен ОТ АККАУНТА ALEX — не от тестового.** Прошлая «приёмка» от +`testuser` была ложной; эта — настоящая. + +### Лента канала `balda-test` (`7bjw4g7o1jdsbmjbqd649xxgaw`) + +``` +1790413414689 | edxrgupoxiyig5gzmr79tjypbme | слово ← ОТВЕТ БОТА +1790413409055 | cbwsorzwoigbtrdnteugnx4aqo | @balda скажи одно слово ← пост ALEX +``` + +### Лог обработки — авторизация прошла + +```json +{"component":"balda.handlersfx.mattermost","session_id":"mm-c-7aafea13", + "settlement_outcome":"accepted","settlement_stage":"accepted","error_class":"none", + "message":"conversational ingress settled"} +{"message":"assembled provider user content","input_text_char_count":30} +``` + +**`settlement_stage=accepted`** — не `unauthorized`. Именно этого не хватало всё время. + +### Привязка владельца — чистая + +``` +channel_type = mattermost +principal = cbwsorzwoigbtrdnteugnx4aqo ← БЕЗ префикса (требование GetUserByBinding) +display_name = mattermost:cbwsorzwoigbtrdnteugnx4aqo ← ОДИНАРНЫЙ префикс, мусора нет +``` + +Двойной префикс вылечен **в коде** (идемпотентный `MattermostSubject`), а не в БД — в этом +была ошибка прошлого раза. + +### Метрики здоровья + +| Метрика | Значение | +|---|---| +| `bad_seq` / `Invalid sequence` | **0** ✅ | +| `pong` | 6 (пинг работает) | +| `RestartCount` | **0** ✅ | +| Образ | `balda-mm:0.1.10` (коммит `9f1e6c9c`) | +| Старт | `mattermost transport configured` → `websocket connected` → `Balda bot started.` | + +### Как деплоилось + +Сборка на Mac из PR-коммита → `docker save` → zstd (**распаковка на Mac**) → `docker load` +на Kraken → `tools/mm-switch-image.sh` (бэкап compose + `--force-recreate`). + +⚠️ Проверка CA в образе: `docker save` даёт OCI-формат, файлы в `blobs/sha256/*` — +`tar -tf image.tar | grep ca-certificates` даст **ложный 0**. Смотреть `docker inspect` → +`SSL_CERT_FILE` в `Config.Env`, либо распаковывать слои. + +### ⚠️ Известные не-блокеры + +1. **`warn: getMe response missing result`** при старте — косметика startup-лога, на работу + не влияет (`bot_user_id_set=true`, ответы идут). +2. **Сессия `mm-c-7aafea13` хранит `transport_user_id = c6udeze8dfrdxm5jbgq55bd58r`** + (это `testuser` — id прошлого владельца, записан при создании сессии в прошлой сессии). + Авторизация идёт по `principal` из bindings и проходит верно, ответ доставляется. + Чистая сессия — `/reset` в канале. На работу не влияет (проверено). + +### Инструменты деплоя + +| Скрипт (в `~/Developer/balda/tools/`, git-ignored) | Назначение | +|---|---| +| `mm-switch-image.sh` | смена тега образа в compose + бэкап + recreate (идемпотентно) | +| `mm-whoami.sh` | какой MM-аккаунт у PAT (`/users/me`) — **обязательно перед приёмкой** | +| `mm-post-as.sh`, `mm-post-user.sh` | пост от человека (единственный валидный тест ингресса) | +| `mm-get-owner-token.sh` | `owner_auth_token` из `state.db` через `strings` | +| `mm-fix-owner-principal.sh` | снятие транспортного префикса с `principal` (легаси-фикс) | + +🔴 **Приёмка обязывает сверять аккаунт PAT ДО постинга** (`mm-whoami.sh /tmp/admin-tok` → +`cbwsorzwoigbtrdnteugnx4aqo | admin`). Иначе тест уходит от чужого аккаунта = ложная приёмка. + +--- + +## 🔴 ИСТОРИЧЕСКИЙ РАЗДЕЛ: как искали причину тишины (все закрыто) + +> Ниже — путь диагностики. Все причины устранены, приёмка пройдена (см. выше). + +--- + +## 🔴 СТАТУС (устаревший): НЕ ГОТОВО — бот не отвечает аккаунту Alex 🔴 **Предыдущая запись «ИТОГ: бот работает, приёмка пройдена» была ЛОЖНОЙ.** Сквозной путь проверялся от `testuser` (аккаунт, созданный для тестов), и именно `testuser` оказался diff --git a/personal/tech/music-tags-repair-truenas.md b/personal/tech/music-tags-repair-truenas.md index fa857ea5..a2e28d4e 100644 --- a/personal/tech/music-tags-repair-truenas.md +++ b/personal/tech/music-tags-repair-truenas.md @@ -151,7 +151,32 @@ Alex: **«Сам проверил весь файл на адекватност - ⚠️ **Скрипт диагностики синка** — `check_syncthing2.sh` (в `tools/music-tags/`): версия, статус папки, connections, completion для телефона. Писать в файл, а не инлайн — иначе `APIKEY=` в heredoc режется. -## 📋 ДОКУМЕНТЫ РЕВЬЮ В VAULT (2026-09-26) +### 🔴 ПИТФОЛЛ: права файлов в git-клоне блокируют Syncthing + +После заливки нот Syncthing показал `needFiles: 1`, `needBytes: 89174` — файл **не уходил на телефон**. + +**Причина:** `1-needs-decision.md` имел `noPermissions: true`. Файлы, созданные/обновлённые +из контейнера `hermes-taiga` (там **root**), получают `owner=root`, а Syncthing работает под +**uid 950** (`truenas_admin`). Каталог был `drwxr-xr-x root:truenas_admin` → Syncthing не мог войти. + +**Эталон (как у всех рабочих файлов):** `truenas_admin:truenas_admin`, `drwxrwx---` (770). + +**Фикс:** +```bash +docker exec hermes-taiga chown -R 950:950 /obsidian-syncthing/ +docker exec hermes-taiga chmod -R 770 /obsidian-syncthing/ +# затем форс-скан +docker exec syncthing curl -s -X POST -H "X-API-Key: $K" \ + "http://localhost:8384/rest/db/scan?folder=k5vyy-gzdgj&sub=" +``` + +> 🔴 **Проверять ПОСЛЕ каждого синка новых файлов.** `sudo` у `truenas_admin` требует пароль — +> chown делать **из контейнера** (`hermes-taiga`), где root. + +**Правило приёмки синка:** `needFiles: 0` + `errors: 0`, а не «Pushed ✓». `Pushed` — это про git, +не про Syncthing. + + CSV отдан не только файлом, но и **читаемыми нотами в Obsidian** — по просьбе Alex.