[2026-09-26] eagle: family/how-to/jellyfin-config.md personal/index.md personal/plans/balda-mm-endtoend-plan.md personal/projects/balda/balda-kraken-mm-deploy.md personal/projects/balda/balda-mm-delegation-plan.md personal/tech/balda-go-fx-pitfalls.md personal/tech/music-tags-repair-truenas.md personal/tech/yandex-music-api.md personal/yandex-music-library.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-26 13:56:32 +06:00
1 parent 4109797f6b
commit f9b55abb8c
9 files changed
+2190 -94

No files matched your search

+94 -26
View File
@@ -1,11 +1,48 @@
# План: доделать сквозной путь `@balda` → ответ в Mattermost
> Создан 2026-09-26. Обновлён 2026-09-26 (сессия реализации, полный проход).
> Статус: **🟡 ПЯТЬ ИЗ ШЕСТИ ПРИЧИН УСТРАНЕНЫ. Последний фикс (`base_url` + CA) задеплоен,
> не проверен. Осталась приёмка ответом в UI.**
> Статус: **✅ ЗАКРЫТ И ПРИНЯТ. Все шесть причин устранены, шестая проверена — бот отвечает
> в UI. Push-уведомления: 🔴 невозможны на Team Edition (разбор ниже) — задача снята с плана.**
> Часть [[personal/projects/balda/balda-kraken-mm-deploy]] (Фаза 3).
> Команда Alex: «Доделывай всё. И уведомления в приложения неактивны тоже поправь.»
## ✅ ПРИЁМКА ПРОЙДЕНА (2026-09-26)
Сквозной путь работает. В канале `balda-test` (`7bjw4g7o1jdsbmjbqd649xxgaw`):
```
c6udeze8dfrdxm5jbgq55bd58r (testuser) | @balda reply with a single word
edxrgupoxiyg5gzmr79tjypbme (bot) | работает
edxrgupoxiyg5gzmr79tjypbme (bot) | работает
```
Полный проход в логах образа `0.1.8`:
```
mattermost websocket event decoded event=posted
mattermost post accepted for processing text="reply with a single word"
session created successfully session_id=mm-c-7aafea13
assembled provider user content input_text_char_count=424
received provider event event_author=deepseek text_char_count=16 final_response=true
delivery settled settlement_class=success
command handled and acknowledged
```
🔴 **`base_url` (F1) и CA (F2) — подтверждены фиксом.** Симптом `x509: certificate signed by
unknown authority` и адрес `api.openai.com` из логов ушли полностью: провайдер ответил как
`event_author=deepseek`, 16 символов текста. Приёмка выполнена **через REST-чтение ленты канала**
(`GET /channels/{id}/posts`) — это верифицированный ответ бота, не «контейнер Up».
📌 **Как проверять ответ бота в UI без GUI-браузера:** читать ленту канала REST'ом и грепать
`user_id == <bot_user_id>`:
```bash
ssh kraken 'curl -s -H "Authorization: Bearer $(cat /home/kraken/balda/secrets/mm-bot-token)" \
"http://localhost:8065/api/v4/channels/7bjw4g7o1jdsbmjbqd649xxgaw/posts?per_page=4" \
| jq -r ".order[] as \$o | .posts[\$o] | \"\(.user_id) | \(.message)\""'
```
Это надёжнее «видно в UI» для агента: даёт однозначный `user_id` автора.
## Итог сессии (кратко)
Найдено и устранено **шесть независимых причин** тишины. Каждая подтверждена логами.
@@ -17,21 +54,12 @@
| C | `ChannelMattermost` не было в auth → `unsupported transport` | дельта 17 | ✅ |
| D | `/start` отбивался проверкой доступа **до** привязки | правка хендлера | ✅ команда прошла в runtime |
| E | `principal` с транспортным префиксом в БД → вечный `unauthorized` | UPDATE с бэкапом | ✅ `assembled provider user content` |
| F | **`base_url` не читается из YAML + нет CA в `scratch`** | дельта 22 + `.env` | 🔴 **задеплоено, не проверено** |
| F | **`base_url` не читается из YAML + нет CA в `scratch`** | дельта 22 + `.env` | ✅ **ответ провайдера получен** |
**Где именно стоим:** авторизация **пройдена**, пост дошёл до провайдера
(`assembled provider user content`, сессия `mm-c-7aafea13`). Оставался отказ на уровне
LLM-запроса — провайдер шёл на `api.openai.com` и падал с TLS-ошибкой. Оба дефекта
исправлены в образе `0.1.8`, но финальная проверка не прогонялась.
**Итог:** все шесть причин устранены и проверены. Бот отвечает в канале.
**Следующее действие:**
```bash
ssh kraken '/tmp/mm-post-user.sh 7bjw4g7o1jdsbmjbqd649xxgaw testuser "T3stPassw0rd!x" "@balda скажи одно слово"'
sleep 45
ssh kraken 'docker logs balda-mm --since 60s | grep -iE "error|turn task|x509"'
```
Ожидание: ответ бота в канале `balda-test` **виден в UI**, в логах нет `x509`.
Приёмка = **видно в UI**, не «контейнер Up» и не `settled`.
**Следующее действие:** нет — задача закрыта. Приёмка выполнена через REST-ленту канала
(см. §«Приёмка пройдена» выше).
---
@@ -403,20 +431,55 @@ ssh kraken 'sudo -n strings /srv/…-49e8f586…/docker/balda/state/state.db | g
---
## Шаг 5 — Push-уведомления в MM ⬜ (не начато)
## 🔴 Шаг 5 — Push-уведомления: НЕВОЗМОЖНЫ на Team Edition (диагностика завершена)
Задача Alex: «уведомления в приложения неактивны».
Задача Alex: «уведомления в приложения неактивны тоже поправь».
**Диагноз: это ограничение продукта, а не настройка. Включить нельзя.**
Что проверить/включить:
- `EmailSettings` / `ServiceSettings.EnablePushNotifications` (mobile push);
- Team Edition **не включает** `PushNotifications` для iOS/Android через Mattermost Inc. —
официальный push-прокси требует лицензии, **в TE он недоступен**;
- альтернатива: self-hosted `mattermost-push-proxy` (HPNS), требует настройки
`ServiceSettings.PushNotificationServer` + сертификатов;
- `EmailSettings.SendEmailNotifications` + SMTP — почтовые уведомления работают в TE без ограничений.
### Что показал `mmctl`
⚠️ Точный диагноз «неактивны» снять **до** правок: зайти в System Console → Notifications,
посмотреть, какие тумблеры серые и почему. Не менять конфиг вслепую.
```
EmailSettings.SendPushNotifications false
EmailSettings.PushNotificationServer "" ← пусто
EmailSettings.SendEmailNotifications true
EmailSettings.SMTPServer localhost
EmailSettings.SMTPPort 10025 ← SMTP не слушает: exit 7
mattermost version Build Enterprise Ready: false ← Team Edition
DiagnosticId kgib6ormjf8sf8xds7dkhaee5c
```
Дополнительно: `mmctl config get ServiceSettings.EnablePushNotifications` → **`Error: invalid key`**
(в 11.x ключ переехал в `EmailSettings` — 🔴 искать тумблер в `EmailSettings`, не в `ServiceSettings`).
### Три пути проверены — все закрыты
| Путь | Проверка | Вердикт |
|---|---|---|
| **Официальный push-прокси** | `curl -X POST https://push.mattermost.com/api/v1/send_push` с нашим `server_id=<DiagnosticId>` | ⚠️ Прокси жив (HTTP 200), но **отвергает наш инстанс**: `{"error":"Did not send message because of missing platform property type=ios serverId=kgib6ormjf8sf8xds7dkhaee5c"}`. APNs/FCM-сертификаты вешаются на прокси **только для лицензированных EE** — для TE-`DiagnosticId` их нет |
| **Свой MPNS** (open-source `mattermost-push-proxy`) | Чтение офиц. доков | 🔴 Требует **собственные подписанные сборки мобильных приложений** + APNs `.p8` (Apple Developer, $99/год) + FCM-ключ. **Официальные приложения к своему MPNS не подключатся** — они прошиты на bundle ID Mattermost Inc. |
| **SMTP-почта** | `SendEmailNotifications: true`, но `localhost:10025` → exit 7; `ss -ltn` на хосте | ⚠️ Путь **рабочий в TE без лицензии**, но SMTP не настроен: на хосте **нет ни одного слушателя** на 25/465/587/10025 |
### 📌 Вывод (durable)
**Push в официальных мобильных приложениях Mattermost на Team Edition включить невозможно.**
Клиенты принимают push только от прокси, зарегистрированного за лицензией. Это не
конфигурация, а архитектура продукта. Варианты:
1. **Лицензия Mattermost Professional** (~$10/юзер/мес) — push заработает сразу, официальный прокси.
2. **Свои сборки приложений + свой MPNS** — нужен Apple Developer + Firebase + поддержка форка.
3. **SMTP-почта** — единственный путь без лицензии и затрат; уведомления приходят на e-mail,
не в приложение. ~15 минут работы (Gmail app password или локальный postfix + `EmailSettings`).
4. **Оставить как есть** — уведомлений не будет.
⚠️ **Диагноз снимать ДО правок:** `mmctl config get` по `EmailSettings`, `SendPushNotifications`,
`PushNotificationServer`, затем **живая проба прокси** с реальным `DiagnosticId` из
`SELECT value FROM systems WHERE name='DiagnosticId';`. Не менять конфиг вслепую —
`SendPushNotifications=true` без зарегистрированного прокси не даст ничего.
⚠️ `DiagnosticId` лежит в таблице `systems` (не `Systems`, не `Systems.name='ServerId'`).
Запрос: `docker exec mm-postgres psql -U mmuser -d mattermost -t -c "SELECT name, value FROM systems WHERE name ILIKE '%diagnostic%';"`
🔴 **Кавычки:** внутри `sqlite/psql -c` в ssh-строке одинарные кавычки ломаются — использовать
`'"'"'`-экранирование, иначе `column "DiagnosticId" does not exist`.
---
@@ -445,6 +508,11 @@ ssh kraken 'sudo -n strings /srv/…-49e8f586…/docker/balda/state/state.db | g
| 19 | `AttachBinding` **не даёт перепривязать** (`count != 0` → `ErrBindingAlreadyAssigned`), detach-API отсутствует | править `state.db` точечным UPDATE с бэкапом и остановленным контейнером |
| 20 | `sqlite3` **есть на хосте** Kraken (`/usr/bin/sqlite3`), но не в контейнере | правки БД делать с хоста под `sudo -n`, контейнер остановить |
| 21 | Правка `state.db` через `sudo cp` требует апрува и **блокируется** (таймаут) | точечный UPDATE одного поля вместо операций над каталогом данных |
| 22 | `mmctl config get ServiceSettings.EnablePushNotifications` → **`Error: invalid key`** | в MM 11.x ключ живёт в `EmailSettings.SendPushNotifications` |
| 23 | Официальный push-прокси отвечает 200 даже на **невалидный** `server_id` — успех по HTTP не значит доставку | читать **тело** ответа: `"status":"FAIL"` + `Did not send message because of missing platform property` |
| 24 | `psql -t -c "… name IN ('DiagnosticId')"` в ssh-строке ломается на кавычках → `column "DiagnosticId" does not exist` | экранировать `'"'"'` внутри ssh-команды, либо использовать `ILIKE` без кавычек на значении |
| 25 | Приёмка «виден в UI» без GUI-браузера | `GET /api/v4/channels/{id}/posts?per_page=N` + `jq` по `user_id` автора — однозначное доказательство |
| 26 | `docker compose` в `/home/kraken/mattermost/` — 3 сервиса (`postgres`, `mattermost`, сеть `mm-net`), БД `mm-postgres` | БД доступна как `docker exec mm-postgres psql -U mmuser -d mattermost` |
## Связанные заметки