Разбор 500 на /admin/assets/<owner>/delete → корень ACL (app pool RX-only на App_Data после scp-миграции) → полная развязка хранилища CMS: - S3 FileStorage провайдер (MoreThenCms.FileStorage.S3) построен (координация с интерн-сессией) и раскатан LIVE на прод RUVDS: 6 контентных классов web.config → S3/MinIO, кэши остались Local. Смок 7 тенантов 200/301, 0×500, S3-read byte-parity. Upload-гоча: UseChunkEncoding=false (MinIO ⊥ AWSSDK aws-chunked). - Весь локальный контент RUVDS → MinIO (galleries 5.3G, themes 2.7G, maxMind); imageCache-блоат (2.1G) выпилен из бакета themes. - stostayer.old определён как stale-копия (не мигрировать). Новый concept: snolla-admin-appdata-acl-500-after-scp-migration. Трекеры: morethencms-s3-filestorage-provider (LIVE), reconcile-local-assets-to-minio (done). Rollback: web.config.bak-pre-s3-2026-07-03 на хосте. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.4 KiB
[morethencms-s3-filestorage-provider] — S3-провайдер FileStorage для MoreThenCms (MinIO)
Status: 🟢 LIVE на прод RUVDS (2026-07-03). Split-brain закрыт: боевой catch-all C:\sites\snolla теперь читает/пишет ассеты/темы/галереи из MinIO. Локальный IIS (windows-recovery-host) — отложен до ухода сайтов с RUVDS (решение user).
Прод-cutover RUVDS (2026-07-03)
- Backup:
web.config.bak-pre-s3-2026-07-03+ IIS-снапшотpre-s3-cutover-2026-07-03. Rollback = restore + recycle (Local вернётся, MinIO не трогается). - 3 DLL (S3+AWSSDK.*) →
C:\sites\snolla\bin. web.config<fileStorageClients>: 6 контентных классов (assets/galleries/images/scripts/stylesheets/watermarks) → S3, креды в конфиге (ACL SYSTEM+Admins); кэши (imageCache/uploadCache/contentCache/_imageCache-Azure) оставлены Local. Правка — точечный regex, UTF-8/BOM сохранён, XML валиден (10 записей). - Pre-flight: RUVDS→minio.kzntsv.site:443 = TCP+HTTPS 200. Egress ок.
- Smoke GREEN: 7 тенантов 200/301 (0× 500); S3-read вживую — theme CSS
16ba5cb8…/css/lato.css→ 200/9239b/text/css, byte-parity с MinIO. Write-механика — self-test цикл (ранее). - imageCache-прун бакета
themes(2.1 ГБ мусора) — фоном bfb8wy94n. Валидация (standalone-проба, IIS/elevation не нужны): Read/key/byte-parity ✅ + full self-testput→exists→download(MD5==)→delete→exists=false✅ после upload-фикса. Upload-фикс:UseChunkEncoding=falseвPutObjectRequest(MinIO отвергает AWSSDK 3.7 aws-chunkedSTREAMING-AWS4-HMAC-SHA256-PAYLOAD;DisablePayloadSigningНЕ помогает). 17/17 юнитов + интеграция._selftest/-мусора нет.
Метод валидации (важно — IIS/elevation НЕ нужны)
Провайдер чистый (AWSSDK + базовый FileStorageClient, без SnollaHost/Autofac) → грузится standalone в PowerShell: загрузить 3 DLL из deploy/ + зависимости из C:\sites\stostayer.old\bin (резолвер с guard от рекурсии), инстанцировать AssetsStorage через $type::new($cfgDict), гонять против real MinIO. Проба: scratchpad s3-provider-probe.ps1 + s3-upload-diag.ps1. stostayer.old НЕ трогается (только его DLL читаются в чужой процесс). Self-test пишет в throwaway assets/_selftest/ (чистится).
Owner-split: код — прогер (проект MoreThenCms); координация + deploy + приёмка — admin (я).
Ключ-конвенция (ground-truthed 2026-07-03, финал)
Провайдер = калька с Local (не Azure — Azure в бою не гонялся), ключи по snolla-фронту packages/core/lib/services/storage.js (key = ownerId.toLowerCase()+'/'+storageFilename).
- assets: bucket
assets, ключ<ownerId:N>/<file>— ownerId без дефисов (админка отдаётToString("N"), объекты в MinIO без дефисов). НЕ вставлять дефисы. - themes (css/images/js/watermarks): единый bucket
themes, ключ<themeId:N>/{css,images,js,watermarks}/<file>. scripts=js(не/scripts!). watermarks НЕ отдельный бакет — они вApp_Data\themes\<themeId>\watermarks\(LocalWatermarksStorage), 11 файлов вкл. tandemmebel.ru. - galleries: bucket
galleries, ключ<siteId:N>/<file>плоско (без/images). - Azure separator-баг (
prefix+fileUriбез/) прогер поймал →Trim('/')+"/"+fileUri. - Configuration net461→net462 (
OpeItcLoc03/MoreThenCms.Configuration 3e79ff2) — build-only, на прод НЕ едет (шипим только 3 DLL). - Приёмка на локальном IIS: key-parity + byte-parity sweep (ключ совпал с существующими + MD5==).
Зачем
Админка MoreThenCms пишет ассеты на локальный диск IIS (App_Data, провайдер FileStorage.Local), а боевой фронт snolla читает из MinIO → split-brain (правка в админке не видна на сайте). Плюс отдельный симптом — 500 на delete из-за RX-only ACL (пофикшен 2026-07-03 выдачей Modify, но это лечит только delete, не устраняет раздвоение). Настоящее закрытие — посадить админку на тот же MinIO через S3-провайдер, которого в кодовой базе нет (есть только Local и Azure).
Решения (приняты)
- Новая сборка
MoreThenCms.FileStorage.S3— калька сMoreThenCms.FileStorage.Azure, backendAWSSDK.S3против MinIO (ForcePathStyle=true). - Объём: все контентные классы (Assets/Galleries/Images/Scripts/Stylesheets/Watermarks). Кэши (image/upload/content) остаются Local.
- Один MinIO на всех:
minio.kzntsv.site(books-vds, 89.253.255.133), path-style. Bucket = имя класса, ключ =<prefix>/<file>без ведущего слэша (parity с уже мигрированными объектами). - Deploy target админки: локальный IIS на windows-recovery-host (репрпоуз PC; серверная роль была декоммишнута, сам PC жив). DNS-аудит 2026-07-03: инфра-хосты
*.kzntsv.siteрезолвятся в реальные IP, перехвата127.0.0.1НЕТ — костыль в конфиг не нужен.
Where I stopped
ТЗ (полное, под новичка, с таблицей префиксов и выделенной граблей «ведущий слэш в ключе S3») лежит в ~/projects/MoreThenCms/.claude-inbox/2026-07-03T06-40-09Z-admin.md.
Next action
Дождаться MoreThenCms.FileStorage.S3.dll от прогера → развернуть на локальный IIS (windows-recovery-host) → сквозняк: upload из админки → объект в MinIO с корректным ключом+Content-Type → фронт через imgproxy отдаёт 200 → byte-parity (ETag/MD5). Затем deploy на боевой + переключить <fileStorageClients> секцию, секреты прокинуть из окружения (не хардкод).
Пайплайн
ТЗ ✅ → сборка ⏳ (прогер) → deploy-local ⏳ → сквозняк-приёмка ⏳ → deploy-remote ⏳ → close split-brain.
Контекст
.wiki/concepts/snolla-admin-appdata-acl-500-after-scp-migration.md(500 + split-brain + fix).wiki/concepts/galleries-storage-class-local-not-s3.md(Local-класс, миграция в S3, префиксы)- Абстракция:
MoreThenCms/FileStorage/FileStorageClient.cs+Azure/AzureCloudStorage.cs(образец)
Branch: n/a (admin ops + external code)