Compare commits

..

2 Commits

Author SHA1 Message Date
ed581f4ccf meta(tasks): refresh session handoff after assets migration 2026-06-13 23:16:49 +03:00
82d724f108 feat(assets): migrate snolla assets originals Local-disk → S3
assets storage class = Local (RUVDS IIS App_Data\assets), never in S3 →
snolla imgproxy source s3://assets/<ownerId>/<storageFilename> = 404.
Created MinIO bucket `assets` (books-vds), rclone'd whole tree from RUVDS
verbatim: 4750 obj / 215.5 MiB, 145 owner folders. Verify count+size ==
source. Smoke: brevno.jpg → 200 image/webp; validly-signed missing obj →
404. snolla code unchanged (path A). Scope widened past pilorama98 (closes
404 class for all tenants; owner→site map non-obvious). snolla-side stub
content-api/routes/assets.js still pending (flagged in inbox).

Closes [migrate-assets-originals-to-s3].

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 23:16:10 +03:00
3 changed files with 46 additions and 28 deletions

View File

@@ -1,37 +1,37 @@
---
_last_updated_: 2026-06-11T00:00:00Z
session_id: 2026-06-11-rusonyx-notification-wiki-lint-mssql-backup
_last_updated_: 2026-06-13T20:20:00Z
session_id: 2026-06-13-migrate-assets-originals-to-s3
---
# Next session handoff
## Recent commits
- `e2338b6f` wiki(lint): close all 10 lint issues + delete windows-host backup task
- `4fd8288e` meta(wiki): log += ingest concepts/mcp-init-resilience
- `054fceea` task(agents-task-runner-vds-deploy): guard verified; always-on HALTED pending grant
- `82d724f1` feat(assets): migrate snolla assets originals Local-disk → S3 (closes [migrate-assets-originals-to-s3])
- `f0442661` feat(galleries): migrate pilorama98 gallery originals Local-disk → S3
- `b332af66` fix(vds-backup): MSSQL backup INIT→FORMAT + estate backup audit
## Open треки
| Трек | Готовность | Entry-point |
|---|---|---|
| `fix-nl-vds-reality-pq-dest` | 🟡 server-side done, ждёт client-side | user меняет SNI в v2rayN: профиль `pqmkayaxo2` → SNI=`www.microsoft.com`, reconnect → confirm → close |
| `agents-task-runner-vds-deploy` | 🟡 пауза — ждёт явного гранта на запуск поллеров | Next: grant → `npm run build` в OpeItcLoc03/common (оба lib) → docker up dry-run → live cycle. `.admin` excluded. |
| `harden-books-vds-exposed-ports` | ⚪ ready | mongo/books-db/bookva-db/minio/bookva-minio на 0.0.0.0, credentialed; начать с mongo (EOL 4.2) |
| docker-vhdx compact (135 ГБ в `docker_data.vhdx`) | ⏸ отложено user'ом | `Optimize-VHD -Mode Full` после полного закрытия Docker Desktop; не горит |
| **MSSQL backup smoke** | ⚠️ **ВСЁ ЕЩЁ не проверено** | Должно было отработать 05:00 MSK 12-го И 13-го. Проверить kreknin: свежие `.bak` 5 баз + размеры (MoreThenCms 910M/StayerCalculator 528M/StayerPrice 39M/TireService 4.5M/stostayer 990M). Память: «backup не done пока не доказан реальным прогоном». |
| `fix-nl-vds-reality-pq-dest` | 🟡 | user: SNI в v2rayN `pqmkayaxo2``www.microsoft.com`, reconnect → confirm → close |
| `agents-task-runner-vds-deploy` | 🟡 пауза | ждёт явного гранта user'а на автономный запуск поллеров |
| `harden-books-vds-exposed-ports` | ⚪ ready | mongo/minio и др. на 0.0.0.0 (credentialed); начать с mongo |
| `infra-inventory`, `stateful-split-volume-copy` | ⚪ ready | не начаты |
## Спроси user'а
- **VDS MSSQL backup smoke:** добавлен в run.sh сегодня (5 DBs, sqlcmd COPY_ONLY). Завтра 05:00 MSK — первый авто-прогон. Если email/ntfy придёт с `mssql MoreThenCms: N bytes` — значит работает. Стоит проверить.
- **agents-task-runner grant:** разрешаем запускать поллер автономно? Сейчас gate «ни одного claim без явного гранта».
- **MSSQL backup:** проверить реальный прогон (см. выше) — самое time-sensitive.
- **agents-task-runner grant:** разрешаем автономный запуск поллеров?
- **fix-nl-vds:** client-side шаг сделан?
## Не делать (preemptive guards)
- Не запускать агентские поллеры автономно — только по явному гранту user'а ("не запускай поллеров без разрешения").
- Не поднимать `docker compose up` на VDS напрямую по ssh — только через Portainer (anti-pattern). Исключения: traefik + portainer.
- `pass show` работает в bash, НЕ в PowerShell напрямую. Для кредов VDS — bash-инструмент или `bash -c "pass show ..."`.
- localhost-проверки на этой машине — `curl --noproxy "*"` (системный прокси глотает localhost). Прод — `--resolve host:IP`.
- pass show — в bash, НЕ в PowerShell напрямую.
- RUVDS IIS: SSH по паролю через **plink** (нативный ssh.exe пароль non-interactively не умеет, sshpass нет). `plink -ssh -batch -hostkey "SHA256:r/vSKU5WzH4B8T7RiXyXlg0D8XZ9hlBxzmdrPzuPWzE" -pw "$PASS"`; пароль из pass с CRLF → `tr -d '\r\n'`.
- imgproxy smoke — мимо LAN-DNS воркстейшна: `--resolve imgproxy.kzntsv.site:443:89.253.255.133`.
- VDS docker-stacks — только через Portainer (исключения traefik+portainer).
- Не запускать агентские поллеры автономно без гранта.
## Memory updates за сессию
- (нет новых файлов памяти — все изменения зафиксированы в `.wiki/` и git)
- (нет новых файлов памяти; механика доступа RUVDS-IIS зафиксирована в этом handoff + guard'ах)
- assets-миграция и форма ключа — в `.wiki/concepts/galleries-storage-class-local-not-s3.md`.

View File

@@ -1,4 +1,5 @@
# Admin Task Board
_Updated: 2026-06-13 — 🟢 **[migrate-assets-originals-to-s3] closed.** assets-оригиналы (весь `App_Data\assets`: 4750 obj / 215.5 MiB, 145 owner-папок) залиты в новый MinIO bucket `assets` (books-vds) rclone'ом с RUVDS IIS, ключи `<ownerId>/<storageFilename>` verbatim. Verify count+size == source. Smoke (мимо LAN-DNS): brevno.jpg → 200 image/webp 64556 B (был 404), валидно-подписанный несуществующий объект → 404 (негатив-контроль). Код snolla не менялся (path A); scope намеренно шире pilorama98 — закрывает класс-404 для всех тенантов snolla, регрессии нет (shared bucket, как galleries). ⚠️ snolla-side остаётся `content-api/routes/assets.js` (пустой stub) — без него картинки не рендерятся на сайте. Inbox victor/snolla отправлен._
_Updated: 2026-06-12 (4) — 🟢 **[migrate-gallery-originals-to-s3] closed (scope pilorama98).** Галереи snolla не отдавались (imgproxy 404) т.к. в legacy `storageClient="galleries"` = тип **Local** (диск `App_Data\galleries\<siteId>`), НЕ S3 — оригиналы никогда туда не заливались (продукты — заливались, bucket `pilorama98`). Развилка A/B закрыта фактами MinIO → **A**: создан bucket `galleries`, залиты 301 файл (77 MiB) pilorama98 (siteId `37e67fc4…`) с RUVDS IIS через rclone → `s3://galleries/<siteId>/<guid>.jpg` verbatim (== ровно то, что строит `middleware/galleries.js:47`). Код snolla НЕ менялся. Verify: count+size == source. Smoke с books-vds: реальный объект imgproxy → 200 webp, fake → 404. Уточнение инфра: `imgproxy.kzntsv.site` с 08.06 на **books-vds** (стек 29/30), не на windows-host — `minio-imgproxy-on-vds.md` был stale. Inbox victor/snolla отправлен._
_Updated: 2026-06-12 (3) — 🟢 **bookva-es snapshot done** (не отложен). Portainer stack 37 пересоздан с `path.repo=/snapshots`+bind (PUT API, том цел, epz/products уцелели), repo `kreknin` зарегистрирован, snapshot-блок в `run.sh`. Поймана коллизия basename `snapshots` (оба ES-каталога одноимённы → сливались в один dest-репо, порча обоих) → источник bookva-es = родительский `/usr/docker/bookva-es`. Verified: `BOOKS-VDS backup OK 10m28s`, на kreknin раздельно `snapshots/`(slovo index-41) + `bookva-es/snapshots/`(index-4). Таска `bookva-es-snapshot-repo` 🟢 closed._
_Updated: 2026-06-12 (2) — 🟢 **bookva-* backup gap закрыт.** bookva tenant (db/mongo/es/minio, поднят 26.05) не бэкапился — books-скрипт написан 25.05 до bookva, покрытие не расширили (висело wiki-follow-up #2). Добавлены bookva-db (тот же root pw), bookva-mongo (no-auth), bookva-minio (raw volume) в `books-vds-backup-daily-kreknin/run.sh`; деплой == репо (`.bak-pre-bookva`). Verified green: `BOOKS-VDS backup OK 10m42s`, артефакты на kreknin (bookva-mariadb 257M, bookva-mongo 3.2M, bookva-minio 1.4G). bookva-es отложен → `bookva-es-snapshot-repo` (покрыт slovo-снапшотом, индексы идентичны). Правило в память: новый stateful → бэкап в том же коммите._
@@ -432,7 +433,10 @@ vehicles-loader (stostayer) деплоится в Docker у клиента (lite
---
## [migrate-assets-originals-to-s3] — Залить Local-storage assets-оригиналы сайта pilorama98 в S3 — латентная дыра того же класса, что галереи (закрыта миграцией `migrate-gallery-originals-to-s3`). snolla отдаёт inline-картинки контента (`<img src="/assets/<ownerId>/<size>/<file>">`) через imgproxy с источником `s3://assets/<ownerId>/<storageFilename>`, но объектов в S3 нет — imgproxy 404 "Source image is unreachable". БД-записи есть, файлы только на legacy-IIS диске. Тип `StorageClient="assets"` — это `MoreThenCms.FileStorage.Local.*`, в S3 никогда не мигрировали.
## 🟢 [migrate-assets-originals-to-s3] — closed 2026-06-13 — assets-оригиналы залиты в S3, imgproxy 200 verified (scope расширен: весь assets-дерево, не только pilorama98). Создан bucket `assets` (отсутствовал) на MinIO books-vds; rclone RUVDS IIS `App_Data\assets` → `s3://assets/<ownerId>/<storageFilename>` verbatim. **Verify:** dest == source точь-в-точь — 4750 объектов / 225 935 853 B (215.5 MiB), 145 owner-папок. **Smoke (через books-vds, мимо LAN-DNS):** brevno.jpg (предподписанный URL из задачи) → 200 image/webp 64556 B (был 404); валидно-подписанный несуществующий объект → 404 (негативный контроль). Код snolla НЕ менялся (path A). Inbox victor/snolla отправлен. ⚠️ Остаётся snolla-side: `content-api/routes/assets.js` пустой stub — картинки не поедут на сайт пока роут не реализован (код-таска snolla, не блокер миграции).
### (исходное описание ниже сохранено до prune)
Залить Local-storage assets-оригиналы сайта pilorama98 в S3 — латентная дыра того же класса, что галереи (закрыта миграцией `migrate-gallery-originals-to-s3`). snolla отдаёт inline-картинки контента (`<img src="/assets/<ownerId>/<size>/<file>">`) через imgproxy с источником `s3://assets/<ownerId>/<storageFilename>`, но объектов в S3 нет — imgproxy 404 "Source image is unreachable". БД-записи есть, файлы только на legacy-IIS диске. Тип `StorageClient="assets"` — это `MoreThenCms.FileStorage.Local.*`, в S3 никогда не мигрировали.
## Acceptance criteria
1. Legacy assets-оригиналы pilorama98 залиты в S3 bucket `assets` ключами `<ownerId>/<storageFilename>` (path A, как с галереями: storageClient = имя бакета).
@@ -469,11 +473,19 @@ vehicles-loader (stostayer) деплоится в Docker у клиента (lite
**weight:** needs-human
**notify:** victor/snolla
**Status:** ready
**Where I stopped:** (not started)
**Next action:** Найти legacy-диск assets-оригиналов pilorama98, залить в S3 bucket `assets` ключами `<ownerId>/<storageFilename>`, прозвонить контрольный imgproxy-URL → ждём 200.
**Branch:** n/a
**Notify:** victor/snolla
**Status:** done (closed 2026-06-13)
**Where I stopped:** мигрировано всё дерево assets. rclone size min:assets == источник (4750 / 225935853). Smoke 200/404 OK.
**Next action:** — (хвост на стороне snolla: реализовать `content-api/routes/assets.js`; остальные Local-классы images/scripts/stylesheets/watermarks — отдельный аудит snolla, если поднимутся через imgproxy).
**Branch:** master
**Notify:** victor/snolla — ✅ inbox `.claude-inbox/2026-06-13T20-14-16Z-admin.md`
**Closure note (2026-06-13):**
- **Диск (RUVDS IIS `C:\sites\snolla\App_Data\assets`):** Local storage class, 145 owner-папок (32-hex), плоские файлы. brevno owner `83150d77…` = 6 файлов, `brevno.jpg`=580667 B == DB `Files.Size`. Ключ-форма `<ownerId>/<storageFilename>` подтверждена на диске.
- **MinIO (books-vds, minio.kzntsv.site):** bucket `assets` отсутствовал → создан. Залив rclone v1.74.2 (env-var s3-remote, без записи cred), `App_Data\assets``min:assets` verbatim. Verify `rclone size` == source: 4750 объектов / 225935853 B.
- **Smoke (мимо LAN-DNS воркстейшна, `--resolve …:89.253.255.133`):** предподписанный imgproxy-URL brevno.jpg → 200 image/webp 64556 B; валидно-подписанный (IMGPROXY_KEY/SALT с books-vds) несуществующий объект → 404 text/plain. 200 не ложный — imgproxy реально ходит в S3.
- **Scope расширен намеренно:** задача про pilorama98, залито всё (215 MiB — мизер). owner→сайт маппинг неочевиден (риск пропустить owner pilorama98), заливка всего гарантирует покрытие + закрывает класс-404 для всех тенантов. Регрессии нет (shared bucket, как galleries).
- **Wiki:** concept `galleries-storage-class-local-not-s3` обновлён (assets done).
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: victor/snolla / 2026-06-13T19:31:07.686Z -->
<!-- closed-by: vitya@.admin-exec / 2026-06-13 / path A: bucket assets + весь App_Data\assets (4750 obj/215.5 MiB), imgproxy 200/404 verified, snolla code unchanged -->
---

View File

@@ -53,6 +53,12 @@ curl -sk --resolve imgproxy.kzntsv.site:443:127.0.0.1 'https://imgproxy.kzntsv.s
- **pilorama98** (siteId `37e67fc44b9e4c06a522a26a73bac9b0`): мигрирован 2026-06-12 — 301 файл / 77 MiB, imgproxy 200 verified.
- **Остальные ~40 siteId-папок** в `App_Data\galleries`НЕ мигрированы (часть пустые). Bucket `galleries` shared; заполнен только префикс pilorama98. Другие сайты в snolla → 404 пока не зальёшь (регрессии нет).
- Если поднимаются другие Local-классы (`assets`/`images`/…) в snolla через imgproxy — их ждёт та же дыра, тот же рецепт.
- Если поднимаются другие Local-классы (`images`/`scripts`/`stylesheets`/`watermarks`) в snolla через imgproxy — их ждёт та же дыра, тот же рецепт.
См. задачу `.tasks/STATUS.md``[migrate-gallery-originals-to-s3]`.
### `assets` класс — мигрирован 2026-06-13
Тот же Local-класс, тот же путь A. **Отличие ключа:** prefix = `OwnerId` медиа-папки (из таблицы `Folders`), **НЕ siteId**; snolla строит `s3://assets/<ownerId>/<storageFilename>` (`middleware/assets.js:98`), storageFilename плоский. Залит **весь** `C:\sites\snolla\App_Data\assets` (145 owner-папок, 4750 файлов / 215.5 MiB) в новый bucket `assets` rclone'ом с RUVDS — scope шире pilorama98 (owner→сайт маппинг неочевиден; заливка всего гарантирует покрытие + закрывает класс для всех тенантов). Verify count+size == source. Smoke: brevno.jpg → 200, валидно-подписанный фейк → 404.
⚠️ На стороне snolla `content-api/routes/assets.js` — пустой stub: объекты в S3 есть и отдаются через imgproxy, но inline-картинки контента не отрендерятся, пока роут не реализован (код-таска snolla).
См. задачи `.tasks/STATUS.md``[migrate-gallery-originals-to-s3]`, `[migrate-assets-originals-to-s3]`.