[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

This commit is contained in:
Alexey Martemyanov committed 2026-09-26 15:06:18 +06:00
1 parent 7564ae26ac
commit 7dbb3871b0
3 files changed
+218 -11

No files matched your search

+99
View File
@@ -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.**
@@ -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` оказался
+26 -1
View File
@@ -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/<path>
docker exec hermes-taiga chmod -R 770 /obsidian-syncthing/<path>
# затем форс-скан
docker exec syncthing curl -s -X POST -H "X-API-Key: $K" \
"http://localhost:8384/rest/db/scan?folder=k5vyy-gzdgj&sub=<path>"
```
> 🔴 **Проверять ПОСЛЕ каждого синка новых файлов.** `sudo` у `truenas_admin` требует пароль —
> chown делать **из контейнера** (`hermes-taiga`), где root.
**Правило приёмки синка:** `needFiles: 0` + `errors: 0`, а не «Pushed ✓». `Pushed` — это про git,
не про Syncthing.
CSV отдан не только файлом, но и **читаемыми нотами в Obsidian** — по просьбе Alex.