tasks(bookva-tenant-cutover-prep): create — 7-step VDS prep после tenant-split dev-side closed
Gitea secrets для PORTAINER_STACK_ID_BOOKVA_* + GITEA_TOKEN, создание
Portainer stacks для bookva-{api,web,scheduler,task-runner,ozon-mcp,
ops-mcp,db,mongo,es,ntfy}, volume create+copy (Mongo/ES/MinIO/configs),
bookva-db login-gate password-replace, DNS bookseller.kzntsv.site,
PWA redirect env в books-web, books-web embedded-api env (pending
step из embed-api handoff).
Dev-side done в victor/books master:
- 5e28fd1 embed-api + zod^4 (root cause: zod 3.x в web shadowed
root zod 4.x, @nuxt/ui v4.5 silent broke without zod 4 API)
- 4a9cafc ES endpoint per-tenant via custom-environment-variables.json
- c1e58cf PWA redirect banner (user.id=1 modal)
- 88df172 deploy.yml per-tenant (tenant input + per-tenant stack IDs)
Overlay-repos обновлены: bookva-overlay 58d4295 (+ ES env + ntfy
full config), slovo-overlay bca6bbc (+ ES env + ntfy full config).
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
# Admin Task Board
|
# Admin Task Board
|
||||||
|
_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.)_
|
_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.)_
|
||||||
|
|
||||||
## 🟢 [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] — 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 НЕ выключен.
|
||||||
@@ -13,6 +15,23 @@ _Updated: 2026-05-25 (`iis-migration-to-ruvds` 🟢 closed Phase 1 per user deci
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## ⚪ [bookva-tenant-cutover-prep] — 7-step prep на books VDS перед поднятием Bookva стека
|
||||||
|
|
||||||
|
Gitea secrets + Portainer bookva stacks + volume create/copy (Mongo/ES/MinIO/configs — beyond MariaDB из stateful-split-volume-copy) + bookva-db login-gate + DNS `bookseller.kzntsv.site` + PWA redirect env в books-web + books-web embedded-api env (pending step из embed-api). После — отдельной задачей `bookva-tenant-cutover` (compose up).
|
||||||
|
|
||||||
|
**Контекст dev-source:** victor/books `.wiki/concepts/tenant-split.md` rev v3. Code-side closed master: `5e28fd1` embed-api+zod^4, `4a9cafc` ES endpoint, `c1e58cf` PWA redirect, `88df172` deploy.yml per-tenant. Overlay-repos: bookva-overlay/main `58d4295`, slovo-overlay/main `bca6bbc`.
|
||||||
|
|
||||||
|
**Acceptance:** все 7 шагов выполнены (см. task-файл), но `compose up bookva-*` ещё не запущен — это отдельная задача.
|
||||||
|
|
||||||
|
**Status:** ready
|
||||||
|
**Where I stopped:** (not started — все dev-side prep closed)
|
||||||
|
**Next action:** Step 1 в Gitea UI — добавить bookva secrets (placeholder values). Шаги 2-7 по порядку.
|
||||||
|
**Blocker:** —
|
||||||
|
**Branch:** main
|
||||||
|
<!-- created-by: vitya / 2026-05-26 / Phase 2 cutover prep после tenant-split code-side done -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## ⚪ [stateful-split-volume-copy] — поднять `bookva-db` + `slovo-db` на VDS как копии `books-db` через `cp -a` volume
|
## ⚪ [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-тасками потом.
|
Ops-таска для Фазы 1 дизайна `tenant-split` из victor/books. Scope сужен 2026-05-25 (user: «просто поднимем 2 БД»): только MariaDB volume copy + up 2 контейнеров. Mongo / MinIO / DELETE / app-стеки — отдельными ops-тасками потом.
|
||||||
|
|||||||
151
.tasks/bookva-tenant-cutover-prep.md
Normal file
151
.tasks/bookva-tenant-cutover-prep.md
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
# bookva-tenant-cutover-prep
|
||||||
|
|
||||||
|
Подготовительные ops-шаги на books VDS перед cutover Bookva tenant в отдельный стек на `bookseller.kzntsv.site`. Code/CI part сделан в victor/books master (см. dev-side ниже).
|
||||||
|
|
||||||
|
## Контекст dev-source
|
||||||
|
|
||||||
|
- Дизайн: victor/books `.wiki/concepts/tenant-split.md` rev v3 (2026-05-25).
|
||||||
|
- Overlay-репо: `victor/bookva-overlay` + `victor/slovo-overlay` (compose'ы + config-templates).
|
||||||
|
- Code-side done в master:
|
||||||
|
- `5e28fd1` embed-api в web (server/api/*) + zod^4 fix.
|
||||||
|
- `4a9cafc` ES endpoint per-tenant через `custom-environment-variables.json`.
|
||||||
|
- `c1e58cf` BookvaRedirectBanner — PWA handoff modal для user.id=1.
|
||||||
|
- `88df172` deploy.yml per-tenant (tenant input + per-tenant stack IDs + bookva-overlay clone).
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Bookva стек готов взлететь — все secrets/stacks/volumes/DNS/PWA-redirect на месте. Сам `compose up` для bookva = последний шаг (отдельная задача `bookva-tenant-cutover` будет создана когда юзер скажет).
|
||||||
|
|
||||||
|
## Plan
|
||||||
|
|
||||||
|
### Step 1 — Gitea secrets (admin via gitea UI или API)
|
||||||
|
|
||||||
|
Добавить в repo `victor/books` settings → Secrets:
|
||||||
|
|
||||||
|
```
|
||||||
|
PORTAINER_STACK_ID_BOOKVA_API
|
||||||
|
PORTAINER_STACK_ID_BOOKVA_WEB
|
||||||
|
PORTAINER_STACK_ID_BOOKVA_SCHEDULER
|
||||||
|
PORTAINER_STACK_ID_BOOKVA_OPS_MCP
|
||||||
|
GITEA_TOKEN # read-access к victor/bookva-overlay
|
||||||
|
HEALTHCHECK_BOOKVA_API_URL # опционально, http healthcheck
|
||||||
|
HEALTHCHECK_BOOKVA_WEB_URL
|
||||||
|
```
|
||||||
|
|
||||||
|
Значения stack ID — после Step 2.
|
||||||
|
|
||||||
|
После Phase 2 cutover (отдельная задача) — переименовать `PORTAINER_STACK_ID_{API,WEB,SCHEDULER,OPS_MCP}` → `PORTAINER_STACK_ID_SLOVO_*` для symmetry. До тех пор deploy.yml использует fallback на legacy имена.
|
||||||
|
|
||||||
|
### Step 2 — Portainer bookva stacks
|
||||||
|
|
||||||
|
В Portainer (https://portainer.kzntsv.site) создать stacks из overlay-compose:
|
||||||
|
|
||||||
|
- `bookva-db` — `~/projects/bookva-overlay/deploy/db.compose.yml`
|
||||||
|
- `bookva-mongo` — `mongo.compose.yml`
|
||||||
|
- `bookva-es` — `elasticsearch.compose.yml` (новый, в-stack ES 7.10.0)
|
||||||
|
- `bookva-api` — `api.compose.yml`
|
||||||
|
- `bookva-web` — `web.compose.yml`
|
||||||
|
- `bookva-scheduler` — `scheduler.compose.yml`
|
||||||
|
- `bookva-task-runner` — `task-runner.compose.yml`
|
||||||
|
- `bookva-ozon-mcp` — `ozon-mcp.compose.yml`
|
||||||
|
- `bookva-ops-mcp` — `ops-mcp.compose.yml`
|
||||||
|
- `bookva-ntfy` — `ntfy.compose.yml`
|
||||||
|
|
||||||
|
Env-vars stack-level (Portainer Stack → Environment):
|
||||||
|
- `CORE_SHA` — последний master tag из registry (например `master-5e28fd1`).
|
||||||
|
- `HOSTNAME_API` / `HOSTNAME_WEB` — `bookseller.kzntsv.site` (per design v3).
|
||||||
|
- `HOSTNAME_NTFY` — `push.bookseller.kzntsv.site`.
|
||||||
|
|
||||||
|
После создания каждого stack — Portainer присваивает ID → записать в Gitea secrets (Step 1).
|
||||||
|
|
||||||
|
### Step 3 — Volume create + copy (stateful split)
|
||||||
|
|
||||||
|
См. отдельную задачу [stateful-split-volume-copy](stateful-split-volume-copy.md) — MariaDB.
|
||||||
|
|
||||||
|
Дополнительно для Phase 2 нужны (текущая задача охватывает только MariaDB):
|
||||||
|
- `bookva-mongo-data` — copy с `books-job-scheduler-mongo_data` через `cp -a` + `deleteMany({'data.idSeller': 2})` для cleanup чужих agenda jobs.
|
||||||
|
- `bookva-es-data` — пустой volume; данные через ES snapshot+restore из shared kzntsv ES в Phase 2.
|
||||||
|
- `bookva-minio-data` ИЛИ FS-rename `books` → `slovo` + `cp -a slovo bookva` в shared MinIO контейнере.
|
||||||
|
- Config volumes — `bookva-{api,scheduler,task-runner}-config` + `bookva-web-branding` + `bookva-ntfy-data` (см. README в bookva-overlay для bootstrap).
|
||||||
|
|
||||||
|
### Step 4 — bookva-db login-gate
|
||||||
|
|
||||||
|
После volume copy + bookva-db up:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- В bookva-db только (slovo-db не трогать!):
|
||||||
|
UPDATE users SET password = SHA2(UUID(), 256) WHERE id NOT IN (1, 2);
|
||||||
|
```
|
||||||
|
|
||||||
|
(точная команда — после проверки актуального password storage format в `packages/api/server/services/auth/*` или embedded `packages/web/server/api/auth/login.post.js`.)
|
||||||
|
|
||||||
|
Эффект: только id=1 (Bookva-учредитель) + id=2 (Slovo-учредитель) могут логиниться в `bookseller.kzntsv.site`. Остальные user-записи остаются, но без работающего пароля.
|
||||||
|
|
||||||
|
### Step 5 — DNS
|
||||||
|
|
||||||
|
Добавить A-record `bookseller.kzntsv.site` → books-vds IP (тот же что `bookva.kzntsv.site` сейчас).
|
||||||
|
|
||||||
|
После cutover (отдельная задача) — `bookva.kzntsv.site` остаётся на тот же IP (роутит на slovo стек).
|
||||||
|
|
||||||
|
### Step 6 — PWA redirect handoff (за 1-2 недели до cutover)
|
||||||
|
|
||||||
|
В Portainer для текущего `books-web` stack (= future slovo-web после cutover) добавить env:
|
||||||
|
|
||||||
|
```
|
||||||
|
NUXT_PUBLIC_BOOKVA_REDIRECT_URL=https://bookseller.kzntsv.site
|
||||||
|
```
|
||||||
|
|
||||||
|
После DEPLOY_AT bump → recreate web container → новый SW bundle подхватывает `BookvaRedirectBanner` компонент. user.id=1 видит modal «Bookva теперь на bookseller.kzntsv.site → Перейти».
|
||||||
|
|
||||||
|
### Step 7 — books-web embedded-api env (pending step из embed-api handoff)
|
||||||
|
|
||||||
|
В Portainer `books-web` stack environment:
|
||||||
|
|
||||||
|
ADD:
|
||||||
|
```
|
||||||
|
NUXT_AUTH_TOKEN=<значение из books-api.NITRO_AUTH_TOKEN>
|
||||||
|
NUXT_JWT_SECRET_KEY=<значение из books-api.NITRO_JWT_SECRET_KEY>
|
||||||
|
```
|
||||||
|
|
||||||
|
CHANGE/REMOVE:
|
||||||
|
```
|
||||||
|
NUXT_PUBLIC_BOOKS_API_URL=/api # было https://books.kzntsv.site, переключаем на embedded
|
||||||
|
NUXT_PUBLIC_BOOKS_API_KEY= # удалить (legacy)
|
||||||
|
```
|
||||||
|
|
||||||
|
После DEPLOY_AT bump → recreate. Embedded api начнёт обслуживать `/api/*` (вместо старого books-api стека).
|
||||||
|
|
||||||
|
После 24-48ч стабильности — остановить `books-api` stack (отдельная micro-task).
|
||||||
|
|
||||||
|
## Acceptance
|
||||||
|
|
||||||
|
- Gitea secrets выставлены (Step 1).
|
||||||
|
- Portainer stacks `bookva-*` созданы (Step 2), stack IDs в Gitea secrets.
|
||||||
|
- Volumes `bookva-*` существуют + data populated (Step 3).
|
||||||
|
- bookva-db login-gate применён (Step 4).
|
||||||
|
- DNS `bookseller.kzntsv.site` → books-vds (Step 5).
|
||||||
|
- `NUXT_PUBLIC_BOOKVA_REDIRECT_URL` в books-web env (Step 6) — за 1-2 недели до cutover.
|
||||||
|
- books-web env обновлён для embedded api (Step 7).
|
||||||
|
- Acceptance не включает `compose up bookva-*` — это **отдельная** задача `bookva-tenant-cutover` (создаётся когда юзер скажет «давай поднимать Bookva»).
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
ready
|
||||||
|
|
||||||
|
## Where I stopped
|
||||||
|
|
||||||
|
(not started — все code/CI prep на dev-стороне closed, осталась только VDS/Portainer работа)
|
||||||
|
|
||||||
|
## Next action
|
||||||
|
|
||||||
|
Step 1 в Gitea UI: добавить bookva secrets (значения placeholder). Шаги 2-7 — по порядку под maintenance window.
|
||||||
|
|
||||||
|
## Blocker
|
||||||
|
|
||||||
|
—
|
||||||
|
|
||||||
|
## Branch
|
||||||
|
|
||||||
|
main
|
||||||
|
|
||||||
|
<!-- created-by: vitya / 2026-05-26 / Phase 2 cutover prep после tenant-split code-side done -->
|
||||||
Reference in New Issue
Block a user