- .admin claim-guard pushed + verified: claim-gate run over real .admin board skips all 4 claimable .admin tasks with reason=needs-human (zero slip-through). - Always-on bring-up started (docker mongo+reconciler) then torn down per user "don't start pollers without permission". Host task-runner never started — no claim/spawn occurred. .env/secrets.env/guard left in place, ready. - Worker config decided: this workstation; AGENT_RUNTIME=claude-opus; AGENT_CAPABILITIES=needs-internet; headless claude login suffices. - Caught a stale-claimable task (MoreThenCms cms-maljarka-https-mode-bug-fix was ⚪ ready though the bug was fixed today) — closed it. Lesson recorded: sweep boards for stale-claimable before enabling always-on. - GATE: starting pollers awaits explicit user grant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
352 lines
56 KiB
Markdown
352 lines
56 KiB
Markdown
# Admin Task Board
|
||
_Updated: 2026-06-08 — 🟢 ad-hoc fix `maljarka.tandemmebel.ru` (iis-migration follow-up): домен переехал на RUVDS корректно (DNS/TLS/IIS ок), но отдавал 502 **только на HTTPS**. Root cause не в миграции: у тенанта maljarka `dbo.Sites.SettingsData=NULL` (нет блока `httpSecure`) → MoreThenCms `SnollaMiddleware` бросает KeyNotFound на HTTPS-ветке → 502; по HTTP 200. Fix: `UPDATE dbo.Sites SET SettingsData='{httpSecure:enableHttps=true,…}' WHERE SiteId=a2476738… AND SettingsData IS NULL` + `Restart-WebAppPool snolla`. Verified maljarka:443→200 (server-local + external по 80.64.31.36), kupimknigi не задет. Audit: maljarka — единственный NULL-сайт с :443-биндингом из 25. rimiz degraded по др. причине. Concept: `.wiki/concepts/morethencms-null-settingsdata-https-502.md`._
|
||
_Updated: 2026-06-05 (вечер) — 🟡 `fix-nl-vds-reality-pq-dest`: по команде user применён server-side fix + ротация кредов. Reality dest intel→microsoft (x-ui.db + restart), сквозной тоннель через реальный :443 = HTTP 204; 32030 жив. Креды ротированы (root SSH / panel user+pass / panel secret-JWT — светились в плейнтексте; новые в `pass nl-vds-3xui/full-env`, старые отклоняются, БД-бэкап на сервере). Остался client-side: user меняет SNI в v2rayN (`pqmkayaxo2`→microsoft) + подтверждает → close._
|
||
_Updated: 2026-06-05 — заведена `fix-nl-vds-reality-pq-dest`. Новый NL VDS (213.176.64.253, 3x-UI/Xray 26.6.1): диагностирован отказ Reality-инбаунда 443 — **ML-DSA-65 (PQ) × dest `www.intel.com` (Akamai шлёт HRR)**; plain VLESS 32030 работает. Узел+root-cause в вики (`nl-vds-3xui`, `reality-pq-mldsa65-dest-incompatibility`); креды в `pass nl-vds-3xui/full-env`._
|
||
_Updated: 2026-05-31 — 🟢 `vehicles-loader-progress-deploy` **closed**: live-verify прогона Sun 31.05 06:21→07:53 MSK прошёл — progress-logging показывает движение по всем фазам (▶/батчи/✓/delete-sweep), НЕ тишина; exit 0; `importRun id=4 ok`, `reportJson errors:[]`. **Попутно найден+починен email-баг:** `STOSTAYER_MAIL_TO=site@stostayer.ru` (слалось само себе) → `vitya.kuznetsov@gmail.com` в host env (бэкап `.bak.20260531`); доставка на gmail подтверждена тест-письмом (`250 queued`). Follow-up'ы (не блокеры): units-фаза 1h31m на 100k rows = узкое место; generation `unmatched:51`; репо `config/default.json` дефолт `to` всё ещё site@ (прод перекрыт env)._
|
||
_Updated: 2026-05-30 — 🟡 `vehicles-loader-progress-deploy`: деплой 0.4.0 ВЫПОЛНЕН (build здесь → push `docker.stostayer.ru` → host pull + re-tag `:latest`=0.4.0, 0.3.0 retained). Acceptance #1 ✅. Verify-окно = natural (user-выбор, не форсим baseline → клиент без внепланового email). timer next trigger Sun 2026-05-31 06:21 MSK → live-verify journalctl в след. сессию. Open Q #1 (push кода) снят: `a74ef73` уже в origin/master._
|
||
_Updated: 2026-05-30 — заведена ⚪ `vehicles-loader-progress-deploy` (handoff из stostayer.new). Progress-logging 0.4.0 зашипан в коде (stostayer.new `a74ef73`, 24/24 теста); ops-follow-up — rebuild образа той же схемой (build здесь → push `docker.stostayer.ru` → host pull+re-tag) и снять `journalctl` с боевого прогона (закрывает не-верифицированный 5-й критерий «journalctl показывает движение»). Попутно добивает остаток email-SEND из `vehicles-loader-image-distribution`._
|
||
_Updated: 2026-05-29 — 🟢 `vehicles-loader-image-distribution` **closed**: канал поставки = собственный registry клиента `docker.stostayer.ru`, build у нас (verdaccio-депы запекаются → клиенту verdaccio не нужен), без Portainer (oneshot + systemd-timer). Доки финализированы (stostayer.new `e55cfba`). Открытие `pass stostayer/client` показало свою инфру клиента (Portainer+registry) → развилка A/B пересмотрена. Фактический prod-деплой — follow-up, ждёт grant'а._
|
||
_Updated: 2026-05-29 — **РЕЦИДИВ того же инцидента, диагноз сменён.** Вчерашняя гипотеза «оператор в cutover» **опровергнута**. Истинная причина: ES публиковал `0.0.0.0:9200` мимо traefik (free-ES без auth) → **ransom-бот** удалял индексы by-name (мимо Control #1), оставлял `read_me` с BTC-выкупом. accessLog (Control #2) пуст — бот шёл прямо в порт. **Control #3 (fix):** убрана публикация host-порта (Portainer PUT stack 33) → дыра закрыта; `epz/products/artmone` restore из `daily-2026-05-25`. Второй, отдельный баг: epz-поиск падал у ОБОИХ тенантов — `config.get("tenant")` (node-config) не задан ни в `default.json`, ни в env-маппинге, `TENANT` env был мёртвым грузом → добавил `tenant` в overlay `default.json` (slovo/bookva), резолвится, ошибки прекратились (products работал — другой код-путь). accessLog откатан (сторожил не ту дверь). Exposure-audit → ⚪ `harden-books-vds-exposed-ports`. См. `.wiki/concepts/es-destructive-delete-incident-2026-05-26.md` § «Рецидив 2026-05-29»._
|
||
_Updated: 2026-05-28 (вечер) — 🟢 `restore-elasticsearch-indices-books-vds` **closed** в ту же сессию через snapshot restore (46 сек) из `daily-2026-05-25` (полные данные, ~2ч после оригинального reindex'а). RCA: 5 индексов (включая system `.tasks`) удалены через ES API `DELETE _all` за 1 сек на 2026-05-26 10:21 UTC, **1ч 11мин после создания bookva-es** — оператор в cutover-prep попал на canonical вместо internal-only bookva-es. Caller identity не восстановим (audit log = X-Pack платный, traefik accessLog был выключен, Portainer audit = enterprise). 2 preventive фикса applied + verified: (1) ES env `action.destructive_requires_name=true` — `DELETE _all` / wildcard теперь 400; (2) traefik JSON accessLog в `/letsencrypt/access.log` — будущие DELETE оставят forensic след. См. таску + `.wiki/concepts/es-destructive-delete-incident-2026-05-26.md`._
|
||
_Updated: 2026-05-28 — **prod incident**: books-app slovo поиск товаров + EPZ сломаны, ES `elasticsearch.kzntsv.site` (books VDS stack 33) пуст (0 индексов из 3 ожидаемых; source `elasticold.kzntsv.site` rollback — все 928k docs на месте). Заведена ⚪ `restore-elasticsearch-indices-books-vds`. Окно поломки: 27.05 10:24 → 28.05 13:59, в этом окне шла работа bookva-cutover-prep (bookva-es stack 37 создавался) — возможный конфликт. См. таску для playbook'а._
|
||
_Updated: 2026-05-28 — **vds-kzntsv network-stack mismatch RESOLVED** в 13:52 MSK. Сначала ~2.5ч активного outage (05:45-08:30) + ~5.5ч на эфемерной статике до окончательного fix хостером. Revised RCA: наш netplan+networkd поверх provider's expected ifupdown stack ломал их auto-recovery когда DHCP-binding разорвался на их стороне. Fix: `systemctl mask netplan systemd-networkd` (на running system, без stop — IP и SSH сохранились), Rusonyx ребутнули + положили чистый `/etc/network/interfaces.d/ifcfg-eth0` с /18 netmask через свой `start/ipadd` procedure. Все 24 docker контейнера up. Disk after GC: 79% (132G→118G/158G). Anti-pattern закреплён: НЕ использовать netplan на Rusonyx VDS. Wiki updated с revised RCA + permanent-fix runbook + 2 quirks (#9 /18 layout, #10 ifupdown vs netplan)._
|
||
_Updated: 2026-05-27 — `modulair-rag-vds-redeploy` 🟢 **closed** в ту же сессию: 4-контейнерный стек развёрнут на VDS (Portainer stack 15), acceptance 6/6. Образы пересобраны на самом VDS (push 3.36GB через traefik с дома падал 499); env/entrypoint/minio-host скорректированы под VDS-реальность. 3 follow-up'а переданы в modulair-rag handoff._
|
||
_Updated: 2026-05-27 — заведена `modulair-rag-vds-redeploy` ⚪ (handoff из modulair-rag session). NAS-loss redeploy 4 контейнеров на VDS. Блокер MinIO снят — verified up на VDS 2026-05-27. postgres `proxy`-network reachability подтверждён (`postgres:5432` резолвится из pipeline/mcp). Спека: modulair-rag concept `nas-loss-vds-redeploy-context` + compose.yml as-is._
|
||
_Updated: 2026-05-27 (ночь, после re-open) — ops-mcp multi-tenant **activated** (stack 26 PUT + BOOKVA_MARIADB_PASSWORD env). Smoke verified: slovo/bookva DB queries возвращают tenant-specific data (АФО2 vs Ира warehouses), bookva agendaJobs count=2818. Один host-level books-ops-mcp видит обе tenant DBs._
|
||
|
||
_Updated: 2026-05-27 (ночь) — bookva-tenant deep-debug session. 6 багов одной природы (incomplete cutover-prep): (1) bookva-web без config volume → slovo DB leak; (2) bookva-{api,scheduler,task-runner} mount path /app→/usr/src/app; (3) NITRO/NUXT env не reference'или в compose; (4) bookva-scheduler без RECONCILER_ENABLED → dry-run handlers; (5) bookva-scheduler без healthcheck → CI timeout; (6) deploy.yml svc=job-scheduler vs secret=SCHEDULER mismatch. + composite agendaJobId display fix + books-web config mount (slovo also missed) + jobs.post.js agenda.db.collection→MongoClient. Ingested wiki concept tenant-overlay-config-volume-mount-path-pitfall (shared). ops-mcp multi-tenant код в image готов но stack 26 ещё не пере-PUT'нут (next session)._
|
||
|
||
_Updated: 2026-05-26 (поздний вечер) — `books-ops-mcp-host-promote` 🟢 **closed** в ту же сессию следом за заведением. Stack 26 (books-ops-mcp) in-place PUT в host-level compose без container churn. Stack 43 (bookva-ops-mcp) deleted. 2 Gitea secrets revoked. `victor/books ae3ab14` + `victor/bookva-overlay 50f5bbb` + `.admin` host-stacks/books-vds/ops-mcp.compose.yml. ops-mcp теперь management-plane (manual Portainer)._
|
||
|
||
_Updated: 2026-05-26 (поздний вечер) — заведена `books-ops-mcp-host-promote` ⚪ (deploy run#437/439 валился на bookva-ops-mcp restart-loop → hot-fix `bookva-overlay 437d024` idle-stub interim → user ideology «books VDS = host, slovo/bookva = клиентские стэки» → promote `books-docker-proxy-ro`+`books-ops-mcp` в host-level stack, drop bookva-ops-mcp). Deploy run#440 зелёный._
|
||
|
||
_Updated: 2026-05-26 (поздний вечер) — `bookva-tenant-cutover-prep` 🟢 **closed** — 6/7 в одну сессию: Steps 1+2+3+4+5+7. Step 6 delayed по spec (1-2 нед до cutover). bookva-ozon-mcp deferred (image не в registry). MinIO bucket copy deferred (cutover-time). 9 bookva Portainer stacks created (3 active: db/mongo/es internal-only; 6 stopped pre-cutover). bookva-overlay 4 commits: templates+mariadb:10.6+mongo:4.2+api internal-only+depends_on removed._
|
||
|
||
_Updated: 2026-05-26 (вечер) — `bookva-tenant-cutover-prep` 🟡 paused, 4/7 steps done в этой сессии: Steps 1+5+7 closed, Step 3 partial (6 empty volumes + 4 populated). Maintenance-window remaining: Step 2 stacks, Step 3 stateful (Mongo/MariaDB/MinIO), Step 4 login-gate. bookva-overlay templates align'нуты к prod shape + design v3 (commit `5b173de` pushed). books `75ea320` pushed (deploy/web.compose.yml embed-api refs). Pass entry `gitea/victor-books-ci-bookva-overlay` added._
|
||
|
||
_Updated: 2026-05-26 — заведена `bookva-tenant-cutover-prep` ⚪ (7-step prep на books VDS перед поднятием Bookva стека). Code-side done в victor/books master: embed-api с zod^4 fix, ES endpoint per-tenant, PWA redirect banner, deploy.yml per-tenant, overlay-репо finalize, ntfy per-tenant. Осталась только Portainer/Gitea-secrets/VDS работа._
|
||
|
||
_Updated: 2026-05-25 (`iis-migration-to-ruvds` 🟢 closed Phase 1 per user decision — 9/24 hostnames live на RUVDS, source IIS оставлен running. `migrate-elasticsearch-to-books-vds` 🟢 closed ранее сегодня. 16 IIS hostnames + LE renewal pipeline + decommission — descoped в Closure note, не отдельные tracker tasks.)_
|
||
|
||
## 🟡 [fix-nl-vds-reality-pq-dest] — Reality-инбаунд 443 на NL VDS (213.176.64.253): server-side done, ждёт client-side
|
||
**Status:** 🟡 server-side fix + cred-rotation применены и проверены 2026-06-05; остался один client-side шаг (user меняет SNI в v2rayN) + подтверждение → закрыть.
|
||
**Where I stopped:** ✅ dest `www.intel.com`→`www.microsoft.com` на инбаунде 443 (x-ui.db + restart), сквозной тоннель через реальный :443 (SNI microsoft) = HTTP 204; 32030 жив. ✅ Креды ротированы (root SSH pass / panel user+pass / panel secret-JWT — оригиналы светились в плейнтексте), всё в `pass nl-vds-3xui/full-env`, БД-бэкап на сервере. Root cause: ML-DSA-65 (PQ) × intel/Akamai (HRR), разбор в `.wiki/concepts/reality-pq-mldsa65-dest-incompatibility.md`.
|
||
**Next action:** user в v2rayN профиль `pqmkayaxo2`: SNI → `www.microsoft.com`, reconnect. Подтвердит, что Reality поднялся → 🟢 close. См. [fix-nl-vds-reality-pq-dest.md](fix-nl-vds-reality-pq-dest.md).
|
||
**Branch:** n/a (admin ops)
|
||
<!-- created-by: vitya@.admin-exec / 2026-06-05 / trigger: user-задача "не получается vless+Reality" -->
|
||
|
||
---
|
||
|
||
## 🟢 [vehicles-loader-progress-deploy] — closed 2026-05-31 — 0.4.0 задеплоен + live-verify прошёл. Прогон Sun 31.05 06:21:48→07:53:14 MSK на changed-выгрузке: журнал показал движение по всем фазам (▶ branches/vehicles/units/delete-sweep, батч-прогресс `manufacturers 18/183…`, `units 3/26…`, `✓ done: N rows`, per-model delete-sweep), НЕ тишина. exit 0, `importRun id=4 ok`, `reportJson errors:[]`. **Email-баг найден+починен:** `STOSTAYER_MAIL_TO` слался сам себе (`site@stostayer.ru`) → исправлен на `vitya.kuznetsov@gmail.com` в host env (бэкап `.bak.20260531`), доставка на gmail подтверждена тест-письмом. Все 4 acceptance ✅. См. [vehicles-loader-progress-deploy.md](vehicles-loader-progress-deploy.md).
|
||
**Follow-ups (не блокеры, в stostayer.new):** (1) units-фаза 1h31m на 100529 rows — узкое место, батч-инсёрт/индексы; (2) generation `unmatched:51` — проверить не теряем ли данные; (3) `config/default.json` дефолт `to: site@stostayer.ru` выровнять (прод перекрыт env).
|
||
**Branch:** n/a
|
||
<!-- created-by: vitya@stostayer.new-session / 2026-05-30 / handoff: stostayer.new/.tasks/vehicles-loader-progress-logging.md -->
|
||
<!-- closed-by: vitya@.admin-exec / 2026-05-31 / live-verify journalctl прошёл + email-recipient баг починен+verified -->
|
||
|
||
---
|
||
|
||
## 🟢 [restore-elasticsearch-indices-books-vds] — closed 2026-05-28 — snapshot restore из `kreknin:daily-2026-05-25` за 46 сек (epz=820604, products=105922, artmone=2621, counts == source). Forensics: 5 индексов удалены через ES API `DELETE _all` 26.05 10:21 UTC, через 1ч 11мин после создания `bookva-es` — оператор в cutover-prep попал на canonical вместо internal-only bookva. Caller identity unrecoverable (audit log = X-Pack платный, traefik accessLog был выключен). 2 preventive фикса applied: ES env `action.destructive_requires_name=true` + traefik JSON accessLog в `/letsencrypt/access.log`. См. [restore-elasticsearch-indices-books-vds.md](restore-elasticsearch-indices-books-vds.md) § Closure + `.wiki/concepts/es-destructive-delete-incident-2026-05-26.md`.
|
||
**Branch:** n/a
|
||
<!-- created-by: vitya@books-session / 2026-05-28 / trigger: prod 404 index_not_found_exception на /api/epz/search + /api/products/search -->
|
||
<!-- closed-by: vitya@.admin-exec / 2026-05-28 / snapshot restore + 2 preventive fixes verified -->
|
||
<!-- REOPENED+RECLOSED: vitya@.admin-exec / 2026-05-29 / рецидив — true RCA = exposed :9200 ransom-бот, Control #3 (порт закрыт) + re-restore + epz tenant-config fix -->
|
||
|
||
---
|
||
|
||
## ⚪ [harden-books-vds-exposed-ports] — закрыть публично торчащие host-порты на books VDS (89.253.255.133)
|
||
**Status:** ready
|
||
**Where I stopped:** exposure-audit сделан (ES :9200 уже закрыт в рамках инцидента); mongo/books-db/bookva-db/minio/bookva-minio + rsync:873 торчат на `0.0.0.0`, все credentialed (auth включён, не дыра-нараспашку как free-ES).
|
||
**Next action:** по каждому сервису определить — приложение коннектится через docker-сеть или host-порт; нужен ли внешний admin (тогда SSH-туннель / DOCKER-USER IP-allowlist вместо публичного порта). Начать с mongo (EOL 4.2 + reuse пароля).
|
||
**Branch:** n/a (admin ops)
|
||
<!-- created-by: vitya@.admin-exec / 2026-05-29 / trigger: exposure-audit во время ES ransom-incident — 5+ stateful-сервисов с публичными host-портами -->
|
||
|
||
---
|
||
|
||
## 🟢 [modulair-rag-vds-redeploy] — closed 2026-05-27 — 4-контейнерный стек развёрнут на VDS, acceptance 6/6
|
||
|
||
NAS помер → 4 контейнера пропали → fresh redeploy на VDS (89.253.255.94). Portainer stack id=15. **Acceptance 6/6 green:** 4 контейнера up без restart-loop; lightrag Uvicorn :9621; `https://modulair-mcp.kzntsv.site`→200; pipeline+tier1 0% CPU; pipeline-лог без postgres/minio ошибок.
|
||
|
||
Таска писалась по stale-предпосылкам — по ходу исправлено (см. [modulair-rag-vds-redeploy.md](modulair-rag-vds-redeploy.md) Decisions): registry-образы отсутствовали (registry переустановлен 2026-05-20) → **rebuild на VDS** (push 3.36GB tier1-слоя с дома падал 499 через traefik → собрал на самом VDS, push локальный); `MINIO_ENDPOINT`=`minio.vds.kzntsv.site` (не `minio.kzntsv.site`=books VDS); traefik entrypoint `https`→`websecure` (NAS-имя в compose-лейбле); DB+bucket+scoped-svcacct созданы; ROUTERAI key в pass; DNS поправил user.
|
||
|
||
**Follow-ups (не блокеры acceptance):** modulair-rag/compose.yml entrypoint-фикс в репо; portainer-stack.md под VDS; lightrag embedding binding=ollama/model=None — проверить ROUTERAI_* маппинг. Все переданы в handoff (consumer repo / parallel session).
|
||
**Branch:** master
|
||
<!-- closed-by: vitya@.admin-exec / 2026-05-27 / Portainer stack 15 deployed, acceptance 6/6 verified -->
|
||
<!-- created-by: vitya@modulair-rag-session / 2026-05-27 / handoff: user gave deploy to .admin (has VDS access) -->
|
||
<!-- created-by: vitya@modulair-rag-session / 2026-05-27 / handoff: user gave deploy to .admin (has VDS access) -->
|
||
|
||
---
|
||
|
||
## 🟢 [migrate-elasticsearch-to-books-vds] — closed 2026-05-25 — ES indices с Windows (elasticold.kzntsv.site, 7.10.1) → books VDS (elasticsearch.kzntsv.site, 7.10.0). 3 indices, 928616 docs. Reindex-from-remote через `reindex.remote.whitelist` env, добавленный в Portainer stack 33. Pre-migration snapshot в kreknin repo как rollback. Consumer configs sed'd, 3 containers restarted, smoke green. Source НЕ выключен.
|
||
|
||
См. [migrate-elasticsearch-to-books-vds.md](migrate-elasticsearch-to-books-vds.md) § Closure note.
|
||
|
||
## 🟢 [books-vds-stacks-to-portainer] — closed 2026-05-25 — 6 SSH-compose стеков на books VDS (89.253.255.133) мигрированы в Portainer-managed (endpoint 1, https://portainer.kzntsv.site). Skip traefik + portainer (management plane). Adapter `scripts/books-vds-portainer-migration/migrate.sh`. Wiki: [portainer-stack-management-books-vds.md](../.wiki/concepts/portainer-stack-management-books-vds.md). Backup pipeline bind paths preserved (verified by inspection, full run pending next 06:00 MSK).
|
||
|
||
## 🟢 [books-vds-backup-daily-kreknin] — closed 2026-05-25 — daily backup books VDS (89.253.255.133, host4g.ru, CentOS 7) → kreknin в 06:00 MSK. DB dumps (mariadb/mongo×2) + ES snapshot via REST → rsync 4.87GB → ntfy/email (phone+inbox ✓). ES path.repo bootstrap + snapshot repo `kreknin` registered. См. [books-vds-backup-daily-kreknin.md](books-vds-backup-daily-kreknin.md).
|
||
|
||
## 🟢 [unify-backup-notifications] — closed 2026-05-25 — единый формат push + email для VDS/RUVDS/windows-host (3 scripts), VDS run.sh импортирован в repo. См. [unify-backup-notifications.md](unify-backup-notifications.md) § Closed. windows-host self-deploy остаётся на user'е (elevated PS).
|
||
|
||
---
|
||
|
||
## 🟢 [bookva-tenant-cutover-prep] — closed 2026-05-26 — 7/7 (Step 6 descoped) + extension (bookva-minio + external port-bind)
|
||
|
||
Все ops-шаги VDS-side выполнены: Gitea secrets ✓ (7 шт), **10/11** Portainer bookva stacks ✓ (ozon-mcp deferred — image отсутствует в registry; bookva-minio добавлен post-closure), volumes ✓ (db+mongo cp -a, es+ntfy empty, 4 config volumes populated, bookva-minio-data cp с books bucket), login-gate SQL ✓ (bookva-db users id≥3 → UUID random pwd), DNS ✓ (pre-existed), books-web embed-api switch ✓, **external access** ✓ (bookva-db:33306 + bookva-minio:9001).
|
||
|
||
**Контекст dev-source:** victor/books `.wiki/concepts/tenant-split.md` rev v3. Code-side: `5e28fd1` embed-api+zod^4, `4a9cafc` ES endpoint, `c1e58cf` PWA redirect, `88df172` deploy.yml per-tenant. Overlay-repos: **bookva-overlay/main `8bffd68`** (templates aligned + mariadb:10.6 + mongo:4.2 + api internal-only + depends_on removed).
|
||
|
||
**Done в сессии 2026-05-26:**
|
||
- ✅ Step 1: 7 Gitea secrets (BOOKVA_OVERLAY_TOKEN, HEALTHCHECK_BOOKVA_{API,WEB}_URL, PORTAINER_STACK_ID_BOOKVA_{API=45,WEB=46,SCHEDULER=47,OPS_MCP=43}). books `2f7b539` (secret name fix).
|
||
- ✅ Step 2: 9/10 Portainer stacks. Stack IDs: db=34, mongo=36, es=37, ops-mcp=43, ntfy=44, api=45, web=46, scheduler=47, task-runner=48. ozon-mcp deferred (image not in registry). User-facing stacks (api/web/scheduler/task-runner/ops-mcp/ntfy) **stopped** post-create (Status=2) — bookseller.kzntsv.site returns 000 как desired pre-cutover state. db/mongo/es оставлены running (внутренние, useful для testing).
|
||
- ✅ Step 3: 6 volumes created. **bookva-db-data (4.7G)** = cp -a `/usr/docker/books-db/data` (downtime 59s). **bookva-mongo-data (517M)** = cp -a `/opt/books/job-scheduler/mongo/db` (downtime 5s). 4 config volumes populated из corrected overlay templates (api, scheduler, task-runner, web-branding). 2 empty by design (ntfy-data, es-data — Phase 2 snapshot/restore). MinIO deferred (no maintenance impact — `mc cp books bookva` at cutover, не rename).
|
||
- ✅ Step 4: bookva-db login-gate `UPDATE users SET password=UUID() WHERE id_user NOT IN (1,2)` — 3 users scrambled (id=3,4,5), id=1 (Bookva founder) + id=2 (Slovo founder) untouched. books-db verified unaffected.
|
||
- ✅ Step 5: DNS `bookseller.kzntsv.site` → 89.253.255.133 (был pre-existing, closed by inspection).
|
||
- ✅ Step 7: Portainer books-web stack 24 PUT atomic (compose+env). Env: `NUXT_PUBLIC_BOOKS_API_URL=/api`, `NUXT_AUTH_TOKEN`, `NUXT_JWT_SECRET_KEY`. Embed-api на bookva.kzntsv.site/api/* живёт (smoke green, auth identical to books-api). books `75ea320` (compose template synced). Soak 24-48ч до books-api shutdown micro-task.
|
||
- 🔵 Step 6: delayed по spec (за 1-2 нед до cutover — `NUXT_PUBLIC_BOOKVA_REDIRECT_URL=https://bookseller.kzntsv.site` env на books-web для PWA redirect banner user.id=1).
|
||
|
||
**Deferred (отдельной micro-task):**
|
||
- `bookva-ozon-mcp` stack — image `registry.kzntsv.site/books-ozon-mcp:master` не существует в registry. Нужен build в victor/books CI (ozon-mcp service в build.yml?). Скорее всего service ещё не настроен — отдельная task'а.
|
||
- Mongo agenda cleanup partial — 7 jobs с idSeller=2 удалены, осталось 2817 jobs (большинство — system-wide без idSeller). При cutover проверить если нужен дальнейший cleanup.
|
||
|
||
**Branch:** master | **Closure pushes:** books `2f7b539`+`75ea320` (master); bookva-overlay `5b173de`→`8bffd68` (main): templates align + mariadb:10.6 + mongo:4.2 + api internal-only + depends_on removed. Pass: `gitea/victor-books-ci-bookva-overlay`.
|
||
<!-- created-by: vitya / 2026-05-26 / Phase 2 cutover prep после tenant-split code-side done -->
|
||
<!-- progress-2026-05-26: 6/7 closed одну сессию: Steps 1+2+3+4+5+7. Step 6 delayed by design. bookva-ozon-mcp deferred (image build needed). MinIO bucket copy deferred (cutover-time) -->
|
||
|
||
---
|
||
|
||
## 🟢 [books-ops-mcp-host-promote] — closed 2026-05-26 — host-promote ops-mcp+docker-proxy в `.admin/host-stacks/books-vds/`, drop bookva-ops-mcp
|
||
|
||
Stack 26 (books-ops-mcp) in-place PUT без container churn (env MARIADB_PASSWORD preserved). Stack 43 (bookva-ops-mcp) deleted. Gitea secrets `PORTAINER_STACK_ID_BOOKVA_OPS_MCP` + `PORTAINER_STACK_ID_OPS_MCP` revoked. ops-mcp убран из tenant=slovo|bookva pipeline (deploy.yml). Management-plane: image updates через Portainer UI manual.
|
||
|
||
**Design locks (см. [books-ops-mcp-host-promote.md](books-ops-mcp-host-promote.md) § Closure note):** Q1 location=`.admin/host-stacks/`, Q2 deploy=manual Portainer, Q3 MariaDB scope=slovo's only (Option A), Q4 config volume path unchanged, Q5 audit прочих host-level кандидатов punt.
|
||
|
||
**Commits:** `victor/books ae3ab14` + `victor/bookva-overlay 50f5bbb` + `.admin` (this commit).
|
||
**Branch:** master
|
||
<!-- created-by: vitya / 2026-05-26 / trigger: deploy run#437/439 fail + user ideology clarification -->
|
||
<!-- closed-by: vitya / 2026-05-26 / Portainer in-place PUT stack 26 + delete stack 43 + 2 secrets revoked + 3 commits -->
|
||
|
||
---
|
||
|
||
## ⚪ [stateful-split-volume-copy] — поднять `bookva-db` + `slovo-db` на VDS как копии `books-db` через `cp -a` volume
|
||
|
||
Ops-таска для Фазы 1 дизайна `tenant-split` из victor/books. Scope сужен 2026-05-25 (user: «просто поднимем 2 БД»): только MariaDB volume copy + up 2 контейнеров. Mongo / MinIO / DELETE / app-стеки — отдельными ops-тасками потом.
|
||
|
||
**Контекст dev-source:** дизайн в victor/books `.wiki/concepts/tenant-split.md` § «Фаза 1». Compose-файлы готовы в `bookva-overlay` / `slovo-overlay` (commit d0eb210 в books).
|
||
|
||
**Acceptance:** `docker ps` показывает живые `bookva-db` + `slovo-db`, оба отвечают `SELECT 1`. Текущий `books-db` стек снова в строю после maintenance window.
|
||
|
||
**Status:** ready
|
||
**Where I stopped:** (not started — lean playbook готов в [stateful-split-volume-copy.md](stateful-split-volume-copy.md))
|
||
**Next action:** под maintenance window 5-10 мин на VDS — execute 5 команд из task-файла. Backup → stop books-db → cp -a в 2 volume'а → up 2 новых контейнера через Portainer → start books-db.
|
||
**Blocker:** —
|
||
**Branch:** master
|
||
<!-- created-by: vitya / 2026-05-25 / moved from victor/books .tasks/ (scope is ops/VDS, not books-code) -->
|
||
|
||
---
|
||
|
||
<!--
|
||
Status legend:
|
||
🔴 Active — only one at a time
|
||
🟡 Paused — in progress, resumable
|
||
⚪ Ready — defined, not started
|
||
🟢 Done — moved to ARCHIVE.md once committed
|
||
🔵 Blocked — waiting on external input
|
||
-->
|
||
## 🟢 [iis-migration-to-ruvds] — closed 2026-05-25 per user decision — Phase 1 done: RUVDS infra setup + 8.66GB scp + IIS recreate + 25 HTTPS SNI bindings (LE R13 expire 2026-07-22) + 9 hostnames (kupimknigi.spb.ru, emspb±www, pilorama98±www, labtools.pro±www, rimiz±www) live на 80.64.31.36 with correct per-tenant content. 16 hostnames остаются на windows source per user pace (incl. tandemmebel scope-exception). Source IIS:8089 + traefik routes ALIVE для rollback. Decommission + LE renewal + cleanup descoped в Closure note. См. [iis-migration-to-ruvds.md](iis-migration-to-ruvds.md) § Closure note.
|
||
|
||
<!-- HISTORICAL details preserved below — task closed, content kept до prune'а board'а -->
|
||
|
||
**Status:** closed 2026-05-25
|
||
**Where I stopped:** 2026-05-24 — `kupimknigi.spb.ru` + `emspb.ru` (+ `www.emspb.ru`) DNS A flipped на `80.64.31.36`, authoritative `ns1.reg.ru` правильный, public resolver caches expire'ятся (8.8.8.8=~6h, 1.1.1.1=~24h max). RUVDS state: snolla site (8.66 GB / 44725 files) transferred + IIS recreated + 25 HTTPS SNI bindings c LE certs (R13, valid до 2026-07-22), 7 prod hostnames live-smoke через VDS (третья сеть) → 200 OK / correct content. Source IIS:8089 + traefik routes ALIVE — rollback ready. **2026-05-25 close-time DNS probe:** ещё 5 пар hostnames swap'нуты user'ом silently — итого 9 на RUVDS, 16 на source.
|
||
**Findings зафиксированы в** [iis-migration-to-ruvds.md](iis-migration-to-ruvds.md) Decisions log: (1) outbound 445 блокирует home ISP, не RUVDS-FW → SSH/scp = canonical transfer-метод; (2) home network HTTP-middlebox mangles Host header for direct external HTTP — real end-users не пострадают, тестировать через VDS; (3) traefik acme.json → IIS PFX recipe работает (extract + openssl pkcs12 -export + Import-PfxCertificate + AddSslCertificate by thumbprint); (4) IIS 10 HTTP/2 default; (5) `maljarka.tandemmebel.ru` + 3 rimiz hostnames → 502/404 — pre-existing CMS-tenant config gap, не migration defect.
|
||
|
||
**Scope exception (2026-05-24 user decision):** `tandemmebel.ru` + `www.tandemmebel.ru` ОСТАЮТСЯ на windows-IIS на неопределённый срок (отдельное решение user'а — site не готов к cutover ровно сейчас). DNS НЕ свапать. Cert на RUVDS уже импортирован, binding existing — может оставаться idle, traffic не пойдёт.
|
||
|
||
**Next action:**
|
||
1. **Снизить DNS TTL** в reg.ru на оставшиеся **22 hostnames** до 300s — `pilorama98.ru`, `labtools.{ru,pro}`, `snolla.com` + 11 snolla subdomains + `rimiz.{ru,snolla.com}` + `maljarka.tandemmebel.ru` (но не `tandemmebel.ru` — см. Scope exception). Сократит cache-tail с 24h до 5 мин.
|
||
2. **24h soak kupimknigi + emspb** — verify через cache-clean resolver (потом curl без `--resolve`).
|
||
3. **Bulk DNS swap** оставшихся 22 hostnames на 80.64.31.36 (single sitting). **tandemmebel.ru / www.tandemmebel.ru — пропустить.**
|
||
4. **1-week prod soak** с RUVDS как live source для migrated hostnames.
|
||
5. **Decommission source IIS:8089** только для migrated hostnames (snolla catch-all site нельзя decommission'ить пока tandemmebel.ru на нём же). Решение defer до tandemmebel migration.
|
||
6. **LE renewal pipeline** — win-acme + HTTP-01 на RUVDS после full cutover (LE certs expire 2026-07-22, soak window до ~07-15).
|
||
7. **Cleanup migration-temp:** `Remove-NetFirewallRule 'smb-from-source','ssh-from-source'` на RUVDS, удалить `~/.ssh/ruvds-iis-migration*` на source, очистить `C:\ProgramData\ssh\administrators_authorized_keys` на RUVDS.
|
||
|
||
Полный план + Completed + Open questions + Remaining steps — в [iis-migration-to-ruvds.md](iis-migration-to-ruvds.md).
|
||
**Branch:** master
|
||
<!-- created-by: user-decision / 2026-05-22 / trigger: RUVDS purchased -->
|
||
<!-- partial-cutover-by: vitya / 2026-05-24 / kupimknigi + emspb DNS flipped, 22 hostnames pending, tandemmebel.ru excluded -->
|
||
<!-- scope-narrowed: vitya / 2026-05-24 / tandemmebel.ru stays on windows-IIS indefinitely -->
|
||
**Branch:** master
|
||
|
||
---
|
||
|
||
## ⚪ [infra-inventory] — two-tier инвентаризация: public-карта в global wiki + admin-detailed runbook локально
|
||
|
||
**Status:** ready
|
||
**Where I stopped:** (not started — создана 2026-05-22 из инцидента `gitea.` vs `git.` + перепутанный source/dest IP в traefik access-логах; scope расширена в тот же день — single-page → two-tier per user «у все общее представление, у админа полное»)
|
||
**Next action:** см. полный план в `infra-inventory.md`. Шаги: (1) probing-фаза одна для обоих — `nslookup` известных subdomain'ов + `vds-ops`/`synology-ops` `ops_docker_ps`/`inspect` + `knowledge_search` по существующим bootstrap-concept'ам + `rg "kzntsv.site"` по `~/projects/`. (2) Write A — light public в `projects-wiki/concepts/infrastructure-inventory.md` (машины, canonical hostnames, anti-aliases) → `knowledge_ingest`. (3) Write B — heavy admin в `.admin/.wiki/concepts/infrastructure-stack.md` (per-stack: версии, internal IPs, volumes, depends-on, backup paths, DR pointers) → commit + push. (4) Cross-refs A↔B + pointer в `.admin/.wiki/CLAUDE.md` Domain conventions.
|
||
**Branch:** n/a
|
||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: .workshop / 2026-05-22 / trigger: gitea-hostname-confusion-incident -->
|
||
<!-- scope-expanded: 2026-05-22 — single-page → two-tier (public + admin-detailed) -->
|
||
|
||
---
|
||
|
||
## 🔵 [books-vds-bookva-bootstrap] — Ops-таска для Фазы 4 дизайна `tenant-split` из victor/books (см. `mcp__projects-meta__knowledge_get slug=concepts/tenant-split`). Поднять новый VDS для Bookva — billing на юрлицо Bookva (учредители развелись, каждое юрлицо платит инфру напрямую провайдеру).
|
||
|
||
**Контекст dev-source:** дизайн в victor/books `.wiki/concepts/tenant-split.md`; brainstorm trace `~/projects/.workshop/.archive/2026-05-24-books-tenant-split.md`.
|
||
|
||
**Direction:** Slovo остаётся на текущем VDS, Bookva переезжает на новый.
|
||
|
||
**Acceptance:**
|
||
- Новый VDS у провайдера (Rusonyx или другой по предпочтению Bookva), billing-account оформлен на юрлицо Bookva.
|
||
- Docker + traefik + certbot развёрнуты.
|
||
- DNS `*.bookva.<tld>` готов резолвиться на новый IP (фактический switch — в `books-dns-cutover-bookva`).
|
||
- SSH-ключи: только инженерные (core-разраб + админ Bookva, если есть). Аналитики Bookva — НЕ имеют SSH к новому VDS.
|
||
|
||
**Status:** blocked
|
||
**Where I stopped:** (not started)
|
||
**Next action:** **Pre-step:** прочитать `concepts/tenant-split.md` § «Фаза 4» в victor/books (через `mcp__projects-meta__knowledge_get slug=concepts/tenant-split` или git clone victor/books → `.wiki/concepts/tenant-split.md`).
|
||
|
||
1. Согласовать с учредителем Bookva: provider, configuration (CPU/RAM/disk), регистрация billing'а на юрлицо Bookva.
|
||
2. Provision VDS, базовая настройка (firewall, fail2ban, SSH ключи).
|
||
3. Установить Docker + docker-compose.
|
||
4. Развернуть traefik + certbot из overlay-репо `victor/books-bookva/deploy/traefik.compose.yml`.
|
||
5. Подготовить DNS-зону `bookva.<tld>` (создать A-records, TTL=300 для возможности быстрого switch'а).
|
||
6. Smoke: `curl https://placeholder.bookva.<tld>` → 200 от nginx-placeholder или из traefik.
|
||
7. Документировать в `victor/books-bookva/README.md`: hostname, IP, как ssh, runbook smoke-теста.
|
||
8. Закрыть с note: «VDS поднят, IP=<...>, готов к stack deploy».
|
||
**Blocker:** `OpeItcLoc03/admin books-stateful-split-execution` (Фаза 1 — physical split на shared VDS, bookva-* контейнеры живут) + `victor/books per-tenant-backup-and-observability` (Фаза 2 — per-tenant backups настроены до физического переезда)
|
||
**Branch:** n/a
|
||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-24T12:02:19.507Z -->
|
||
|
||
---
|
||
|
||
## 🔵 [books-dns-cutover-bookva] — Ops-таска для Фазы 4, шаг 5 дизайна `tenant-split` из victor/books. DNS switch `*.bookva.<tld>` → новый VDS IP, с parallel-run старого bookva-стека на shared VDS 7 дней без публичного hostname.
|
||
|
||
**Контекст dev-source:** дизайн в victor/books `.wiki/concepts/tenant-split.md` § «Фаза 4».
|
||
|
||
**Acceptance:**
|
||
- DNS `*.bookva.<tld>` (или конкретный hostname Bookva — определяется учредителем) указывает на новый VDS IP.
|
||
- Старый bookva-стек на shared VDS остаётся запущенным, **без публичного hostname** (traefik labels убраны или disabled), доступен только по docker-сети для возможного отката.
|
||
- Smoke с двух разных сетей (mobile + офисный wifi) — `https://<bookva-hostname>` отвечает с нового VDS.
|
||
- Per-VDS backup'ы на новом VDS подтверждены — есть snapshot спустя 24ч после DNS-switch'а.
|
||
- Через 7 дней parallel-run без откатов — decommission старого bookva-стека (см. Фаза 4, шаг 7 в spec).
|
||
|
||
**Status:** blocked
|
||
**Where I stopped:** (not started)
|
||
**Next action:** **Pre-step:** прочитать `concepts/tenant-split.md` § «Фаза 4, шаги 4–7» в victor/books.
|
||
|
||
1. Maintenance window 1–2ч (объявить за 7 дней).
|
||
2. Финальная синхронизация: `mysqldump mariadb-bookva` на текущем VDS → `mysql` на новом VDS (если schema/data разошлись с момента Фазы 2).
|
||
3. Smoke на новом VDS до DNS-switch'а: hosts-файл override → проверить login + base flow.
|
||
4. DNS-switch: меняем A-record(s) для bookva-hostname на new IP. TTL=300 уже стоял (Phase 4 step 1).
|
||
5. Через 1ч (TTL expiry + propagation): smoke с двух сетей.
|
||
6. На старом VDS — отключить traefik labels для bookva-стека (контейнеры продолжают работать, но не доступны снаружи).
|
||
7. **Parallel-run 7 дней.** Каждый день — smoke. Per-VDS backup на новом VDS — проверить хотя бы 1 успешный snapshot.
|
||
8. Если за 7 дней проблем нет → закрыть с note «cutover stable». Если есть — DNS rollback на старый IP, follow-up debug task в victor/books.
|
||
9. **Decommission** старого bookva-стека на shared VDS (отдельный шаг, не в этой таске — финальный backup в архив + `docker compose down` + volume drop).
|
||
**Blocker:** `books-vds-bookva-bootstrap` + victor/books `pwa-redirect-handoff` (SW bump выкачен в shared API за 1–2 недели до этой таски).
|
||
**Branch:** n/a
|
||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-24T12:02:41.503Z -->
|
||
|
||
---
|
||
|
||
## ⚪ [books-bookva-user-whitelist-gathering] — **Процессная** ops-таска для Фазы 3, шаг 1 дизайна `tenant-split` из victor/books. Получить от учредителя Bookva письменный список пользователей, которые допущены к Bookva-инсталляции. Без этого списка cutover не возможен — иначе утечка доступа: либо лишние юзеры получат доступ к Bookva (через копирование «всех users»), либо легитимные юзеры заблокированы (через пустой whitelist).
|
||
|
||
**Direction:** Bookva — новая инсталляция, начинается с whitelist'а (закрытый список). Slovo — остаётся на текущем стеке, получает копию всех текущих users (статус-кво).
|
||
|
||
**Контекст dev-source:** дизайн в victor/books `.wiki/concepts/tenant-split.md` § «Двухуровневая изоляция пользователей → App-level» и § «Фаза 3, шаг 1».
|
||
|
||
**Не блокируется ничем** — можно начинать gathering сразу, лаг до cutover'а может быть значительным.
|
||
|
||
**Acceptance:**
|
||
- Письменный список от учредителя Bookva (email или подписанный документ): ФИО + role (если знают).
|
||
- Список зафиксирован в `OpeItcLoc03/admin/.wiki/concepts/books-bookva-whitelist.md` или в отдельной таблице.
|
||
- Для каждой строки списка сверка с текущей `users`-таблицей shared БД: user существует / роль соответствует / email актуален.
|
||
- Любые расхождения (запрошенный user не существует в shared / роль другая) — обработаны: создать новый user в Bookva-БД post-cutover ИЛИ скорректировать список с учредителем.
|
||
|
||
**Status:** ready
|
||
**Where I stopped:** (not started)
|
||
**Next action:** 1. Отправить учредителю Bookva формальный запрос (email/мессенджер): «Для tenant-split нужен список пользователей, которые останутся в Bookva после разделения. Формат: ФИО + роль + email/login. Список будет применён на cutover'е как whitelist».
|
||
2. Дождаться ответа (это может занять дни/недели — нормально).
|
||
3. Получив список — сверить с `users`-таблицей shared БД:
|
||
```sql
|
||
SELECT id, login, email, role FROM users WHERE email IN (<list>) AND deleted_at IS NULL;
|
||
```
|
||
4. Разобрать расхождения с учредителем (missing / role mismatch / inactive).
|
||
5. Зафиксировать финальный список в `OpeItcLoc03/admin/.wiki/concepts/books-bookva-whitelist.md` (или в local-only encrypted file если NDA-чувствительно).
|
||
6. Финальный список становится input'ом для Фазы 3, шаг 1: при настройке Bookva-БД в неё попадают **только** эти users.
|
||
7. Закрыть с note: «whitelist (N users) подтверждён учредителем, готов к применению на cutover'е».
|
||
**Branch:** n/a
|
||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-24T12:03:18.548Z -->
|
||
|
||
## 🔵 [books-stateful-split-execution] — Ops-таска для **Фазы 1** дизайна `tenant-split` из victor/books. Выполнить playbook на shared VDS в maintenance window — docker volume copy для MariaDB + Mongo + MinIO bucket rename + DELETE cleanup. Identical bit-for-bit копии через `cp -a` alpine helper. Никаких mysqldump/mongodump/mc cp.
|
||
|
||
**Playbook (dev-source, читать целиком до начала):** `victor/books/.tasks/stateful-split-volume-copy.md`.
|
||
|
||
**Контекст дизайна:** `mcp__projects-meta__knowledge_get slug=concepts/tenant-split` § «Фаза 1 — Physical stateful split + overlay-repos». Brainstorm trace: `~/projects/.workshop/.archive/2026-05-24-books-tenant-split.md`.
|
||
|
||
**Container naming:** drop `books-` prefix → `bookva-<svc>` / `slovo-<svc>`.
|
||
|
||
**TDD-режим:** `[skip-tdd: one-off migration on maintenance window]` — verify через post-cleanup audit.
|
||
|
||
**Acceptance:**
|
||
- `bookva-db` + `slovo-db` контейнеры живые, audit `SELECT DISTINCT idSeller` = `{1}` / `{2}` соответственно.
|
||
- `bookva-mongo` + `slovo-mongo` контейнеры живые, agenda-история preserved, jobs чужого tenant'а cleanup'нуты.
|
||
- MinIO (один shared) имеет bucket'ы `bookva` + `slovo` вместо `books`; объекты чужого tenant'а удалены.
|
||
- Shared catalog tables (`books`, `editions`, `epz`, `epz_pages`, `warehouses`, `products`) — полные копии в обеих БД.
|
||
- Smoke с двух сетей: login через `bookva.<tld>` → Bookva-данные; текущий URL → Slovo.
|
||
- Через 7-14 дней parallel-run без откатов → cleanup старых `books-*` контейнеров и volumes (отдельный заход).
|
||
|
||
**Status:** blocked
|
||
**Where I stopped:** (not started)
|
||
**Next action:** **Pre-step:** прочитать `victor/books/.tasks/stateful-split-volume-copy.md` целиком. Убедиться что 7 open questions resolved (закрыто dev-prep таской `victor/books stateful-split-volume-copy`): FK CASCADE, units/receipts strategy, MinIO key structure, users whitelist, task_runs handling, chrome/traefik shared.
|
||
|
||
1. Подтвердить overlay-репо `victor/bookva-overlay` + `victor/slovo-overlay` готовы — compose-файлы для `bookva-*` / `slovo-*` стеков на месте.
|
||
2. Подтвердить per-tenant backups настроены (`victor/books per-tenant-backup-and-observability`) — иначе нет точки rollback.
|
||
3. Объявить maintenance window 1-2ч (без записи).
|
||
4. Execute Steps 0-11 из playbook на shared VDS.
|
||
5. Post-execution audit: `SELECT DISTINCT idSeller FROM <each>`, `db.agendaJobs.distinct('data.idSeller')`, `mc ls` on MinIO.
|
||
6. Smoke с двух сетей.
|
||
7. Через 7-14 дней parallel-run без откатов → cleanup старых `books-*` контейнеров+volumes (отдельный заход).
|
||
8. Closing note: «Physical split done, bookva-* + slovo-* контейнеры живут на shared VDS, audit clean, parallel-run start <date>».
|
||
**Blocker:** `victor/books stateful-split-volume-copy` (dev-prep — 7 open questions resolved + dev-DB test passed) + `victor/books per-tenant-backup-and-observability` (Фаза 2 — per-tenant backups настроены)
|
||
**Branch:** n/a
|
||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-25T04:46:48.271Z -->
|
||
|
||
---
|
||
|
||
## 🟢 [vehicles-loader-image-distribution] — closed 2026-05-29 — канал поставки решён: build здесь → push в **собственный registry клиента** `docker.stostayer.ru` → host pull + re-tag `:latest`. **Без Portainer** (oneshot не stack + Portainer cron не умеет; systemd-timer + `docker run --rm` сохраняет `OnFailure=`). Build здесь = депы (вкл. приватный verdaccio) запекаются в образ, клиенту verdaccio/yarn/node не нужны. Финализированы `deploy/README.md` § Image distribution + дизайн-док (вопрос #4 закрыт). **Commit:** stostayer.new `e55cfba`. **Prod-деплой ВЫПОЛНЕН 2026-05-29** (stostayer.new `ddda63f`): образ `docker.stostayer.ru/vehicles-loader:0.3.0` собран здесь+запушен, env `/etc/stostayer/vehicles-loader.env` (600 root), systemd-timer enabled (next 2026-05-30 06:20 MSK). **Гочи по ходу (обе в `stostayer.new/.wiki/concepts/client-infra-access.md`):** (1) MariaDB — под `--network host` наследуется хостовый `/etc/hosts` (`www→127.0.0.1 И ::1`), Node резолвит `::1` первым, mariadb слушает только IPv4 → timeout. Фикс: `STOSTAYER_DB_HOST=127.0.0.1`. (2) Контейнерный DNS сломан (Docker переписывает resolv.conf на публичные, исходящий :53 зафайрволен; `--add-host` под host-net игнорится) → email-отчёт на `mail.stostayer.ru` не резолвился. Фикс: `-v /etc/stostayer/container-hosts:/etc/hosts:ro` (свой hosts с пином mail-IP).
|
||
|
||
**Первый боевой прогон 2026-05-30 06:20:** sync УСПЕШЕН (`importRun id=3 ok`, ~84мин, units.json изменился относительно baseline), но упал на email (DNS, см. гочу #2) → systemd `failed` + ложный OnFailure. **Данные залились корректно.** Email-фикс применён и проверен `nodemailer.verify()` → `SMTP_VERIFY_OK` (DNS+TCP+STARTTLS+AUTH). Юнит redeployed, failed сброшен, next run Sun 06:21. Доки в stostayer.new `8e5997c`. **Заведена ⚪ `vehicles-loader-progress-logging`** (stostayer.new) — лог тонкий, ~2ч sync молчал. **Остаточное:** живой email-SEND в составе sync проверится на следующем changed-прогоне (verify доказал транспорт); OnFailure-юнит шлёт через хостовый `mail` — не проверен.
|
||
|
||
<details><summary>исходный scope (decision-task)</summary>
|
||
|
||
vehicles-loader (stostayer) деплоится в Docker у клиента (lite docker-deploy, дизайн залочен 29.05, см. stostayer.new `.wiki/concepts/vehicles-loader-docker-deploy.md`). Нужно решение по каналу поставки образа клиенту — единственный открытый вопрос #4, блокирующий финализацию Dockerfile CMD + deploy/README.
|
||
|
||
Развилка:
|
||
- **A (рекомендация brainstorm'а):** мы билдим образ → push в docker registry VDS → клиент `docker pull` по pinned-тегу. Rollback = перетыкнуть тег. Клиенту не нужен monorepo + yarn berry build-toolchain. Требует: у клиента docker login creds + сетевой доступ к нашему registry.
|
||
- **B (fallback):** клиент билдит из git у себя. Требует VCS-доступ + node22 + yarn berry **+ доступ к verdaccio** (`verdaccio.kzntsv.site`) с валидным токеном на хосте клиента. Причина: `.yarn/cache` в `.gitignore` (не коммитится), build идёт offline против cache → свежий `git clone` имеет пустой cache → `yarn workspaces focus` падает, пока клиент не прогонит `yarn install` против приватной регистры. Тяжелее, медленнее rollback, +зависимость от приватной регистры.
|
||
|
||
Образ: multi-stage node:22-alpine, `yarn workspaces focus @stostayer/vehicles-loader --production` (плагин `@yarnpkg/plugin-workspace-tools` закоммичен в stostayer.new `.yarn/plugins/`).
|
||
|
||
> **UPDATE 2026-05-29 (из stostayer.new session):** lite docker-deploy CORE зашипан (10/10 tasks на master). **Dockerfile CMD уже финализирован** (`ENTRYPOINT ["node","index.js"]` + `CMD ["sync"]`, source через env `STOSTAYER_SOURCE_ZIP` дефолт `/var/from_1c/export_from_1c.zip`) — эта часть блокера СНЯТА. Остаётся ТОЛЬКО: (1) решение по каналу поставки образа; (2) distribution-секция `deploy/README.md` (помечена PENDING на эту таску). **A build-proven:** образ собран локально (`docker build` ок) и запускается (`docker run --rm vehicles-loader:dev --help` ок). С учётом verdaccio-зависимости B (выше) — **A ещё предпочтительнее**: при A клиенту verdaccio не нужен вообще (cache наполняется нашим authed `yarn install` при сборке).
|
||
|
||
**Status:** closed 2026-05-29
|
||
**Resolution:** канал = собственный registry клиента `docker.stostayer.ru` (не наш VDS-registry, не build-from-git). Развилка пересмотрена при открытии `pass stostayer/client` — у клиента своя инфра (Portainer + registry). Build остаётся у нас (verdaccio-депы запекаются). Без Portainer для запуска (oneshot). Доки финализированы в stostayer.new `e55cfba`.
|
||
**Branch:** n/a
|
||
</details>
|
||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: victor/stostayer.new / 2026-05-29T10:17:29.967Z -->
|
||
<!-- closed-by: vitya@.admin-exec / 2026-05-29 / decision: client-registry + build-here + no-Portainer; deploy/README + design-doc finalized (stostayer.new e55cfba) -->
|
||
|
||
---
|
||
|
||
## 🔴 [agents-task-runner-vds-deploy] — Deploy agents-task-runner (the poller) on WORKER machine(s) — per-machine federation (agent-orchestration-without-user Q9). Each worker runs its own runner, claims from the SHARED Gitea board, runs the agent LOCALLY, commits/pushes. VDS hosts the Gitea board ONLY (already up) — it is NOT a worker, nothing deploys on VDS. [Slug legacy-named '-vds-deploy'; scope corrected 2026-06-08, VDS-as-worker DROPPED.] Runtime code deploy-ready (poller registered in tasks.json, DRY_RUN + requirements-filter + confirm-gate built; compose+Dockerfile). Credentialed per-machine setup (ops).
|
||
|
||
**Status:** active
|
||
**Where I stopped:** 2026-06-08: DRY_RUN провалидирован; `.admin` claim-guard (`policy.toml` default_weight=needs-human) запушен+верифицирован (все `.admin`-таски → needs-human skip). Always-on bring-up начат (docker mongo+reconciler) затем **снесён по запрету user'а «не запускай поллеров без разрешения»** — host task-runner НЕ стартовал, ни одного claim/spawn. **GATE: запуск поллеров ждёт явного гранта user'а.** Попутно поймана+закрыта stale-claimable `cms-maljarka-https-mode-bug-fix` на MoreThenCms board (баг починен сегодня, таска висела открытой — без паузы always-on заспавнил бы агента на уже-решённое). Конфиг (.env/secrets.env/policy guard) готов. См. [agents-task-runner-vds-deploy.md](agents-task-runner-vds-deploy.md).
|
||
**Next action:** (0) BUILD PREREQ (from consult-execution-policy-governance review-outcome, OpeItcLoc03/common): repo tracks TS source only — `dist/` is gitignored. After pulling OpeItcLoc03/common on each worker, run `npm run build` (tsc) in BOTH lib/projects-meta-mcp AND lib/agents-task-runner, then (re)start the runner; otherwise the execution-policy governance lever (consult_policy + needs-human claim-gate, runner v0.16.x) is INERT — the old compiled JS keeps running. (1) Pick first worker machine (workstation / factory Linux). (2) Install + run agents-task-runner there, pointed at the shared Gitea board. (3) Secrets PER MACHINE: ANTHROPIC_API_KEY (headless) or `claude login` + Gitea token + projects-meta config; 600 root, not in git. (4) Capability filter: claims only what that machine can do (requirements/runtime_allowed); cheap model (sonnet/haiku) for impl polling. (5) HARD: .admin excluded from autonomous claim until governance L2/L3 lands (see blocker). (6) DRY_RUN on prod board first → then one live cycle on a real non-.admin task → spawn→commit→push, verified. (7) anti-self-review: distinct machine-id per worker.
|
||
**Branch:** n/a
|
||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-06-08T10:10:16.420Z -->
|
||
|
||
---
|