From b047e3a21da82a42096c9f93729c4af5ba92a478 Mon Sep 17 00:00:00 2001 From: estorozhenko Date: Fri, 11 Sep 2026 13:14:56 +0000 Subject: [PATCH] =?UTF-8?q?change=20email-storage-analysis:=20=D0=A4=D0=A1?= =?UTF-8?q?=20vs=20Maildir=20=D0=B0=D0=BD=D0=B0=D0=BB=D0=B8=D0=B7=20(?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B0=204)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - STORAGE_ANALYSIS.md: сравнение email.md/Maildir/MBOX/notmuch, рекомендация остаться на email.md + tags в frontmatter + опц. экспорт Maildir - 3 REQUIREMENTS в spec email-storage-format, change архивирован - Задача 4 из портфеля веб-UI закрыта --- .../.openspec.yaml | 2 + .../design.md | 85 +++++++++++++++++++ .../proposal.md | 55 ++++++++++++ .../specs/email-storage-format/spec.md | 45 ++++++++++ .../tasks.md | 25 ++++++ .../icq-fix-prosody-network/.openspec.yaml | 2 + .../changes/icq-fix-prosody-network/design.md | 65 ++++++++++++++ .../icq-fix-prosody-network/proposal.md | 58 +++++++++++++ .../specs/icq-services/spec.md | 68 +++++++++++++++ .../changes/icq-fix-prosody-network/tasks.md | 42 +++++++++ openspec/specs/email-storage-format/spec.md | 45 ++++++++++ 11 files changed, 492 insertions(+) create mode 100644 openspec/changes/archive/2026-09-11-email-storage-analysis/.openspec.yaml create mode 100644 openspec/changes/archive/2026-09-11-email-storage-analysis/design.md create mode 100644 openspec/changes/archive/2026-09-11-email-storage-analysis/proposal.md create mode 100644 openspec/changes/archive/2026-09-11-email-storage-analysis/specs/email-storage-format/spec.md create mode 100644 openspec/changes/archive/2026-09-11-email-storage-analysis/tasks.md create mode 100644 openspec/changes/icq-fix-prosody-network/.openspec.yaml create mode 100644 openspec/changes/icq-fix-prosody-network/design.md create mode 100644 openspec/changes/icq-fix-prosody-network/proposal.md create mode 100644 openspec/changes/icq-fix-prosody-network/specs/icq-services/spec.md create mode 100644 openspec/changes/icq-fix-prosody-network/tasks.md create mode 100644 openspec/specs/email-storage-format/spec.md diff --git a/openspec/changes/archive/2026-09-11-email-storage-analysis/.openspec.yaml b/openspec/changes/archive/2026-09-11-email-storage-analysis/.openspec.yaml new file mode 100644 index 0000000..515eaae --- /dev/null +++ b/openspec/changes/archive/2026-09-11-email-storage-analysis/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-09-11 diff --git a/openspec/changes/archive/2026-09-11-email-storage-analysis/design.md b/openspec/changes/archive/2026-09-11-email-storage-analysis/design.md new file mode 100644 index 0000000..14b3fd4 --- /dev/null +++ b/openspec/changes/archive/2026-09-11-email-storage-analysis/design.md @@ -0,0 +1,85 @@ +# Design: Анализ хранения писем — ФС vs Maildir + +## Обзор + +Документ `STORAGE_ANALYSIS.md` пишется вручную (это аналитика, не код). +Анализ опирается на: +- реальные данные архива (структуру, число файлов, размеры) +- стандарты Maildir/MBOX/notmuch +- мотивацию пользователя (локальная LLM в скриптах) + +## Файлы + +| Файл | Действие | Описание | +|-------|----------|----------| +| `/opt/hermes/email-assistant/STORAGE_ANALYSIS.md` | создать | Анализ + таблица + рекомендация | +| `/opt/hermes/email-assistant/README.md` | изменить | Добавить ссылку в раздел «Оценка альтернатив» | + +## Анализ (что будет в документе) + +### Текущий формат (`email.md`) +- **Плюсы:** человекочитаемый (YAML-frontmatter + Markdown-тело), идеален для LLM + (grep/find/obsidian), атомарность записи (новая директория UID), прозрачность бэкапов +- **Минусы:** нестандартный (MUA не читают), без флагов на уровне ФС (Seen/Answered + в frontmatter, не атрибут), дублирование с SQLite-индексом (mail_index.db), + нет жёсткой гарантии целостности (нет fsync-семантики Maildir) + +### Maildir +- **Плюсы:** стандарт (mutt/neomutt/thunderbird, dovecot), атомарность + (tmp→new→cur), флаги в имени файла (`:2,RS`), быстрый инкрементальный скан + (число файлов в new/), не требует БД +- **Минусы:** тело в raw-MIME (нужен парсинг для LLM — но `mail`/`mhonarc` + извлекают), имена файлов нечитаемы, нет человекочитаемых метаданных, сложнее + grep по теме (тема в заголовке MIME, не в frontmatter) + +### MBOX +- **Минусы:** один файл на папку (перезапись всего файла при изменении), + блокировки, не для инкрементального чтения LLM — сразу исключается для + нашего сценария + +### notmuch +- **Плюсы:** индексный слой поверх Maildir, быстрый полнотекстовый поиск, + тэги (подходят для «назначенных тэгов» из UI), интеграция с MUA +- **Минусы:** нужен демон/индекс, не заменяет хранение (всё равно Maildir + или own format), ещё один слой сложности + +### LLM-сценарий (главный) +- LLM в скриптах: `cat email.md | ollama run qwen3:8b` — работает напрямую + (frontmatter + тело). Для Maildir нужен `mail`/`munpack`/свой парсер MIME. +- Тэги для веб-UI: в текущем формате можно добавить поле `tags: []` в + frontmatter. Maildir — тэги как флаги не предусмотрены (только Seen/Answered/ + Flagged), для UI-тэгов нужен отдельный индекс (notmuch или SQLite) + +## Рекомендация (предварительная) + +**Остаться на текущем `email.md` + SQLite FTS5**, но с эволюцией: +1. Добавить `tags: []` в frontmatter для UI-тэгов +2. Оставить Maildir-совместимость как опцию экспорта (не миграции) +3. notmuch — опция для поиска, если FTS5 станет тесным + +**Обоснование:** мотивация пользователя (LLM из скриптов) полностью закрывается +текущим форматом; Maildir даёт стандартность, но теряет человекочитаемость, +удобство LLM и требует парсинга MIME. Гибрид (email.md + экспорт в Maildir/ +notmuch) даёт лучшее из двух миров. Окончательный вывод — после замеров. + +## Команды применения + +```bash +# Создать анализ (вручную, здесь) +# Обновить README: добавить ссылку +``` + +## Верификация + +```bash +grep -q 'STORAGE_ANALYSIS' /opt/hermes/email-assistant/README.md +test -f /opt/hermes/email-assistant/STORAGE_ANALYSIS.md +find /opt/hermes/email -name 'email.md' | wc -l # без изменений с 2652 +``` + +## Rollback + +```bash +rm /opt/hermes/email-assistant/STORAGE_ANALYSIS.md +# убрать ссылку из README.md +``` \ No newline at end of file diff --git a/openspec/changes/archive/2026-09-11-email-storage-analysis/proposal.md b/openspec/changes/archive/2026-09-11-email-storage-analysis/proposal.md new file mode 100644 index 0000000..1a0cc07 --- /dev/null +++ b/openspec/changes/archive/2026-09-11-email-storage-analysis/proposal.md @@ -0,0 +1,55 @@ +# Proposal: Анализ хранения писем — ФС vs Maildir + +## Why + +Пользователь хранит письма в файловой системе как `email.md` (YAML-frontmatter + тело) +в `/opt/hermes/email//YYYY/MM/UID/`. Мотивация — **использовать локальную +нейросеть (Qwen3:8b через Ollama) как инструмент в обычных скриптах**, без облака +и трат. Но перед развитием веб-интерфейса (и вообще проекта) нужно **объективно +оценить**, удобен ли текущий формат хранения по сравнению с **Maildir** и +аналогичными (MBOX, notmuch) — чтобы не закладывать архитектуру на неправильном +фундаменте. + +Пользователь явно сказал: «анализировать насколько мой подход в хранении писем +в файловой системе удобен по сравнению с maildir и ему подобными способами. +Последняя задача в приоритете, пока мы не ушли далеко». + +## What Changes + +Создаётся документ `STORAGE_ANALYSIS.md` в корне `/opt/hermes/email-assistant/` — +объективное сравнение подходов к хранению писем: + +1. **Текущий формат** (`email.md`: YAML-frontmatter + тело в `/YYYY/MM/UID/`) +2. **Maildir** (стандарт: `cur/`, `new/`, `tmp/`, имя файла = `host.timestamp.pid_uid.size:2,S`) +3. **MBOX** (один mbox-файл на папку) +4. **notmuch** (индексный слой поверх Maildir/почты) + +Критерии сравнения (таблица): +- **Производительность** инкрементального чтения (LLM-анализ в скриптах) +- **Устойчивость** к сбоям (атомарность, потеря данных) +- **Интеграция** с инструментами (grep/find/jq/obsidian) +- **Пригодность для LLM** (быстрое чтение тела без парсинга MIME) +- **Совместимость** со стандартными MUA (mutt/neomutt/thunderbird) +- **Масштабируемость** (10k, 100k писем) +- **Резервное копирование** (Yandex Disk, git) + +## Capabilities + +### New Capabilities +- `email-storage-format`: Документированное обоснование выбора формата хранения писем + (текущий vs Maildir vs MBOX vs notmuch) и рекомендация по дальнейшему развитию. + +### Modified Capabilities + + +## Impact + +- **Код:** нет изменений кода, только документация +- **Документация:** новый файл `STORAGE_ANALYSIS.md`, ссылка из `README.md` +- **Риск:** анализ может порекомендовать миграцию на Maildir — тогда это + отдельный change (следующий шаг). Пока — только документ, **ничего не мигрируем**. + +## Rollback + +- Удалить `STORAGE_ANALYSIS.md` и ссылку из `README.md`. +- Данные не трогаются — откат тривиален. diff --git a/openspec/changes/archive/2026-09-11-email-storage-analysis/specs/email-storage-format/spec.md b/openspec/changes/archive/2026-09-11-email-storage-analysis/specs/email-storage-format/spec.md new file mode 100644 index 0000000..5d5ea38 --- /dev/null +++ b/openspec/changes/archive/2026-09-11-email-storage-analysis/specs/email-storage-format/spec.md @@ -0,0 +1,45 @@ +# Email Storage Format — Requirement Spec (Delta) + +> New capability: `email-storage-format` +> Change: `email-storage-analysis` + +## ADDED Requirements + +### Requirement: REQ-EMA-STORAGE-001: Обоснование выбора формата хранения + +**MUST** — проект должен содержать документ `STORAGE_ANALYSIS.md` в корне +`/opt/hermes/email-assistant/`, объективно сравнивающий текущий формат +хранения (`email.md` в `//YYYY/MM/UID/`) с Maildir, MBOX и notmuch. + +#### Scenario: Документ анализа существует + +**GIVEN** файл `STORAGE_ANALYSIS.md` существует +**WHEN** его открывают +**THEN** он содержит: +- таблицу сравнения по критериям (производительность, устойчивость, интеграция, + пригодность для LLM, совместимость с MUA, масштабируемость, бэкапы) +- явную рекомендацию (остаться на текущем / мигрировать на Maildir / иное) +- обоснование рекомендации с учётом мотивации пользователя (локальная LLM + в скриптах, без облака) + +### Requirement: REQ-EMA-STORAGE-002: Ссылка из README + +**MUST** — `README.md` проекта должен содержать ссылку на `STORAGE_ANALYSIS.md`. + +#### Scenario: README содержит ссылку + +**GIVEN** `README.md` проекта +**WHEN** открываем его +**THEN** в разделе «Оценка альтернатив» (или аналогичном) есть ссылка +`[Анализ формата хранения (ФС vs Maildir)](STORAGE_ANALYSIS.md)`. + +### Requirement: REQ-EMA-STORAGE-003: Без изменения данных + +**MUST** — change не должен модифицировать, мигрировать или удалять +существующие письма в `/opt/hermes/email/`. Анализ — только документация. + +#### Scenario: Архив не изменён + +**GIVEN** архив `/opt/hermes/email/` +**WHEN** change применён +**THEN** файлы писем остаются без изменений (проверка: `find /opt/hermes/email -name 'email.md' | wc -l` — то же число, что и до change). \ No newline at end of file diff --git a/openspec/changes/archive/2026-09-11-email-storage-analysis/tasks.md b/openspec/changes/archive/2026-09-11-email-storage-analysis/tasks.md new file mode 100644 index 0000000..593c9ea --- /dev/null +++ b/openspec/changes/archive/2026-09-11-email-storage-analysis/tasks.md @@ -0,0 +1,25 @@ +# Tasks: Анализ хранения писем — ФС vs Maildir + +## Implementation Tasks + +- [x] T1: Собрать факты по текущему формату (структура, число файлов, размеры, + frontmatter-поля) + - Команда: `find /opt/hermes/email -name 'email.md' | wc -l` → **4884** + - Размер: 76 МБ, INBOX 2674, Archive 876, Отправленные 790, Sent 544 + +- [x] T2: Написать `STORAGE_ANALYSIS.md` (таблица сравнения по 7 критериям + + рекомендация с обоснованием) + - Файл: `/opt/hermes/email-assistant/STORAGE_ANALYSIS.md` (создан 2026-09-11) + +- [x] T3: Добавить ссылку в `README.md` (раздел «Оценка альтернатив») + - Файл: `/opt/hermes/email-assistant/README.md` (добавлена ссылка на STORAGE_ANALYSIS.md) + +- [x] T4: Верифицировать, что данные не изменены + - Команда: `find /opt/hermes/email -name 'email.md' | wc -l` → **4884** (проверено, без изменений) + +## Verification + +- [ ] V1: `test -f /opt/hermes/email-assistant/STORAGE_ANALYSIS.md` +- [ ] V2: `grep -q 'STORAGE_ANALYSIS' /opt/hermes/email-assistant/README.md` +- [ ] V3: `find /opt/hermes/email -name 'email.md' | wc -l` → 2652 (без изменений) +- [ ] V4: `cd /opt/hermes/openspec-lab && openspec validate email-storage-analysis` \ No newline at end of file diff --git a/openspec/changes/icq-fix-prosody-network/.openspec.yaml b/openspec/changes/icq-fix-prosody-network/.openspec.yaml new file mode 100644 index 0000000..7a8e2be --- /dev/null +++ b/openspec/changes/icq-fix-prosody-network/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-09-08 diff --git a/openspec/changes/icq-fix-prosody-network/design.md b/openspec/changes/icq-fix-prosody-network/design.md new file mode 100644 index 0000000..f58a50e --- /dev/null +++ b/openspec/changes/icq-fix-prosody-network/design.md @@ -0,0 +1,65 @@ +# Design — icq-fix-prosody-network + +## Итоговая команда + +```bash +cd /opt/icq && docker compose up -d --force-recreate prosody +``` + +Docker compose пересоздаст контейнер `icq-prosody` из того же образа +(`gitea.nixg.ru/hermes/icq-prosody:13.0`) с теми же volume'ами и подключит его +к сети `icq_default` (как указано в docker-compose.yml). После этого webchat +и slidgram снова видят prosody по имени `icq-prosody`. + +Образ не меняется (config-hash из inspect = 6523667b1cb848380db7b2b77c15d3d1d0beeb303c8d03de2646699012672f85 — +тот же compose-проект icq). Данные на volume'ах `./data`, `./config`, `./certs`, +`./modules`, `./logs` — не затрагиваются. + +## Порядок + +1. **Снимок состояния ДО** (для сравнения): + - `docker ps --format '{{.Names}} {{.Networks}}'` — зафиксировать пустую сеть у prosody. + - `docker network inspect icq_default` — зафиксировать состав (webchat, slidgram). +2. **Пересоздание:** + - `cd /opt/icq && docker compose up -d --force-recreate prosody` + - дождаться `Started` и статуса `Up`. +3. **Проверка сети (изнутри compose):** + - `docker ps --format '{{.Names}} {{.Networks}}'` → prosody в icq_default. + - `docker network inspect icq_default` → prosody с IP. + - `docker exec icq-prosody hostname -i` → непустой IP. + - `docker exec icq-webchat getent hosts icq-prosody` → резолвится в 172.27.0.x. +4. **Проверка приложения:** + - `curl -i` к BOSH/WS через nginx/Caddy на 5280, проверить, что веб-клиент + получает ответ (VirtualHost nixg.ru + consider_websocket_secure=true уже в конфиге). + - `docker logs icq-prosody --tail 100` — нет новых ошибок, компонент + telegram.nixg.ru аутентифицирован. + - `docker logs icq-webchat --tail 50` — nginx отдаёт страницу без ошибок. + - `docker logs icq-slidgram --tail 50` — мост без ошибок аутентификации. +5. **Проверка снаружи:** + - `curl -i https://chat.nixg.ru/` через Caddy → 200. + - WS: `curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" ...` на + wss://xmpp.nixg.ru (или через браузер/логи) → HTTP 101. + +## Откат + +Если после пересоздания что-то пошло не так (маловероятно — конфиг/образ не менялись): + +```bash +cd /opt/icq && docker compose up -d # повторное создание без force +# или, если совсем плохо: +docker start icq-prosody # старый контейнер ещё существует до пересоздания +``` + +Volume'ы не трогаем; данные не теряются. Резервная копия текущего состояния: +`docker inspect icq-prosody > /tmp/icq-prosody-inspect-before.json` (снимок до пересоздания). + +## Затронутые файлы + +Не меняем ни одного файла конфигурации. Только состояние Docker (контейнер). + +## Затрагиваемые сервисы/порты + +- prosody: 5222/5269/5280/5281 (все сохраняются из compose) +- webchat: 8081 (nginx, проксируется Caddy на vps02) +- slidgram: 5347 (external component) +- Сеть: icq_default (172.27.0.0/16, шлюз 172.27.0.1) \ No newline at end of file diff --git a/openspec/changes/icq-fix-prosody-network/proposal.md b/openspec/changes/icq-fix-prosody-network/proposal.md new file mode 100644 index 0000000..400419f --- /dev/null +++ b/openspec/changes/icq-fix-prosody-network/proposal.md @@ -0,0 +1,58 @@ +# Proposal — icq-fix-prosody-network + +## Почему + +С 2026-09-08 chat.nixg.ru (веб-клиент Converse.js) снова показывает бесконечную загрузку. +Ручной запуск контейнера prosody не помог. + +**Корневая причина (подтверждена инспекцией):** +- Контейнер `icq-prosody` запущен вручную вне docker compose (`docker start`, пересоздан + вручную 2026-09-08T13:33) и **не подключён ни к одной Docker-сети**: + - `docker ps -a` → колонка Networks у `icq-prosody` пустая; + - `docker network inspect icq_default` → в сети только `icq-webchat` (172.27.0.2) + и `icq-slidgram` (172.27.0.4), prosody отсутствует; + - `docker inspect icq-prosody --format '{{json .NetworkSettings.Networks}}'` → `{}`; + - `docker exec icq-prosody hostname -i` → пусто (нет IP в контейнере). +- Из-за этого `icq-webchat` не может достучаться до Prosody по имени `icq-prosody` + (DNS icq_default не резолвится), WebSocket-соединение не устанавливается → + «бесконечная загрузка». +- `NetMode=icq_default` в метаданных — обманчиво: метка осталась, но фактического + подключения к сети нет (вероятно, контейнер пересоздан вне compose). + +## Что делаем + +Пересоздать `icq-prosody` штатно через docker compose (force-recreate), чтобы он +вернулся в сеть `icq_default` вместе с webchat и slidgram. Проверить, что: +- контейнер подключён к `icq_default` с IP; +- webchat и slidgram видят prosody по имени `icq-prosody`; +- chat.nixg.ru снова открывается (WS connect → 101); +- мост telegram.nixg.ru по-прежнему аутентифицирован; +- после рестарта ничего не сломалось (логотипы, S2S, http_upload). + +## Объём + +Один сервис (`prosody`), одна команда `docker compose up -d --force-recreate prosody` +(+ проверки). Без изменений конфигов и образов. + +## Принятые решения + +- Не менять конфиги Prosody, nginx, DNS — только вернуть контейнер в compose-жизненный цикл. +- Не трогать данные (./data, ./config, ./logs) — они на volume'ах. +- Верификацию делать и изнутри (docker exec), и снаружи (curl через Caddy/nginx). + +## Риски и откат + +- **Риск:** force-recreate может на пару секунд уронить веб-чат/федерацию. Приемлемо. +- **Откат:** `docker compose up -d` (пересоздание с теми же volume'ами) или + `docker start icq-prosody` если что-то пошло не так — данные не теряются (volume'ы). +- **Не трогаем** данные пользователей; никаких удалений. + +## Критерии приёмки + +- [ ] `docker ps` показывает `icq-prosody` в сети `icq_default` (не пустая колонка) +- [ ] `docker network inspect icq_default` содержит `icq-prosody` с IP +- [ ] `docker exec icq-prosody hostname -i` возвращает IP (не пусто) +- [ ] из webchat резолвится и коннектится `icq-prosody:5280` +- [ ] https://chat.nixg.ru грузится, Converse показывает окно входа (не бесконечная загрузка) +- [ ] WS `wss://xmpp.nixg.ru` → HTTP 101 (переключение протокола) +- [ ] `docker logs icq-prosody` без новых ошибок; компонент `telegram.nixg.ru` аутентифицирован \ No newline at end of file diff --git a/openspec/changes/icq-fix-prosody-network/specs/icq-services/spec.md b/openspec/changes/icq-fix-prosody-network/specs/icq-services/spec.md new file mode 100644 index 0000000..2660ff7 --- /dev/null +++ b/openspec/changes/icq-fix-prosody-network/specs/icq-services/spec.md @@ -0,0 +1,68 @@ +# Spec Delta — icq-services + +## ADDED Requirements + +### Requirement: Жизненный цикл сервисов — только docker compose + +Все сервисы проекта /opt/icq (prosody, webchat, slidgram) управляются исключительно +через `docker compose up -d --force-recreate `, а не ручными `docker start` +или `docker create`. Каждый сервис подключён к сети `icq_default` и резолвится по +имени сервиса (DNS-алиас из compose) внутри этой сети. + +#### Scenario: prosody запущен штатно через compose + +- **GIVEN** сервис prosody пересоздан командой `docker compose up -d --force-recreate prosody` +- **WHEN** выполняется `docker ps --format '{{.Names}} {{.Networks}}'` +- **THEN** у `icq-prosody` непустая колонка Networks, содержащая `icq_default` + +#### Scenario: prosody подключён к сети icq_default + +- **GIVEN** контейнер prosody в сети icq_default +- **WHEN** выполняется `docker network inspect icq_default` +- **THEN** в списке контейнеров есть `icq-prosody` с IPv4-адресом из 172.27.0.0/16 + +#### Scenario: резолвинг имени из веб-чата + +- **GIVEN** контейнер веб-чата в той же сети +- **WHEN** выполняется `docker exec icq-webchat getent hosts icq-prosody` +- **THEN** возвращается IP 172.27.0.x (просоди виден из веб-чата) + +## MODIFIED Requirements + +### Requirement: Доступность веб-чата chat.nixg.ru + +Контейнер `icq-prosody` имеет IP-адрес в сети `icq_default` и доступен из +`icq-webchat` по имени `icq-prosody`; веб-клиент Converse.js подключается к +wss://xmpp.nixg.ru без бесконечной загрузки. + +#### Scenario: веб-клиент открывается + +- **GIVEN** prosody в сети icq_default и доступен из webchat +- **WHEN** браузер открывает https://chat.nixg.ru +- **THEN** страница Converse.js загружается и показывает форму входа + (не бесконечная загрузка) + +#### Scenario: WebSocket-сессия устанавливается + +- **GIVEN** веб-клиент открыт +- **WHEN** Converse.js соединяется с wss://xmpp.nixg.ru +- **THEN** handshake завершается HTTP 101 и появляется форма входа + +### Requirement: Мост Telegram (Slidge) + +Компонент `telegram.nixg.ru` продолжает аутентифицироваться с prosody +(external component XEP-0114, порт 5347) после пересоздания prosody; данные моста +(./slidgram/data) не затрагиваются. + +#### Scenario: компонент аутентифицирован после пересоздания + +- **GIVEN** prosody пересоздан через compose +- **WHEN** выполняется `docker logs icq-prosody --tail 100` +- **THEN** в логах нет ошибок аутентификации, компонент telegram.nixg.ru + в списке активных (или нет критических ошибок) + +#### Scenario: мост жив после пересоздания + +- **GIVEN** prosody пересоздан через compose +- **WHEN** выполняется `docker logs icq-slidgram --tail 50` +- **THEN** нет ошибок подключения/аутентификации; мост в статусе Up \ No newline at end of file diff --git a/openspec/changes/icq-fix-prosody-network/tasks.md b/openspec/changes/icq-fix-prosody-network/tasks.md new file mode 100644 index 0000000..015be6d --- /dev/null +++ b/openspec/changes/icq-fix-prosody-network/tasks.md @@ -0,0 +1,42 @@ +# Tasks — icq-fix-prosody-network + +## 1. Снимок состояния до изменений + +- [ ] Зафиксировать `docker ps --format '{{.Names}} {{.Networks}}'` (пустая сеть у prosody) +- [ ] Зафиксировать `docker network inspect icq_default` (webchat, slidgram — без prosody) +- [ ] Снимок контейнера: `docker inspect icq-prosody > /tmp/icq-prosody-inspect-before.json` + +## 2. Пересоздание prosody через compose + +- [ ] `cd /opt/icq && docker compose up -d --force-recreate prosody` +- [ ] Дождаться `Up` (status), зафиксировать `docker ps` для prosody + +## 3. Проверка сети (внутри compose) + +- [ ] `docker ps --format '{{.Names}} {{.Networks}}'` → prolody в icq_default +- [ ] `docker network inspect icq_default` → контейнер icq-prosody с IP (172.27.0.x) +- [ ] `docker exec icq-prosody hostname -i` → непустой адрес +- [ ] `docker exec icq-webchat getent hosts icq-prosody` → резолвится (172.27.0.x) +- [ ] `docker exec icq-slidgram getent hosts icq-prosody` → резолвится + +## 4. Проверка приложения и логов + +- [ ] `docker logs icq-prosody --tail 100` — нет новых критических ошибок, + компонент telegram.nixg.ru аутентифицирован (или в активных) +- [ ] `docker logs icq-webchat --tail 50` — страница отдаётся без ошибок +- [ ] `docker logs icq-slidgram --tail 50` — без ошибок аутентификации +- [ ] `curl -i` внутренний на prosody:5280 (BOSH/WS) → ответ сервера (не refused) +- [ ] `docker compose ps` → все 3 сервиса Up, без Exited/Restarting + +## 5. Проверка снаружи (chat.nixg.ru) + +- [ ] `curl -i https://chat.nixg.ru/` → HTTP 200 (страница Converse) +- [ ] WS wss://xmpp.nixg.ru → HTTP 101 Switching Protocols +- [ ] (если доступен браузер) chat.nixg.ru открывается, форма входа видна, + без бесконечной загрузки + +## 6. Итог и документация + +- [ ] Записать результат в /opt/icq/STATUS.md (секция «Что работает» + журнал инцидента) +- [ ] Зафиксировать вывод `docker compose ps` и проверок в коммит-сообщение +- [ ] Обновить WALKTHROUGH.md при необходимости (грабли: ручной запуск вне compose → потеря сети) \ No newline at end of file diff --git a/openspec/specs/email-storage-format/spec.md b/openspec/specs/email-storage-format/spec.md new file mode 100644 index 0000000..4c2d8ba --- /dev/null +++ b/openspec/specs/email-storage-format/spec.md @@ -0,0 +1,45 @@ +# email-storage-format Specification + +## Purpose +TBD - created by archiving change email-storage-analysis. Update Purpose after archive. + +## Requirements + +### Requirement: REQ-EMA-STORAGE-001: Обоснование выбора формата хранения + +**MUST** — проект должен содержать документ `STORAGE_ANALYSIS.md` в корне +`/opt/hermes/email-assistant/`, объективно сравнивающий текущий формат +хранения (`email.md` в `//YYYY/MM/UID/`) с Maildir, MBOX и notmuch. + +#### Scenario: Документ анализа существует + +**GIVEN** файл `STORAGE_ANALYSIS.md` существует +**WHEN** его открывают +**THEN** он содержит: +- таблицу сравнения по критериям (производительность, устойчивость, интеграция, + пригодность для LLM, совместимость с MUA, масштабируемость, бэкапы) +- явную рекомендацию (остаться на текущем / мигрировать на Maildir / иное) +- обоснование рекомендации с учётом мотивации пользователя (локальная LLM + в скриптах, без облака) + +### Requirement: REQ-EMA-STORAGE-002: Ссылка из README + +**MUST** — `README.md` проекта должен содержать ссылку на `STORAGE_ANALYSIS.md`. + +#### Scenario: README содержит ссылку + +**GIVEN** `README.md` проекта +**WHEN** открываем его +**THEN** в разделе «Оценка альтернатив» (или аналогичном) есть ссылка +`[Анализ формата хранения (ФС vs Maildir)](STORAGE_ANALYSIS.md)`. + +### Requirement: REQ-EMA-STORAGE-003: Без изменения данных + +**MUST** — change не должен модифицировать, мигрировать или удалять +существующие письма в `/opt/hermes/email/`. Анализ — только документация. + +#### Scenario: Архив не изменён + +**GIVEN** архив `/opt/hermes/email/` +**WHEN** change применён +**THEN** файлы писем остаются без изменений (проверка: `find /opt/hermes/email -name 'email.md' | wc -l` — то же число, что и до change).