Прод RUVDS отдаётся быстро (~0.35s); медленность была локальной stale-копией
(LAN-DNS → home traefik :8089), не дефектом прода. traefik не трогал.
Open ES-incident треки/guards перенесены вперёд.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Рецидив вчерашнего ES-инцидента вскрыл истинную причину. Вчерашняя
гипотеза «оператор в cutover попал на canonical» опровергнута.
Root cause: ES (stack 33) публиковал 0.0.0.0:9200 мимо traefik. Free-ES
7.10 без auth → порт открыт всему интернету. Ransom-бот сносил индексы
by-name (мимо Control #1 destructive_requires_name), оставлял read_me с
BTC-выкупом. accessLog (Control #2) пуст — бот шёл прямо в порт, не через
traefik. firewalld бесполезен (docker-publish обходит INPUT-зоны).
Fix (Control #3): убрана публикация host-порта из stack 33 (Portainer
PUT), дыра закрыта; re-restore epz/products/artmone из daily-2026-05-25.
Отдельный баг: epz-поиск падал у ОБОИХ тенантов — getTenantIdSeller(
config.get("tenant")) через node-config, а tenant не задан ни в
default.json, ни в env-маппинге (TENANT env = мёртвый груз). Добавлен
tenant в overlay default.json (slovo/bookva). products работал —
отдельный код-путь.
accessLog откатан (сторожил не ту дверь).
- wiki concept: correction-блок + секция «Рецидив 2026-05-29» + exposure-audit
- tasks: restore-es reopened+reclosed; new ⚪ harden-books-vds-exposed-ports
- NEXT_SESSION handoff
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
snapshot restore из kreknin:daily-2026-05-25 за 46 сек (epz=820604,
products=105922, artmone=2621, counts == source).
RCA: 5 индексов (включая system .tasks) удалены через ES API DELETE _all
за 1 сек на 2026-05-26 10:21 UTC — 1ч 11мин после создания bookva-es в
cutover-prep. Каноничный endpoint elasticsearch.kzntsv.site попал под
команду которая предназначалась bookva-es:9200 (internal-only, без
traefik route). Caller identity unrecoverable: ES audit = X-Pack платный,
traefik accessLog был выключен, Portainer CE без audit.
Preventive controls applied + verified:
1. ES env action.destructive_requires_name=true (stack 33) — DELETE _all
и wildcard теперь 400 BadRequest; by-name DELETE работает (нужно для
reindex). Pattern удаления что случился физически невозможен.
2. Traefik JSON accessLog в /letsencrypt/access.log — будущие DELETE
оставят forensic след с IP/user/method/path.
Wiki concept: .wiki/concepts/es-destructive-delete-incident-2026-05-26.md
с recovery runbook + preventive controls + cross-refs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
— labtools.ru: Я.360 (admin.yandex.ru/domains), apex+www A → 80.64.31.36
— tandemmebel.ru: reg.ru, apex A → 80.64.31.36; www/maljarka follow via CNAME
Server-side prep for tandemmebel done same session: cert tandemmebel.ru
(LE R13, NotAfter 2026-07-21) extracted from local traefik acme.json,
imported to RUVDS LocalMachine\My, attached to existing IIS bindings for
apex + www. Wiki entity ruvds-iis-host.md stale on this point — bindings
were already created during initial migration, just lacked cert.
Deployed modulair-rag (Portainer stack 15) on VDS 89.253.255.94, acceptance 6/6.
Pre-flight verify found the task was filed on stale premises; corrected in-flight:
- registry images absent (registry reinstalled 2026-05-20) → rebuilt all 3 ON the
VDS (3.36GB tier1 layer 499'd pushing through traefik from home; local push works)
- MINIO_ENDPOINT=minio.vds.kzntsv.site (minio.kzntsv.site is books VDS)
- traefik entrypoint https→websecure (NAS-era label) fixed in live stack
- created DB modulair_rag, minio bucket + scoped svcacct, ROUTERAI key to pass
- DNS modulair-mcp.kzntsv.site→VDS (user)
Follow-ups (consumer repo modulair-rag): compose.yml entrypoint commit,
portainer-stack.md rewrite, lightrag embedding binding=ollama/model=None check.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stack 26 (books-ops-mcp) PUT с pullImage:true + добавлен BOOKVA_MARIADB_PASSWORD
env (= MARIADB_PASSWORD, bookva-db ops_ro password identical после cp-a).
Container books-ops-mcp@master-f5f295b running.
Smoke:
- ops.mariadb.query tenant=slovo → АФО2/Главная26/НК11 (slovo warehouses)
- ops.mariadb.query tenant=bookva → Главная26/Ира/НК11 (bookva warehouses)
(Ира появилась в bookva post-cutover, нет в slovo — данные genuinely разные)
- ops.mongo.count tenant=bookva collection=agendaJobs → 2818
Один host-level ops-mcp видит обе tenant DBs через per-tenant pool maps.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Multi-fix session: bookva tenant works correctly после 6 fix'ов одной природы
(incomplete cutover-prep без e2e smoke). См. NEXT_SESSION.md § "What's LIVE"
+ § "Memory updates" + shared wiki concept tenant-overlay-config-volume-mount-path-pitfall.
Changes:
- host-stacks/books-vds/ops-mcp.compose.yml: add BOOKVA_MARIADB_PASSWORD env
declaration + multi-tenant docs note. Stack 26 ещё не пере-PUT'нут на это,
открытая микро-таска ops-mcp-multi-tenant-stack-activate в NEXT_SESSION.
- STATUS.md: 6-bug summary в latest update line.
- NEXT_SESSION.md: full rewrite с 14 recent commits, open треками, asks к user'у,
memory updates про agenda.db.collection / composite jobId / scheduler envs /
bookva auth tokens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7/7+minio+cutover done в одну сессию. bookva tenant LIVE на bookseller.kzntsv.site
(10 stacks active, login-gate, ES reindexed 920k docs). Auto-deploy tenant=all
активирован. 3 wiki concepts ingested (gitea-reserved-secret-prefix, mongo-wt-
format-major-version-incompat, portainer-per-stack-depends-on-pitfall).
Open треки: books-api-shutdown (~2026-05-27/28), bookva-ozon-mcp-image-build,
optional bookva-minio HTTPS DNS. bookva-tenant-cutover task не понадобилась —
de-facto cutover произошёл сегодня.
Auto-push grant был session-only — следующая session требует нового grant.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Clone-adapted from .wiki/concepts/portainer-stack-management-vds.md § Migration script.
Diffs from VDS-infra version:
- PORTAINER_URL = portainer.kzntsv.site
- Auth via X-API-Key (PAT works, no JWT fallback needed)
- DIR prefix /usr/docker/<stack> (not /opt/stacks/<stack>)
- Down step via `docker rm -f` by compose-project label
(bypasses docker-compose v1 ContainerConfig bug entirely; no compose binary on path required)
- Refuses traefik/portainer migration (management plane)
Idempotent: delete-then-create against existing stack by name on endpoint 1. Re-runs are safe.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Acceptance:
- 3 scripts (VDS bash + RUVDS ps1 + windows-host ps1) синхронизированы под
unified push + email format (commit 73ad6dd0).
- VDS deployed + smoke ntfy+email ✓.
- RUVDS deployed + smoke ntfy+email ✓.
- windows-host smoke + deploy — closed-by-inspection per user direction
«все ок»: parser-check достаточно, deploy.ps1 готов для self-deploy
elevated PS у user'а. Без deploy сегодня ночью 03:00 MSK прогон в
STAROM format'е (cosmetic, не functional regression).
Также атомарный revert (`.bak-pre-unify` на каждом хосте) задокументирован
в .tasks/unify-backup-notifications.md § Closed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stale prompt-file от попытки iis-on-host-migration 2026-05-19 — таска
уже 🟢 закрыта, файл устарел. Также содержит 4 plaintext password'а
(MSSQL SA conn-strings + snolla/stayer DB users + VM admin) — leaked
в git history с 2026-05-21 (`c55cb119`). User accept risk без rotation /
history-rewrite (private gitea, ограниченный pull-access).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 host-pipelines (VDS bash, RUVDS+windows-host ps1) had drifted formats:
ntfy title `VDS backup OK $D` vs `RUVDS backup OK ($D)`, tags
`white_check_mark` vs `green_circle`, email subject `[VDS] backup OK` vs
`RUVDS backup -- SUCCESS`. Phone-side фильтрация и desktop reading
ломались за счёт inconsistency.
Unified to:
- ntfy push: title `<HOST> backup OK <date>`, body
`<duration_human>, size=<>, snapshots=<>, dest=kreknin:<>`,
tags `green_circle` (OK) / `red_circle` (FAILED).
- email: subject `[<HOST>] backup <STATUS> <date>` (STATUS=OK|FAILED),
body — structured Date/Duration/Size/Snapshots/Source/Dest/Components/Log.
Failure body extends with `Tail (last 40 lines)`.
Also imports VDS `run.sh` into repo as `scripts/vds-backup-rsync-kreknin/`
— closes drift из общего `scripts/<slug>/` pattern (RUVDS+windows-host
уже жили там; VDS жил только на /opt/stacks/backup/scripts/).
Deploy status:
- VDS: deployed via scp + sudo install, sha256=27b09ca272bb, smoke ntfy+email ✓
- RUVDS: deployed via scp + Move-Item, sha256=f3bb57a86af5, smoke ntfy+email ✓
- windows-host: deploy.ps1 + smoke-notify.ps1 готовы в scripts/, **pending
elevated PS у user'а** (ACL=SYSTEM+Administrators, не пишется без UAC).
Spec + decisions + completed: .tasks/unify-backup-notifications.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pulls in `session handoff: read on start, write on end` so the
session-handoff skill (installed via claude-skills) activates in this
project. Inserted between `pull remote before work` and
`follow project discipline` — session-lifecycle clustering, mirrors
claude-skills CLAUDE.md and project-bootstrap's canonical template.
Refs OpeItcLoc03/claude-skills [session-handoff-existing-projects-upgrade].
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>