From 8dc856b92d5e10d5028ba6a66aa1ab487ebbd65c Mon Sep 17 00:00:00 2001 From: OpeItcLoc03 Date: Sat, 13 Jun 2026 19:31:08 +0000 Subject: [PATCH] meta(tasks): create [migrate-assets-originals-to-s3] in OpeItcLoc03/admin --- .tasks/STATUS.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/.tasks/STATUS.md b/.tasks/STATUS.md index 68dc831..a0c243e 100644 --- a/.tasks/STATUS.md +++ b/.tasks/STATUS.md @@ -431,3 +431,49 @@ vehicles-loader (stostayer) деплоится в Docker у клиента (lite --- + +## ⚪ [migrate-assets-originals-to-s3] — Залить Local-storage assets-оригиналы сайта pilorama98 в S3 — латентная дыра того же класса, что галереи (закрыта миграцией `migrate-gallery-originals-to-s3`). snolla отдаёт inline-картинки контента (``) через imgproxy с источником `s3://assets//`, но объектов в S3 нет — imgproxy 404 "Source image is unreachable". БД-записи есть, файлы только на legacy-IIS диске. Тип `StorageClient="assets"` — это `MoreThenCms.FileStorage.Local.*`, в S3 никогда не мигрировали. + +## Acceptance criteria +1. Legacy assets-оригиналы pilorama98 залиты в S3 bucket `assets` ключами `/` (path A, как с галереями: storageClient = имя бакета). +2. Контрольный прозвон imgproxy подтверждает 200 image/webp на реальном объекте + 404 на несуществующем (негативный контроль). +3. Verify: dest object count == source, размер == source. +4. Зафиксирована точная форма ключа и охват (какие ownerId/папки залиты), отчёт в inbox victor/snolla. + +## Подтверждённое репро (от victor/snolla, 2026-06-13) +- URL у консьюмера: `http://localhost:3742/assets/83150d773cf0455ea58ddcccb2578713/800x450/brevno.jpg` → 404. +- БД `MoreThenCms` (mssql.kzntsv.site), таблицы `Folders`/`Files`: + - `Folders`: OwnerId `83150d77-3cf0-455e-a58d-dcccb2578713` → корневая папка `/` (FolderId `03CE5D8D-95B9-4D81-B222-80AEC76225CD`). **Внимание: ownerId это владелец медиа-папки, НЕ siteId** (siteId pilorama98 = `37e67fc4…`). + - `Files`: `brevno.jpg` → StorageClient `assets`, StorageFilename `brevno.jpg`, ContentType image/jpeg, Size 580667 B. +- Прямой прозвон imgproxy подписанным URL источника `s3://assets/83150d773cf0455ea58ddcccb2578713/brevno.jpg` → **HTTP 404 "Source image is unreachable"** (подпись валидна, объекта в S3 нет). +- Подписанный путь для верификации после заливки: + `https://imgproxy.kzntsv.site/n8AdQMelCr2lIvWzeQ3Mw6Fqxft3Q24Rd3vCg-ctHaA/fill/800/450/ce/1/czM6Ly9hc3NldHMvODMxNTBkNzczY2YwNDU1ZWE1OGRkY2NjYjI1Nzg3MTMvYnJldm5vLmpwZw.webp` → ждём 200 после миграции. + +## Подсказки по форме ключа (важно — отличие от галерей) +- Галереи: prefix = `String(site.id)` (siteId сайта). Ассеты: prefix = **OwnerId папки из таблицы Folders**, НЕ siteId. Для brevno.jpg это `83150d773cf0455ea58ddcccb2578713`. На диске ассеты, вероятно, разложены по этим owner-id, а не по siteId. +- Ключ верстается snolla как `s3://${asset.storageClient}/${ownerId}/${asset.storageFilename}` (`middleware/assets.js:98`), storageFilename берётся verbatim (с заменой `\`→`/`). +- Залить ВСЕ assets-папки/owner'ы pilorama98 (не только owner brevno.jpg) — иначе остальные inline-картинки контента дадут ту же дыру. + +## Хвосты (контекст, не блокеры) +- Тот же Local-класс у `images / scripts / stylesheets / watermarks` — если snolla отдаёт их через imgproxy, их ждёт та же дыра (отдельный аудит на стороне victor/snolla, таска `audit-local-storage-clients-imgproxy-s3-gap`). +- На стороне snolla отдельно нужна реализация `content-api/routes/assets.js` (сейчас пустой stub) — это код-таска victor/snolla, не блокер миграции, но картинки не поедут пока не сделаны ОБА (миграция + роут). + +## Обязательные скилы — вызвать до начала работы +- invoke `using-tasks` — управление статусом задачи +- invoke `project-discipline` — дисциплина коммитов/пушей +- invoke `using-projects-meta` — cross-project: отчёт в inbox victor/snolla при close/park +- invoke `systematic-debugging` — прозвон по фактам (DB → диск → S3 → imgproxy) до выводов + +**TDD:** нет — инфра-миграция/ops (если всплывёт код — отдельной impl-таской с TDD). +**Разрешения:** интерны: нет | автопуш: да +**weight:** needs-human +**notify:** victor/snolla + +**Status:** ready +**Where I stopped:** (not started) +**Next action:** Найти legacy-диск assets-оригиналов pilorama98, залить в S3 bucket `assets` ключами `/`, прозвонить контрольный imgproxy-URL → ждём 200. +**Branch:** n/a +**Notify:** victor/snolla + + +---