Перейти к содержанию

Шаблоны и каталог

Два механизма переиспользования в 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) и через CLI axon 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)

  1. Templates → найти шаблон → Apply.
  2. Выбрать целевой проект, заполнить переменные (форма строится по config_schema), включить anonymisation rules.
  3. Submit → handler материализует WorkflowDefinition с подставленными переменными → publish_definition от имени актора → определение появляется в проекте.
  4. Дальше — обычный путь: настроить Bindings, запустить Run Wizard.

5.2 Создать проект из project template (admin/owner)

  1. Templates → Project template → Apply или Projects → + New from template.
  2. Заполнить переменные (имя проекта, env, и т.д.).
  3. Handler разворачивает: новый project, набор WorkflowDefinitions, declared connector_requirements, default policy. Креденшiалы не переносятся — manager затем привязывает свои.

5.3 Опубликовать определение в Catalog (developer + admin/owner)

  1. Developer пишет WorkflowSpec в modules/workflows/<name>/definition.py. Только Mode A для всех connector-backed шагов (connector_requirement: "<requirement_key>" в step.config, объявление в WorkflowDefinition.connector_requirements[]).
  2. axon push modules/workflows/<name>/ --catalog (без --project; AXON_PROJECT env должна быть пустой — иначе CLI откажется).
  3. CLI вычисляет content_hash, определяет version (latest_version + 1 или 1, если нового key ещё нет), отправляет publish_to_catalog команду с target_type='workflow_definition_catalog_entry', project_id=null, payload содержит definition + metadata.
  4. 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.
  5. Failure modes:
  6. catalog_portability_invalid — нашли Mode B / Mode C / raw secret;
  7. version_conflict — попытка перезаписать существующую неархивированную версию с другим content_hash;
  8. version_archived — попытка переиспользовать архивированный номер версии (нужно увеличить version);
  9. идемпотентный re-push того же (definition_key, version, content_hash) → возвращает already_published: true без дубля.

5.4 Установить из Catalog в проект (manager+)

  1. Catalog → выбрать карточку → Install to project.
  2. Выбрать целевой проект (project:write обязательно), опционально definition_key_override (если предчувствуется collision).
  3. Submit → install_catalog_entry (target_type='workflow_definition', project_id=<target>). Handler:
  4. находит catalog_entry_id, проверяет non-archived;
  5. проверяет idempotent re-install (тот же entry_id + version в том же проекте → возвращает существующий definition_id);
  6. проверяет collision (definition_key_already_exists_in_project → 409 + suggested_definition_key);
  7. копирует definition, обогащает metadata (installed_from_catalog_entry_id / installed_from_catalog_version);
  8. вызывает PublishDefinitionHandler (source='catalog_install') → новое WorkflowDefinition в проекте.
  9. После Install: открыть Bindings, привязать connector_requirements к CI проекта (auto-mapping предложит, если есть usable CI того же типа).

5.5 Обновить установленное определение до новой версии Catalog

  1. В Catalog появилась новая версия — Manager в Console видит «v2 available» (UI бы должен подсветить, см. §8 если не показывает).
  2. Install to project с новой версией. Если в проекте уже есть определение из старой версии (тот же definition_key) → handler вернёт definition_key_already_exists_in_project.
  3. Manager: либо definition_key_override (две версии живут параллельно), либо сначала retire старую (отдельный workflow lifecycle action — не часть catalog).
  4. Никакого автоматического upgrade в текущей версии нет (install — snapshot copy). Это сознательная разница с маркетплейсом: catalog — это диспетчеризация definition, не self-updating subscription.

5.6 Архивировать catalog entry (admin/owner)

  1. Catalog → entry detail → Archive (catalog:manage).
  2. Команда archive_catalog_entry (target_type='workflow_definition_catalog_entry', project_id=null).
  3. Handler: deleted_at = now(), archive_reason сохраняется. Idempotent: повторный archive того же entry → no-op.
  4. Установленные копии не трогаются. Они продолжают работать в своих проектах; 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_id inline) и Mode C (connector_key) отвергаются на publish.
  • Catalog: project_id MUST 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_at set, копии в проектах живут. 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 §11 ConnectorRegistry hot-reload, alembic 022+).

10. Связанные мануалы и каноны

  • Workflows.md — definitions / publish / Run Wizard; catalog install — продолжение publish_definition.
  • Connectors-Credentials.mdconnector_requirement (Mode A) + auto-mapping после install.
  • Projects-Lifecycle.md — project templates применяются при создании проекта.
  • Roles-And-Permissions.mdmanage_templates / catalog:manage / catalog:install.
  • Каноны: ARCHITECTURE-V6.md §15 (Flexible Templates), §11 (auto-mapping), §8 (DDL workflow_definition_catalog / module_catalog); WORKFLOW-ARCHITECTURE.md §2 (терминология), §8 (Publish Flow); CONCEPT-CONNECTORS.md §- (Catalog контракт).