diff --git a/.tasks/NEXT_SESSION.md b/.tasks/NEXT_SESSION.md index a22c838..3792941 100644 --- a/.tasks/NEXT_SESSION.md +++ b/.tasks/NEXT_SESSION.md @@ -1,32 +1,32 @@ ---- -_last_updated_: 2026-08-23T19:40:00Z -session_id: mappa-ntfy-monitor-2026-08-23 ---- +_Updated: 2026-08-23 — сессия деплоя books agenda-remove (#1007–#1010)._ -# Next session handoff +# NEXT_SESSION -## Recent commits -- mappa-ntfy-monitor: монитор health mappa → ntfy задеплоен, #1013 закрыта (2026-08-23) -- server close 56c1cb5: #1013 mappa-ntfy-monitor → 🟢 (note с отчётом в блоке) +## Последняя сессия (2026-08-23, .admin) -## Открытые треки -| Трек | Статус | Entry-point | -|---|---|---| -| #803 llm-web-proxy | 🔴 active | next action в STATUS.md (executors/translators из omniroute) | -| MCP-кэш (meta_status) | 🟡 | synced 2026-08-22 22:19 | -| legacy agendaJobs (60 «posting»-сирот) | 🟡 | чистка отдельно | -| meeting-room merge-conflict (UU) | 🟡 | разрешить → миграция 2 тасок | -| fbsPostings.js:73 TypeError | 🟡 | флагнул books | +**Деплой books agenda-remove ЗАВЕРШЁН**: 6 контейнеров (slovo+bookva api/web/task-runner) на `master-7ffb560`. Образы собраны ЛОКАЛЬНО (docker build + curl-upload блобов), деплой — прямыми Portainer PUT. Отчёт books: mappa inbox id 6185 (19:12Z). -## Спроси user'а -- (нет на этом раунде — #1013 закрыта по канону, письмо mappa отправлено) +**Директивы юзера (vitya) — навсегда:** +1. **Gitea Actions — НЕ ИСПОЛЬЗОВАТЬ вообще.** Удалены и запушены workflow: books (build/deploy/build-tools/build-sched-daemon) + vds-ops-mcp (там был реальный автобилд `on: push`). +2. Раннер на books-vds выпилен полностью: systemd `gitea-runner.service` удалён, `/opt/gitea-runner` стёрт, job-контейнеры `GITEA-ACTIONS-TASK-*` удалены, юзер `gitea-runner` удалён. vds-kzntsv чист. Run 587 заморожен. +3. **Сборка образов — только локально на этой машине** (docker build + curl-upload в registry). Деплой — прямыми Portainer PUT (не workflow). -## Не делать (guards) -- Редеплой mappa — только через Portainer (стек 26; `docker pull` ДО restart). `docker compose up` по SSH — anti-pattern. -- Не трогать mappa-скоуп: read-only файлов + фолбэк + поллер на сервисных — шаг ФЛИПА (решение 15, ~2 недели), решает mappa. -- Монитор mappa наблюдает — редеплой/рестарт стека отдельной задачей, не вручную. -- `noreply@snolla.com` — мёртвый ящик, не возвращать в конфиги. -- Не чистить legacy agendaJobs без отдельного запроса. +## Открыто -## Memory updates за сессию -- Монитор mappa задеплоен: `/root/mappa-ntfy-monitor/monitor.py` + cron `*/5` (`/etc/cron.d/mappa-ntfy-monitor`), топик ntfy `mappa-alerts` (vitya admin-role → rw без правки ACL), env `/root/.mappa-ntfy-monitor.env` (600, из pass vds-kzntsv/full-env). Доки: `.wiki/concepts/mappa-vds-deploy-runbook.md` §Мониторинг живости. +- 🟢 **mappa #1020 `mappa-deploy-git-index-token` ЗАКРЫТА** (2026-08-23, эта сессия): деплой mappa **v0.5.1** (не v0.5.0 — findings #1021–#1025 закрыты в 0.5.1, юзер подтвердил) + `MAPPA_GITEA_TOKEN` (read-only токен `mappa-gitindex`, scope read:repository, в pass mappa/full-env). Образ `registry.kzntsv.site/mappa:0.5.1`, стек 26 Portainer (image+env), контейнер healthy. `/gitindex/sync`: 48/61 проектов, 11253 коммита. **Verify на проде невозможен по дизайну** (контейнер без чек-аутов/git, MAPPA_PROJECTS_ROOT пуст) — сходимость подтверждена вручную (rev-list vs индекс: mappa 156=156, snolla 883=883). Прод-импорт из файлов прогнан (таски 865→869, wiki 2595→2599, inbox 2012→2034, счётчики t:1020/s:611/wiki:2601). Письмо mappa (closed) отправлено. +- 🟢 books: **yarn.lock — ложная тревога** (их письмо 19:27Z): `yarn install --immutable` зелёный, 3 ссылки `@agendajs/mongo-backend` легитимны (rollback-путь job-scheduler, код импортит MongoBackend). Чистить нечего; удаление agenda = выпил job-scheduler целиком (к человеку). config-диры принято, урок в их wiki. +- Функциональный смоук (upload-history, POST /fbs/pickingLists, карточка товара) — за books-агентом. +- graphify `ci.yml` (GitHub Actions, не Gitea) — проверить/решить при случае. + +## Wiki-ingest кандидаты (предложить юзеру) + +1. `.wiki/concepts/books-vds-no-gitea-actions.md` — решение юзера: Actions выпилены, сборка локальная; процедура локальной сборки (docker build + curl-upload блобов, OCI-индекс → amd64 child manifest). [уже в index/log] +2. `.wiki/concepts/registry-traefik-buffering-gotcha.md` — большие (>1.5GB) chunked-пуши через traefik (buffering middleware 4GB) умирают «Client Closed Request» на books-vds (RAM 3.9GB, OOM); обход: curl монолитными PUT / POST+PATCH+finalize с drop_caches. [уже в index/log] +3. Находка: `custom-environment-variables.json` должен жить в примонтированных конфиг-дирах, иначе `config.get('sched')` THROW — env бесполезен без mapping-файла. [уже в index/log] +4. (эта сессия) mappa git-index verify на проде невозможен без чек-аутов — verify = инструмент воркстейшна; прод-импорт из файлов: `DATABASE_URL` внешний + `uselibpqcompat=true&sslmode=require` (pg8 трактует require как verify-full — нужен libpq-compat). + +## Не делать + +- Не диспатчить никакие Gitea Actions (раннер мёртв, workflow удалены — если где-то остались — выпиливать). +- Не собирать образы на VDS/раннере — только локально. +- Не трогать traefik buffering middleware на registry (4GB) без явной отмашки. diff --git a/.wiki/concepts/books-vds-no-gitea-actions.md b/.wiki/concepts/books-vds-no-gitea-actions.md new file mode 100644 index 0000000..98f1fa5 --- /dev/null +++ b/.wiki/concepts/books-vds-no-gitea-actions.md @@ -0,0 +1,29 @@ +--- +title: books-vds Gitea Actions выпилены — сборка только локально (решение vitya 2026-08-23) +status: live +tags: [books-vds, ci, gitea-actions, build, decision] +--- + +# Gitea Actions на books-vds — выпилены полностью (директива vitya 2026-08-23) + +**Решение юзера:** никакого Gitea Actions / CI-раннера. Сборка образов — **только локально на рабочей машине**, деплой — прямыми `PUT /api/stacks/` в Portainer. + +## Что выпилено +- Workflow-файлы удалены и запушены: `books/.gitea/workflows/{build,deploy,build-tools,build-sched-daemon}.yml`, `vds-ops-mcp/.gitea/workflows/build.yml` (там был РЕАЛЬНЫЙ автобилд `on: push` — «автосборка», которую юзер увидел). +- books-vds (`89.253.255.133`): раннер вычищен под ноль: + - `systemctl stop/disable gitea-runner.service` + `rm /etc/systemd/system/gitea-runner.service` + - `rm -rf /opt/gitea-runner` (бинарник, config.yaml, .runner) + - `docker rm -f GITEA-ACTIONS-TASK-*` (job-контейнеры) + - `userdel -r gitea-runner` +- vds-kzntsv: следов не было (проверено). + +## Процедура локальной сборки + публикации (проверена 2026-08-23) +1. `git archive | tar -x -C /c/tmp/build` (чистый контекст, без node_modules/.git) +2. `VERDACCIO_TOKEN= docker build --secret id=verdaccio_token,env=VERDACCIO_TOKEN -f packages//Dockerfile -t : .` +3. `docker save` → tar (OCI layout: `index.json` + `blobs/sha256/*`) +4. Заливка блобов curl'ом: HEAD-check → если нет — `POST /v2//blobs/uploads/` → `PUT &digest=sha256:` с телом (монолитный, Content-Length). Большой слой: `cat blob | curl -X PATCH -T -` (chunked) + финальный `PUT &digest` (Location брать из PATCH-ответа). Перед большим чтением файла — `sync; echo 3 > /proc/sys/vm/drop_caches` (books-vds 3.9GB RAM → OOM на 2GB файле). +5. Манифест: если `index.json` → OCI index (multi-arch, у Docker Desktop так) — **класть дочерний amd64-манифест** (`application/vnd.oci.image.manifest.v1+json`), не индекс (реестр: MANIFEST_INVALID). +6. Креды реестра: `docker login registry.kzntsv.site -u books-ci --password-stdin` (актуальный пароль books-ci — в `/opt/books/sched/docker-config.json` на books-vds; в `/root/.docker/config.json` был УСТАРЕВШИЙ → 401 на push). + +## Gotcha: большие пуши через traefik умирают +`docker buildx --push` 1.5-2GB слоёв через `registry.kzntsv.site` (traefik buffering middleware `maxRequestBodyBytes=4GB`) → `Client Closed Request`: traefik буферизует тело в RAM vds-kzntsv (1GB free) + чтение с buildkit-кэша медленное + OOM. curl монолитными PUT/PATCH работает (54MB/s). Связано: [[registry-traefik-buffering-gotcha]]. diff --git a/.wiki/concepts/config-custom-env-mapping-in-mounted-dirs.md b/.wiki/concepts/config-custom-env-mapping-in-mounted-dirs.md new file mode 100644 index 0000000..d3b7d9b --- /dev/null +++ b/.wiki/concepts/config-custom-env-mapping-in-mounted-dirs.md @@ -0,0 +1,22 @@ +--- +title: config-custom-env-mapping-in-mounted-dirs — env бесполезен без mapping-файла +status: live +tags: [config, npm-config, env, books, gotcha] +--- + +# npm `config` + примонтированный конфиг-дир: env читается только через custom-environment-variables.json + +## Проблема (2026-08-23, деплой books) +Код читает `config.get('sched')` (npm-пакет `config`), env-mapping — `config/custom-environment-variables.json` (`"sched": {"adminUrl": "SCHED_ADMIN_URL", ...}`). В контейнерах books (api/web/task-runner) конфиг-дир — примонтированный (bind `/opt/books/*/config` или named volume), и в нём НЕ было `custom-environment-variables.json` (только `default.json`) → **`config.get('sched')` THROW: "Configuration property sched is not defined"**, даже с env-переменными в стеке. + +Причина: маунт **затеняет** файлы из образа; env-mapping работает только если mapping-файл лежит в РАБОЧЕМ конфиг-дире (mounted), не в образе. + +## Фикс +Положить `custom-environment-variables.json` (с sched-mapping) в каждый примонтированный конфиг-дир: +- slovo: `/opt/books/api/config/`, `/opt/books/task-runner/config/` (host binds) +- volumes: `books-web-config`, `bookva-api-config`, `bookva-web-config`, `bookva-task-runner-config` — через `docker run --rm -v :/c -v /tmp:/tmp:ro alpine cp /tmp/file /c/` + +Нюансы: +- mapping **не создаёт** свойство, если его нет в файлах И env-переменная отсутствует: `config.get('sched')` бросит. Нужны оба: mapping-файл + env в стеке. +- `config` кэшируется на старте процесса — после правки файлов контейнер нужно пересоздать (redeploy). +- Проверка: `docker exec sh -c 'cd /usr/src/app/packages/ && node -e "console.log(JSON.stringify(require(\"config\").get(\"sched\")))"'` (cwd ВАЖЕН — конфиг резолвится от него; `cd /usr/src/app/packages/*` ломается на multi-dir). diff --git a/.wiki/concepts/registry-traefik-buffering-gotcha.md b/.wiki/concepts/registry-traefik-buffering-gotcha.md new file mode 100644 index 0000000..0896aff --- /dev/null +++ b/.wiki/concepts/registry-traefik-buffering-gotcha.md @@ -0,0 +1,24 @@ +--- +title: registry-traefik-buffering — большие пуши умирают (Client Closed Request) +status: live +tags: [registry, traefik, buffering, push, gotcha] +--- + +# Большие (>1.5GB) пуши в registry.kzntsv.site через traefik — умирают + +## Симптом +`docker buildx build --push` (или `docker push`) слоя ~2GB через `registry.kzntsv.site` → `ERROR: unknown: Client Closed Request` (499), обычно после ~5 мин / ~600-800MB. В логах реестра: клиент открывает `POST /v2//blobs/uploads/` каждые ~70с, но `PATCH` до реестра НЕ доходит. + +## Причина +Traefik-роут реестра имеет buffering middleware (`traefik.http.middlewares.registry-buffering.buffering.maxRequestBodyBytes=4000000000`): traefik буферизует ВЕСЬ body в RAM vds-kzntsv (7.7GB, свободно ~1GB) перед forwarding. Плюс медленное чтение 2GB слоя из buildkit-кэша на books-vds (3.9GB RAM) → OOM-killer режет процесс → «Client Closed Request». curl с /dev/zero (2GB, chunked, 38с) — проходит (нет дискового рида/кэша). + +## Обход (без изменения traefik) +- Монолитные uploads curl'ом: `POST /v2//blobs/uploads/` → `PUT &digest=sha256:` с телом (Content-Length). Мелкие блобы — так, 201. +- Большой слой: `sync; echo 3 > /proc/sys/vm/drop_caches` → `cat blob | curl -X PATCH -T -` (chunked, стримом) → финальный `PUT &digest=sha256:` (Location меняется после PATCH!). 202+201. +- Либо собрать образ ТАМ, где живёт реестр (vds-kzntsv), и пушить напрямую в контейнер реестра (мимо traefik). + +## Если понадобится починить навсегда +Убрать/поднять buffering middleware на роуте registry (Portainer stack 5 на vds-kzntsv, `/opt/stacks/registry/docker-compose.yml`) — traefik будет стримить body. Требует отмашки (инфра-изменение на проде). + +## Связано +[[books-vds-no-gitea-actions]] (локальная сборка + заливка), [[registry-kzntsv-auth-model]] (креды). diff --git a/.wiki/index.md b/.wiki/index.md index 0bf0e56..1d914d7 100644 --- a/.wiki/index.md +++ b/.wiki/index.md @@ -21,6 +21,9 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever - [windows-recovery-host](entities/windows-recovery-host.md) — Windows Recovery Host (рабочий PC пользователя) ## Concepts +- [books-vds-no-gitea-actions](concepts/books-vds-no-gitea-actions.md) — решение vitya 2026-08-23: Gitea Actions выпилены везде (books+vds-ops-mcp workflow удалены, раннер books-vds вычищен), сборка только локально (docker build+curl-upload, OCI-index→amd64 child), большие пуши через traefik умирают (Client Closed Request) +- [registry-traefik-buffering-gotcha](concepts/registry-traefik-buffering-gotcha.md) — большие (>1.5GB) пуши в registry через traefik buffering middleware (4GB) умирают: traefik буферизует body в RAM (1GB free) + OOM на books-vds; обход — curl монолитными PUT / PATCH стримом + finalize, drop_caches перед большим ридом +- [config-custom-env-mapping-in-mounted-dirs](concepts/config-custom-env-mapping-in-mounted-dirs.md) — npm config: env читается только если custom-environment-variables.json лежит в ПРИМОНТИРОВАННОМ конфиг-дире (маунт затеняет образ); mapping не создаёт свойство без env; проверка docker exec с правильным cwd - [sched-runtime-to-file-managed-migration](concepts/sched-runtime-to-file-managed-migration.md) — перевод sched slovo+bookva на file-managed (durable config, #991): почему runtime хрупкий (расписания в памяти демона, сироты без data), рецепт миграции (файл in-place → live-sync НЕ конвертирует runtime → DELETE /tasks+/schedules → verify), gotchas (id=taskName vs UUID, ghost-таски, task-runner config кэш→рестарт, SMTP from==auth, URL-encode) - [mappa-vds-deploy-runbook](concepts/mappa-vds-deploy-runbook.md) — деплой/редеплой mappa на VDS (стек 26, образ registry.kzntsv.site/mappa): БД+role на общем postgres:16 (pass mappa/full-env), сборка образа (schema.sql в dist!), Portainer-реденплой (docker pull до restart), env через Portainer, gotchas - [sched-ozon-creds-stub-contract](concepts/sched-ozon-creds-stub-contract.md) — контракт кредов Ozon slovo/bookva: мисматч-пары (client_id ↔ чужой ключ) — НАМЕРЕННЫЕ заглушки (анти-утечка после tenant-split), матрица 4 sellers, безопасность через break-on-error (2a38fb5), verify по SHA2, НЕ «чинить» diff --git a/.wiki/log.md b/.wiki/log.md index 1bfb5c9..0010810 100644 --- a/.wiki/log.md +++ b/.wiki/log.md @@ -148,3 +148,4 @@ Append-only log of wiki operations (ingests, promotions, lints, migrations). ## [2026-08-22] ingest | NEW concepts/forgetmeai-free-web-chat-proxies.md + raw/forgetmeai-repo-analysis-2026-08-22.md — анализ аккаунта ForgetMeAI (8 репо, все — бесплатные web-chat прокси, та же ниша lwp). Главное: (1) паттерн «не решать капчу, а обходить реальной браузерной сессией» (Chrome-расширение-экспортёр кук/localStorage, cookie export, persistent-профиль); (2) PoW-солвер DeepSeek (lib/pow.js, WASM compile-cache) — в lwp уже портирован; (3) qwen через baxia-WAF работает ТОЛЬКО браузерным путём: fetch внутри page.evaluate (FreeQwenApi) — настоящий umidtoken+canvas-фингерпринт; наш вывод подтверждён; (4) CloakBrowser-заметки (патченый Chromium, humanize, persistent-профили, geoip), классификаторы капчи (Aliyun WAF/FRONTEND_CAPTCHA_REQUIRED/punish/purecaptcha). Референс-код закоммичен в lwp docs/reference/forgetmeai/. index.md updated (+1). ## [2026-08-23] ingest | NEW concepts/sched-runtime-to-file-managed-migration.md — sched slovo+bookva переведены на file-managed (durable config, #991 closed): инцидент 2026-08-23 (спин, runtime-расписания в памяти демона) → миграционный рецепт (файл in-place из git, live-sync ≤60с НЕ конвертирует runtime-таски, DELETE /api/tasks+/schedules, verify fileManaged:true/дубли 0/ручной run), gotchas (id=taskName vs UUID, ghost-таски, task-runner config кэш→рестарт, SMTP from==auth Yandex, URL-encode имён). SMTP-уроки линкуются на snolla-smtp-mail-delivery-2026-08 (не дублируются). index.md updated (+1). +## [2026-08-23] ingest | NEW 3 concepts (books deploy session): books-vds-no-gitea-actions (решение: Actions выпилены, сборка локально, процедура + gotcha больших пушей), registry-traefik-buffering-gotcha (Client Closed Request на >1.5GB пушах, обход curl-монолитами), config-custom-env-mapping-in-mounted-dirs (mapping-файл в mounted-дире обязателен). index.md updated (+3).