Шаблон обещает убрать первые сорок минут новой задачи: структура каталога, имя сервиса, ownership, минимальная документация, базовый delivery-маршрут. Проблема начинается, когда он начинает решать то, чего команда ещё не решила. В форму добавляют переключатель для нового runtime, особого хранения, исключения из policy и «временной» ветки CI. Через несколько запусков один и тот же шаблон выдаёт несовместимые стартовые точки. Цена не в YAML. Review становится длиннее, поддержка спорит с каждым generated repository, а локальная правка превращается в fork без владельца.
Сильный template не пытается покрыть все будущие сервисы. Он экономит работу там, где ответ уже повторяется и известен owner. Остальное нужно вынести из формы: либо в названное расширение, либо в короткий design review. Это выглядит как ограничение выбора, но именно оно оставляет стартовый путь дешёвым для следующей команды. Если шаблон содержит пять альтернативных архитектур, он перестаёт быть golden path и становится каталогом чужих рисков.
Симптом → причина → проверка → действие
- Симптом. В запросе на новый сервис появляются фразы «добавьте одну галочку», «скопируем соседний generated repo» или «после создания поправим всё руками».
- Причина. В template не отделены повторяемые факты от конкретного решения. Поле формы выдали за договор, а локальное исключение выдали за следующий default.
- Проверка. Для каждого поля спросите: есть ли у него известный owner, одинаковое значение для повторяемого класса задач и обратимый путь, если оно оказалось неверным? Если ответ хотя бы раз нет, поле не принадлежит base template.
- Действие. Оставьте в golden path только стабильный контракт. Для известного варианта создайте named extension с owner и условием удаления. Для неизвестного варианта откажитесь от template и начните отдельный design path.
Начать с контракта, а не с набора файлов
Практический template можно описать одной карточкой. В ней есть идентификатор и версия, owner, целевой тип компонента, обязательные факты, список того, что он создаёт, и список того, чего он принципиально не обещает. Например, internal HTTP service с известным owner-ом, одобренным runtime и internal data class. Шаблон может подготовить skeleton, draft catalog metadata и checklist review. Он не может выдать production approval, доказать безопасность, измерить adoption или назвать будущую скорость работы команды.
Эта разница полезна и автору шаблона, и потребителю. Команда получает понятный вход: service name, owner и класс решения. Платформа получает границу: не надо угадывать retention policy или выбирать архитектуру за доменную команду. Если один из входов неизвестен, это не ошибка пользователя формы. Это сигнал, что задача не готова к конвейеру. В такой точке быстрый отказ экономит больше времени, чем генерация заготовки, которую потом переписывают.
| Часть | Фиксируем | Не фиксируем | Почему |
|---|---|---|---|
| Идентичность | имя сервиса, owner, версия template | название будущей команды или продукта | контракту нужен ответственный, но он не предсказывает организацию |
| Повторяемая форма | internal HTTP service и approved runtime class | новый runtime ради одной задачи | повторение уменьшает стоимость старта; новый выбор требует design review |
| Выход | skeleton, metadata draft, review checklist draft | production approval и итог CI | generated файл не является доказательством запуска |
| Data policy | явно выбранный internal class | новая retention или access model | policy нельзя безопасно спрятать в переключатель |
| Изменение | named extension с owner и rollback | локальный patch в каждом generated repo | расширение остаётся видимым; копия быстро теряет общий контракт |
Как выглядит короткий договор
Договору не нужен внутренний фреймворк команды. Достаточно назвать факты, которые должен сохранить любой результат. У generated проекта есть owner; его тип соответствует заявленному классу; runtime относится к перечню, который уже поддерживается; metadata не прячет новый policy. Важно записать и отрицательную часть: template не создаёт секреты, не меняет production, не выбирает retention и не подменяет security review. Так новый автор не превратит «удобную заготовку» в невидимую систему полномочий.
// Только учебная запись контракта; это не реальный template.yaml.
const goldenPathContract = {
templateId: 'synthetic-service-golden-path-v3',
owner: 'synthetic-platform-templates-owner',
supports: 'internal-http-service',
requires: ['owner', 'approved-runtime', 'internal-data-class'],
produces: ['repository-skeleton', 'catalog-metadata-draft'],
refuses: ['new-retention-model', 'unknown-owner', 'one-off-migration'],
extension: 'named-observability-adapter-with-owner-and-rollback',
};
// Никаких файлов, CI, usage и реального repository здесь нет.
Golden path должен быть узким
Узкий не значит бедный. Он может собрать все договорённости, которые команда уже повторяет: расположение документации, обязательные labels, способ зарегистрировать компонент, базовый health endpoint или checklist. Но каждое правило должно отвечать на один вопрос: кто меняет его, если оно устарело? Если owner не назван, правило нельзя обновить без массового угадывания. Если оно зависит от доменной модели одной команды, оно не является общим default.
Backstage в snapshot v1.25.0 описывает Software Templates как skeleton с переменными и последовательными steps, которые могут публиковать результат. Это полезный механизм, когда входы и шаги уже согласованы. Из его возможностей не следует, что любой новый step должен появляться во всех template. В документации также видны логи шага и отмена task; это помогает расследовать запуск, но не превращает task log в правило архитектуры или в отчёт о качестве внедрения.
Escape hatch: расширение вместо fork
Escape hatch нужен не для того, чтобы обойти каждый guard. Он нужен для случая, который остаётся в том же классе работы, но требует одного известного подключения. Пример: service на approved runtime нуждается в заранее описанном observability adapter. Extension должен иметь name, owner, ограниченную границу, условие удаления и rollback. Его output добавляется к base contract, а не заменяет owner, data class, runtime или delivery policy. Тогда reviewer видит, что было исключением, а будущая версия template может решить, стало ли оно общим.
Fork выглядит дешевле: команда копирует generated repository и меняет всё, что мешает. Но GitHub прямо указывает, что ветви repository, созданного из template, имеют несвязанную историю. Это нормальная механика создания нового репозитория, а не канал дальнейшей синхронизации. Поэтому нельзя надеяться, что исправление base template само найдёт все копии. Если команда всё же выбирает самостоятельный путь, его надо назвать самостоятельным design decision, а не «временной настройкой шаблона».
Порядок принятия решения
- Назвать повторяемый класс. Запишите одно предложение: какой компонент создаётся, какой owner и какой runtime/data class уже одобрены. Не добавляйте поля, которые существуют только ради текущей истории.
- Сверить base contract. Проверяйте не файлы, а инварианты: тип, owner, обязательные facts и список обещанных outputs. Совпало — выбирайте golden path.
- Проверить extension. Если различие одно и уже имеет name, owner, границу и rollback, создайте review на extension. Extension не получает право расширять base policy.
- Отказаться вовремя. Если нет повторяемой формы, неизвестен owner, нужна новая access/retention модель или пользователь должен изменить инвариант, form заканчивается. Следующий артефакт — design record, не fork.
- Вернуть результат в цикл. После реального review обновите контракт либо добавьте скоуп extension. Не объявляйте template улучшенным по ощущениям; соберите разрешённые evidence отдельно.
Когда отказ — правильный результат
Особенно опасна задача «один раз перенесём регулируемые данные, а потом, может быть, повторим». В ней ещё нет стабильного component type, неизвестны ownership и lifecycle, а retention и access могут быть собственными решениями. Попытка вставить её в service template скрывает вопросы под нейтральными параметрами. Форма создаст видимость готовности, но команда всё равно будет принимать архитектуру уже после генерации. Правильный ответ здесь: не template пока.
Это не запрет на рост платформы. После нескольких разрешённых design review может появиться устойчивый класс работ и понятный owner. Тогда можно выделить отдельный golden path или extension. Но сперва должен появиться договор, а не набор прошлых копий. Критерий прост: если чтобы пройти форму надо нарушить base invariant, не добавляйте переключатель. Зафиксируйте отказ, объясните следующую проверку и оставьте путь обратимым.
Ограничения, rollback и следующий шаг
Template contract не заменяет threat modeling, legal review, capacity planning, тесты, CI или migration plan. Он не доказывает, что generated repository можно деплоить, и не обязан совпадать со всеми repository teams. Backstage и GitHub описывают конкретные механизмы scaffolding и template repository, а не универсальную организационную policy. Прежде чем привязать реальный action к форме, отдельно задайте разрешённую область, credential boundary и способ проверить output.
Rollback для решения тоже должен быть коротким. Пока создан только draft contract или extension proposal, удаляется именно он; не нужно откатывать чужой template или переписывать repositories. Если расширение оказалось неверным, команда возвращается к versioned base contract и проводит обычный design review. Следующий шаг — выбрать одну часто повторяемую заявку и заполнить для неё пять полей: class, owner, invariants, allowed extension, refusal criterion. Если поле не удаётся назвать без текущей истории, не переносите его в template.
Историческая граница мая 2024
Материал ограничен Backstage v1.25.0 и GitHub Enterprise Server 3.12: оба источника доступны до конца мая 2024. Они подтверждают, что template может подставлять переменные и создавать новую структуру repository, но не подтверждают adoption, скорость, качество конкретной команды или автоматическую синхронизацию forks. Автор уровня M7 использует инструмент как узкий контракт, а не как повод скрыть незакрытое архитектурное решение.
Проверяемые источники
- Backstage v1.25.0: Software Templates, апрель 2024 — Первичный снимок документации Backstage, выпущенный до конца мая 2024. Software Templates умеют загрузить skeleton, подставить переменные и опубликовать результат; задача показывает шаги и поддерживает отмену, но документ не обещает скорость внедрения, корректность конкретного template или автоматическую синхронизацию с будущими изменениями.
- Backstage v1.25.0: Adding your own Templates, апрель 2024 — Первичная документация формата Template: owner, type, parameters и последовательные steps. Она показывает возможности scaffolder-а, но не определяет policy команды, допустимость всех action, безопасность секретов или критерий, когда от template нужно отказаться.
- GitHub Enterprise Server 3.12: Creating a template repository — Первичная историческая документация GitHub, доступная до мая 2024. Новый repository получает структуру и файлы template, однако ветви имеют несвязанную историю. Это объясняет риск самостоятельных копий; источник не описывает portal-template, ownership или процесс обновления команды.