Шаблоны и каталог¶
Два механизма переиспользования в Axon. Templates (
module_catalog) — обезличенный слепок (workflow / chain / project), реализованный поверх Module Library: clone из production с анонимизацией и переменными, применяется внутри одного инстанса как «копия для нового проекта». Workflow Definition Catalog (workflow_definition_catalog) — instance-wide публикация переиспользуемойWorkflowDefinition: developer публикует черезaxon push --catalog, manager устанавливает в свой проект через Console. Catalog — это шов между developer и manager, не маркетплейс, не cross-instance. Канон: ARCHITECTURE-V6 §15 (Templates), §8 (DDL).
1. Что это и зачем¶
Module Library (module_catalog)¶
Простой реестр reusable модулей — без maturity lifecycle и без kit ceremony (V6 убрал тяжёлый Domain Pack из V5). module_type ∈ {connector, tool, workflow_template, chain_template, project_template, policy_template}. module_catalog.content — сериализованное тело модуля; module_catalog.config_schema — JSON Schema configure-time параметров для UI/валидации. Это «откуда брать defaults коннектора, тело шаблона, спецификацию tool'а».
Три уровня Templates¶
- Workflow template — слепок одного
WorkflowDefinitionс переменными ({{ project_id }},{{ slack_channel }}, и т.д.) и optional anonymisation rules. Применяется → создаёт новыйWorkflowDefinitionв целевом проекте. - Chain template — слепок цепочки workflow (несколько определений + связи). Применяется → создаёт несколько
WorkflowDefinitions + сетку привязок. - Project template — слепок project-level конфигурации (workflows + roles + connector requirements + policy defaults). Применяется → разворачивает новый проект «из коробки».
Templates работают через UI «Templates» (Module Library section) и через canonical handlers — secrets никогда не переносятся в template body (только references/placeholders).
Workflow Definition Catalog¶
Отдельная сущность (app.workflow_definition_catalog, global scope — project_id IS NULL). Это карточки опубликованных WorkflowDefinition-снапшотов, видимых всем проектам инстанса. Manager заходит в Catalog, видит карточку («Email triage pipeline v2», автор admin, теги), нажимает Install → в его проект записывается копия definition с metadata-меткой «installed_from_catalog_entry_id». Это не source of truth для runtime — runtime читает app.workflow_definitions проекта; catalog нужен только для discovery + install.
Разница с Template (Module Library):
| Аспект | Workflow Template (module_catalog) |
Catalog Entry (workflow_definition_catalog) |
|---|---|---|
| Scope | instance-wide reusable модуль | instance-wide reusable определение |
| Применение | «применить шаблон в проект» (с переменными/anonymisation) | Install в проект (snapshot копия, без переменных) |
| Cross-developer handoff | manager-driven (взять готовый шаблон) | developer-published → manager-installed |
| Маркетплейс | да (UI: Module Library) | нет (только этот инстанс) |
| Auto-update | нет (template — слепок) | нет (install — snapshot; новая версия требует новый install) |
| Mode A/B/C | любой | только Mode A (Catalog rejects inline credential_id и connector_key — переносимость требует connector_requirement) |
2. Роли и доступ¶
Из core/models/auth.py. Полная матрица — Roles-And-Permissions.md.
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Workflow / chain / project templates: создать/применить/архивировать | manage_templates |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Catalog: publish / archive | catalog:manage |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Catalog: install в проект | catalog:install |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Catalog: смотреть карточки | read (instance-wide) |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
Engineer — не RBAC-роль, работает в коде (
modules/workflows/, git) и через CLIaxon push --catalog. Чтобы публиковать в catalog, у CLI-актора должна бытьcatalog:manage(обычно admin/owner; для CI-автоматизации — system actor сcatalog:manage).
Все мутации — через CommandEnvelope. Command types: publish_to_catalog, archive_catalog_entry, install_catalog_entry. Backdoor SQL запрещён.
3. Где это в Console¶
Раздел Templates (Module Library)¶
Доступен для admin/owner (manage_templates).
| Экран | Что на нём |
|---|---|
| Список шаблонов | таблица: module_type, key, name, version, теги, кнопка Apply |
| Применить шаблон | модал: выбрать целевой проект, заполнить переменные (по config_schema), включить/выключить anonymisation rules, привязать коннекторы (auto-mapping предлагает кандидатов по типу) |
| Создать шаблон (из существующего workflow / project) | модал-визард: выбрать source, описать анонимизацию (regex по полям, dropping ids), задать переменные с дефолтами |
Раздел Catalog (Workflow Definition Catalog)¶
Доступен всем (read), действия — catalog:manage / catalog:install по правам.
| Экран | Что на нём |
|---|---|
Catalog list (/admin/catalog) |
таблица: name, definition_key, version (latest), теги, published_at, published_by. Поиск по тегам/имени. Карточка содержит requirement summary — список connector_requirement[*].requirement_key + тип (gmail / generic_http / ...), это видно ещё до Install. |
| Catalog entry detail | полное описание: definition JSON (read-only), connector_requirements, история версий (1..N), action Install to project (manager+), action Archive (admin+) |
| Install to project modal | выбрать целевой проект, опционально override definition_key (если в проекте уже есть definition с таким именем — collision); preview списка connector_requirements, которые надо будет привязать (потом, через Bindings) |
CLI: axon push <path> --catalog (взаимоисключим с --project / AXON_PROJECT). См. §5.3.
4. Концепции (mental model)¶
Module Catalog: config_schema vs content¶
config_schema— JSON Schema configure-time параметров (которые пользователь заполняет при apply): «введи Slack channel», «введи Notion database ID». Используется UI для рендера формы и валидации.content— сериализованное тело модуля: для коннектора — defaults / metadata, для tool'а — spec, для template — JSON-формаWorkflowDefinitionс placeholder'ами{{ var }}. Безcontentшаблон негде materialize-ить.
Auto-mapping коннекторов¶
При apply workflow template / install catalog entry: для каждого connector_requirement в определении система ищет в проекте usable connector instance подходящего типа (adapter_key соответствует requirement).
- 1 кандидат → авто-привязка (auto_configured=true в binding profile).
- N кандидатов → UI просит выбор.
- 0 кандидатов → статус «requires connection» в Bindings; manager создаёт credential + CI и возвращается.
См. Connectors-Credentials.md §6.4 и WORKFLOW-ARCHITECTURE §4.
Catalog: latest-by-default + collision policy¶
- Latest-by-default. CLI
axon push --catalogопределяет version автоматически: еслиdefinition_keyуже есть — берётсяlatest_version + 1. Manager в Console видит карточку с latest version; install ставит latest. - Collision при install. Если в целевом проекте уже есть
WorkflowDefinitionс тем жеdefinition_key— handler возвращаетdefinition_key_already_exists_in_project(suggested:<key>_from_catalog). UI предлагает renaming черезdefinition_key_override. - Idempotency. Повторный install того же catalog_entry в тот же проект (один и тот же
catalog_entry_id+version) возвращает уже установленныйdefinition_idбез записи дубля (metadata-ключиinstalled_from_catalog_entry_id+installed_from_catalog_version). - Archive не трогает установленные копии.
archive_catalog_entry— soft-delete карточки в каталоге; уже установленныеWorkflowDefinitions в проектах продолжают работать.
Catalog Mode A only¶
Catalog entry должен быть переносим между проектами. Поэтому PublishToCatalogHandler отвергает:
- inline credential_id (Stage 1/Stage 2 Mode B) — CatalogModeBInlineRejected;
- {"$credential_ref": "input_data.X"} (Stage 2 Mode B-ref) — CatalogModeBRefRejected;
- connector_key в step.config (legacy Mode C) — CatalogModeCRejected.
Допустим только Mode A: connector_requirement ссылается на slot в WorkflowDefinition.connector_requirements[], который привязывается к конкретному CI в целевом проекте через binding profile после Install.
Catalog-install — это publish_definition под капотом¶
InstallCatalogEntryToProjectHandler.apply() копирует entry.definition, обогащает metadata (installed_from_catalog_entry_id, installed_from_catalog_version) и внутри той же транзакции вызывает PublishDefinitionHandler от имени актора-инсталлятора с source="catalog_install". То есть install проходит ровно ту же publish-time валидацию (sandbox, schema, secrets scan, requirements fingerprint), что и axon push от разработчика — никаких bypass-ов.
5. Флоу: пошаговые сценарии¶
5.1 Применить workflow template в проект (admin/owner)¶
- Templates → найти шаблон → Apply.
- Выбрать целевой проект, заполнить переменные (форма строится по
config_schema), включить anonymisation rules. - Submit → handler материализует
WorkflowDefinitionс подставленными переменными →publish_definitionот имени актора → определение появляется в проекте. - Дальше — обычный путь: настроить Bindings, запустить Run Wizard.
5.2 Создать проект из project template (admin/owner)¶
- Templates → Project template → Apply или Projects → + New from template.
- Заполнить переменные (имя проекта, env, и т.д.).
- Handler разворачивает: новый
project, наборWorkflowDefinitions, declaredconnector_requirements, default policy. Креденшiалы не переносятся — manager затем привязывает свои.
5.3 Опубликовать определение в Catalog (developer + admin/owner)¶
- Developer пишет
WorkflowSpecвmodules/workflows/<name>/definition.py. Только Mode A для всех connector-backed шагов (connector_requirement: "<requirement_key>"вstep.config, объявление вWorkflowDefinition.connector_requirements[]). axon push modules/workflows/<name>/ --catalog(без--project;AXON_PROJECTenv должна быть пустой — иначе CLI откажется).- CLI вычисляет content_hash, определяет version (
latest_version + 1или1, если нового key ещё нет), отправляетpublish_to_catalogкоманду сtarget_type='workflow_definition_catalog_entry',project_id=null, payload содержитdefinition+metadata. - Handler валидирует переносимость (
_validate_catalog_portability— Mode A check, raw secrets scan, binary-like fields rejected) → INSERT вapp.workflow_definition_catalog→ catalog_entry_id видаwdcat_<ulid>. Outbox-событиеworkflow_definition_catalog.published. - Failure modes:
catalog_portability_invalid— нашли Mode B / Mode C / raw secret;version_conflict— попытка перезаписать существующую неархивированную версию с другим content_hash;version_archived— попытка переиспользовать архивированный номер версии (нужно увеличить version);- идемпотентный re-push того же (definition_key, version, content_hash) → возвращает
already_published: trueбез дубля.
5.4 Установить из Catalog в проект (manager+)¶
- Catalog → выбрать карточку → Install to project.
- Выбрать целевой проект (
project:writeобязательно), опциональноdefinition_key_override(если предчувствуется collision). - Submit →
install_catalog_entry(target_type='workflow_definition',project_id=<target>). Handler: - находит
catalog_entry_id, проверяет non-archived; - проверяет idempotent re-install (тот же entry_id + version в том же проекте → возвращает существующий
definition_id); - проверяет collision (
definition_key_already_exists_in_project→ 409 +suggested_definition_key); - копирует definition, обогащает metadata (
installed_from_catalog_entry_id/installed_from_catalog_version); - вызывает
PublishDefinitionHandler(source='catalog_install') → новоеWorkflowDefinitionв проекте. - После Install: открыть Bindings, привязать
connector_requirementsк CI проекта (auto-mapping предложит, если есть usable CI того же типа).
5.5 Обновить установленное определение до новой версии Catalog¶
- В Catalog появилась новая версия — Manager в Console видит «v2 available» (UI бы должен подсветить, см. §8 если не показывает).
- Install to project с новой версией. Если в проекте уже есть определение из старой версии (тот же
definition_key) → handler вернётdefinition_key_already_exists_in_project. - Manager: либо
definition_key_override(две версии живут параллельно), либо сначала retire старую (отдельный workflow lifecycle action — не часть catalog). - Никакого автоматического upgrade в текущей версии нет (install — snapshot copy). Это сознательная разница с маркетплейсом: catalog — это диспетчеризация definition, не self-updating subscription.
5.6 Архивировать catalog entry (admin/owner)¶
- Catalog → entry detail → Archive (
catalog:manage). - Команда
archive_catalog_entry(target_type='workflow_definition_catalog_entry',project_id=null). - Handler:
deleted_at = now(),archive_reasonсохраняется. Idempotent: повторный archive того же entry → no-op. - Установленные копии не трогаются. Они продолжают работать в своих проектах; archive только убирает entry из default-видимого списка catalog.
6. Справочник опций¶
6.1 workflow_definition_catalog (DDL: alembic 036)¶
| Поле | Тип | Описание |
|---|---|---|
catalog_entry_id |
text PK |
префикс wdcat_, формат wdcat_<26-char ULID> |
definition_key |
text |
normalize'd snake_case; уникальность с (version) среди неархивированных |
version |
int |
≥ 1; повторный publish того же (key, version) → idempotent если content_hash совпадает, иначе version_conflict |
name, description, tags |
text / text / text[] | UI-метаданные |
definition |
jsonb |
копия WorkflowDefinition (Mode A only) |
metadata |
jsonb |
metadata-блок (без project_id — отвергается) |
content_hash |
text |
canonical hash definition + normalized metadata; ключ идемпотентности |
requirements_fingerprint |
text |
стабильный fingerprint connector_requirements[] для compatibility-проверок при install |
published_at, published_by_actor_id, published_via_command_id |
audit | |
deleted_at, archived_by_actor_id, archive_reason |
nullable; soft-archive |
6.2 module_catalog (DDL: alembic ранний, не Stage 3)¶
| Поле | Тип | Описание |
|---|---|---|
module_id |
text PK |
префикс зависит от типа |
module_type |
text |
connector / tool / workflow_template / chain_template / project_template / policy_template |
key |
text |
стабильный ключ модуля (для коннекторов — connector_key, для шаблонов — template_key) |
name, description, version, tags |
UI-метаданные | |
config_schema |
jsonb |
JSON Schema configure-time параметров |
content |
jsonb |
сериализованное тело модуля |
6.3 Команды (CommandEnvelope)¶
| Команда | path | target_type |
project_id |
Permission |
|---|---|---|---|---|
publish_to_catalog |
sync_apply |
workflow_definition_catalog_entry |
MUST be NULL (global target) | catalog:manage |
archive_catalog_entry |
sync_apply |
workflow_definition_catalog_entry |
MUST be NULL | catalog:manage |
install_catalog_entry |
sync_apply |
workflow_definition (target = новое определение в проекте) |
target project | catalog:install |
6.4 CLI axon push --catalog¶
| Опция | Описание |
|---|---|
--catalog |
публикация в instance catalog (project_id=null); взаимоисключим с --project и AXON_PROJECT env |
--idempotency-key |
manual override; иначе CLI считает catalog:{definition_key}:{version}:{content_hash} |
--force-new-version |
при равном content_hash всё равно создать новый version (обычно не нужно — идемпотентность сама вернёт already_published) |
7. Жизненный цикл и обслуживание¶
Templates (module_catalog). Lifecycle ручной: владелец проекта/инстанса создаёт шаблон → применяет → при необходимости архивирует/удаляет через manage_templates. Версионирования встроенного нет (поле version есть, но обновление = новая запись или замена). Анонимизация — обязанность создателя шаблона; секреты не переносятся.
Catalog (workflow_definition_catalog). Lifecycle: publish (новая версия) → install в проекты → опционально archive (soft). Versioning append-only через version int; latest определяется выбором max(version) среди неархивированных. Архивированная версия скрыта из default UI, но catalog_entry_id остаётся для compliance/audit.
Installed copy в проекте. После install — это обычная WorkflowDefinition, никак не связанная с catalog в runtime (только metadata-метка installed_from_catalog_entry_id для discovery «откуда это пришло»). Catalog archive не инвалидирует копию. Обновление до новой версии — отдельная manual операция (см. §5.5).
Чтение catalog: read.workflow_definition_catalog_list (alembic 038). Rebuildable read projection; не содержит полного definition JSON (только metadata + requirement summary). Полный JSON приходит из app.workflow_definition_catalog только при открытии detail / install.
8. Траблшутинг¶
| Симптом | Причина | Что делать |
|---|---|---|
axon push --catalog падает с Error: --catalog is mutually exclusive with --project and AXON_PROJECT |
Установлена AXON_PROJECT env или передан --project |
Снять env (unset AXON_PROJECT) и убрать --project из команды |
Publish → catalog_portability_invalid с CatalogModeBInlineRejected / CatalogModeBRefRejected / CatalogModeCRejected |
В definition есть credential_id / $credential_ref / connector_key в шагах |
Переписать на Mode A: connector_requirement + добавить slot в WorkflowDefinition.connector_requirements[] |
Publish → catalog_portability_invalid с raw secrets detected |
В definition или metadata лежит токено-подобная строка | Убрать секрет; для шага использовать credential через Mode A binding после install |
Publish → version_conflict |
Тот же (definition_key, version) уже опубликован с другим content_hash |
Не перезаписывать существующую версию: --force-new-version (или вручную bump version в catalog) |
Publish → version_archived |
Пытаешься переиспользовать архивированный version number | Использовать следующий version (CLI делает это автоматически если не fix-нуть вручную) |
Install → 409 definition_key_already_exists_in_project |
В проекте уже есть definition с этим definition_key |
Передать definition_key_override в install (UI предложит <key>_from_catalog) или сначала retire старую definition |
Install → 404 catalog_entry_not_found или catalog_entry_archived |
entry удалён (archived) до install | Найти не-архивированную версию или попросить admin reactivate (для archive в текущей версии нет команды unarchive — нужен новый publish) |
| Auto-mapping коннекторов не предлагает кандидатов | В проекте нет usable CI нужного типа | Создать credential + CI (Connectors-Credentials.md §3 Flow 4) и вернуться в Bindings |
| Catalog UI не показывает «v2 available» для уже установленного определения | Сейчас Console не делает diff-индикатор автоматически | Открыть Catalog → entry detail вручную; будущая фича (см. CONCEPT-CONNECTORS §- catalog UX backlog) |
| Анонимизация при создании шаблона не убрала чувствительное поле | Правило anonymisation не покрывает это поле | Расширить anonymisation rules в template config или вручную почистить перед save |
9. Ограничения и инварианты¶
- Templates: секреты не переносятся. Только references/placeholders. Анонимизация — обязанность создателя шаблона; нет auto-scrubbing-всё-подряд.
- Catalog: Mode A only.
connector_requirementединственный допустимый mode для connector-backed шагов в catalog. Mode B (credential_idinline) и Mode C (connector_key) отвергаются на publish. - Catalog:
project_idMUST be NULL вpublish_to_catalog/archive_catalog_entry. Global target —target_type='workflow_definition_catalog_entry', см. ARCHITECTURE-V6 Appendix A («Mandatory NULL»). Install —target_type='workflow_definition'сproject_id=<target project>. - Catalog: no auto-update. Install — snapshot copy. Новая версия catalog требует нового manual install (с возможной rename).
- Catalog: no cross-instance. Workflow Definition Catalog — instance-wide, не маркетплейс. Cross-instance distribution — отдельный backlog (не в Stage 3).
- Install идёт через
publish_definitionпод капотом — никаких bypass-ов publish-time валидации (sandbox, schema, secrets scan, requirements fingerprint). - Archive — soft.
deleted_atset, копии в проектах живут. Hard delete catalog entry в текущей версии не реализован. - Idempotency. Publish:
(definition_key, version, content_hash)→ re-push с тем же hash возвращаетalready_published: true. Install:(catalog_entry_id, version, target_project_id)→ re-install возвращает существующийdefinition_id. - Module Library (
module_catalog) — это reusable модули, НЕ runtime registry коннекторов. Runtime adapter registry — отдельная инфраструктура (см. ARCHITECTURE-V6 §11ConnectorRegistryhot-reload, alembic 022+).
10. Связанные мануалы и каноны¶
- Workflows.md — definitions / publish / Run Wizard; catalog install — продолжение
publish_definition. - Connectors-Credentials.md —
connector_requirement(Mode A) + auto-mapping после install. - Projects-Lifecycle.md — project templates применяются при создании проекта.
- Roles-And-Permissions.md —
manage_templates/catalog:manage/catalog:install. - Каноны:
ARCHITECTURE-V6.md§15 (Flexible Templates), §11 (auto-mapping), §8 (DDLworkflow_definition_catalog/module_catalog);WORKFLOW-ARCHITECTURE.md§2 (терминология), §8 (Publish Flow);CONCEPT-CONNECTORS.md§- (Catalog контракт).