Тема
Фаза 0 — Открытые детали реализации
Статус: сводка незакрытого. Спеки фазы 0 написаны; здесь собраны уточнения, которые спеки честно оставили «до кода». Ни одно не блокирует старт фазы 1 — у каждого есть рекомендованный дефолт, который правится при первой реализации без переделки контракта. Закрываются в начале фазы 1 (реализация ядра-минимума), а не сейчас.
Как читать
Каждый пункт: вопрос, рекомендованный дефолт (что берём, если не переспорят), когда закрыть. Дефолт выбран так, чтобы более простой вариант можно было усложнить позже без слома данных клиентов.
Блоки и ревизии
| Вопрос | Рекомендованный дефолт | Когда |
|---|---|---|
Формат id экземпляра блока/виджета | ULID — сортируемый по времени, стабилен в диффе ревизий, короче UUID | фаза 1, при первой модели страницы |
| Гранулярность ревизии страницы | снимок всего дерева блоков (не дифф) — проще и надёжнее для отката; дифф — оптимизация позже, если место станет проблемой | фаза 1 |
| Ретеншн ревизий | конфиг cms.revisions.keep (напр. последние N + все published); чистка старых по расписанию | фаза 1 |
| Граница ленивой vs блокирующей data-миграции блока | обновление модуля с ломающей схемой → батч cms:blocks:migrate в процедуре апгрейда; ленивая при рендере — только страховка от пропущенных | фаза 1, стык с центром обновлений |
Миграция _v в исторических ревизиях | батч обрабатывает только published + последний черновик; старые ревизии мигрируют лениво при откате на них; мажор модуля сохраняет цепочку миграций минимум на 2 мажора назад | фаза 1 |
| Медиа ↔ ревизии (GC) | GC неиспользуемых медиа учитывает ссылки из всех хранимых ревизий, не только published — иначе откат страницы даст битые изображения | фаза 1 |
| Конкурентное редактирование страницы | last-write-wins + неблокирующее предупреждение «страницу редактирует X»; полноценный лок — только если появится реальная боль | фаза 1 |
Источник: контракт блока, модель данных.
Предпросмотр черновика (Preview)
| Вопрос | Рекомендованный дефолт | Когда |
|---|---|---|
| Механизм превью черновика в обход page-cache | подписанная токен-ссылка на draft-ревизию; обычный рендер/API отдаёт только published | фаза 1, стык Q7 + API-контракт |
| Кто потребитель превью | острова предпросмотра в админке + внешний headless-фронт (если клиент строит свой) | фаза 1 |
Упоминается в трёх спеках (блок, API, модель данных) — при реализации свести в один механизм, не три.
Установка и перенос контента
| Вопрос | Рекомендованный дефолт | Когда |
|---|---|---|
| Профиль установки — пакет или часть skeleton | отдельный пакет cms/profile-*, чтобы обновлялся независимо от skeleton | фаза 1 |
| Медиа в переносимом bundle | ссылка на файл в media/ bundle (не встраивание в YAML) — компактнее, проще диффать | фаза 1, стык модель данных |
| Проверка модели на реальных данных | ETL-импорт universal (реляционные блоки → JSONB) как контрольный пример — если модель не принимает universal чисто, модель неверна | фаза 1 (контроль), полный перенос — фаза 4 |
Мультиязычность/мультигород (заготовка)
| Вопрос | Рекомендованный дефолт | Когда |
|---|---|---|
| Локаль/город как измерение хранения | поля locale/city_id заложены в моделях (cms_pages, cms_settings, cms_widgets), но null = глобально; измерение активирует модуль | ядро — фаза 1 (только поля); модуль — по заказу (Q6) |
Заготовка в ядре, стратегия (city-based vs spatie/laravel-translatable) — в модуле под конкретный заказ. Ядро остаётся нейтральным.
Операционное перед стартом кода (не документация)
Это не «открытые детали спек», а подготовка инфраструктуры фазы 1 — вынесено сюда для полноты картины «что осталось»:
- имя продукта — рабочее «Rosveb CMS» уточняется (Q2);
- self-hosted git + Satis — поднять Gitea/GitLab + Satis на инфре студии, добавить в бэкап-процесс (центр обновлений);
- эталонный Docker-образ PHP 8.4 с набором расширений — единый для парка (стек);
- первый клиентский заказ — триггер фазы 1 (Q1): до него код не пишется намеренно (YAGNI + обкатка под дедлайном);
- провижининг сайта end-to-end — скрипт «
composer create-project→ Docker →proxy connect/proxy dns publish→ сертификат LE» на существующей инфре студии (Caddy/ISPmanager CLI): прямой вклад в метрику «развёртывание за день»; - политика регулярных бэкапов (не только перед обновлением): расписание, ретеншн, offsite (S3), периодический restore-тест — обещание подписки из README, контроль в телеметрии;
- миграция с чужих CMS (WordPress/Tilda/Битрикс) — импортёр как модуль «Импорт данных»: частый сценарий продажи, ETL universal его не покрывает;
- staging-проверка обновления — эфемерная копия сайта (снапшот БД + контейнер) для smoke-теста перед прод-апгрейдом первой канарейки, либо зафиксированный осознанный отказ («канареечных волн достаточно»).
Принцип закрытия
Все дефолты выбраны по правилу «проще сейчас, усложнить потом без слома данных»: снимок ревизии → дифф позже; ULID → не меняется; профиль-пакет → независимое обновление; поля локали заложены, но спят. Ни один дефолт не загоняет в угол — поэтому фаза 1 стартует без ожидания их окончательного решения.
Связи
- Дорожная карта — фазы, где эти детали закрываются.
- Контракт блока, модель данных, API-контракт — источники открытых деталей.
- Решения — Q1 (первый заказ), Q2 (репозиторий), Q6 (мультиязычность), Q7 (ревизии).