13 KiB
Схема БД
1. Назначение документа
Этот документ фиксирует структуру хранения конфигураций, версий операций, загруженных артефактов и published runtime-view. Его цель - дать основу для SQL-миграций и для реализации mcpaas-registry.
В документе предполагается реляционная модель, ориентированная на PostgreSQL. Для MVP допускается адаптация под SQLite, но канонической считается схема, совместимая с PostgreSQL.
2. Общие принципы хранения
2.1. Версионирование обязательно
Конфигурация operation не должна храниться только в одной "живой" записи. Каждое существенное изменение должно приводить к появлению новой версии конфигурации.
Для MVP в registry version snapshot хранит protocol-specific конфигурацию, схемы, mapping и execution settings. Поля identity и listing view (name, display_name, protocol) считаются стабильными и хранятся в operations.
2.2. Published и draft разделяются логически
draftможет меняться;publishedдолжна ссылаться на конкретную зафиксированную версию;- runtime читает только опубликованные версии.
2.3. Артефакты и конфигурация не смешиваются
.proto, descriptor set, sample JSON и YAML import payload не должны храниться в той же структуре, что и runtime-ready configuration.
2.4. Секреты не хранятся внутри operation
В БД operation должны храниться только ссылки на auth profiles или secret references.
Для MVP рекомендуется отдельная таблица auth_profiles, где metadata и secret refs отделены от operation versions.
2.5. SQLite-адаптация допустима
Канонической схемой остается PostgreSQL-совместимая модель, но MVP-реализация registry может использовать SQLite. В таком случае:
jsonbхранится какtextс JSON-сериализацией;timestamptzхранится какtext;- внешние ключи и version snapshot semantics сохраняются без изменения.
3. Основные таблицы
Минимальный набор таблиц:
operationsoperation_versionspublished_operationsoperation_samplesdescriptorsauth_profilesyaml_import_jobs
Опционально позже:
operation_test_runsaudit_log
4. Таблица operations
Хранит стабильную сущность операции, не зависящую от конкретной версии.
Поля
idtext primary keynametext not null uniquedisplay_nametext not nullprotocoltext not nullstatustext not nullcurrent_draft_versioninteger not null default 1latest_published_versioninteger nullcreated_attimestamptz not nullupdated_attimestamptz not nullpublished_attimestamptz null
Назначение
- быстрый список операций;
- стабильный идентификатор для UI и MCP;
- привязка к актуальному draft и опубликованной версии.
5. Таблица operation_versions
Хранит полную сериализованную конфигурацию конкретной версии operation.
Поля
operation_idtext not nullversioninteger not nullstatustext not nulltarget_jsonjsonb not nullinput_schema_jsonjsonb not nulloutput_schema_jsonjsonb not nullinput_mapping_jsonjsonb not nulloutput_mapping_jsonjsonb not nullexecution_config_jsonjsonb not nulltool_description_jsonjsonb not nullsamples_jsonjsonb nullgenerated_draft_jsonjsonb nullconfig_export_jsonjsonb nullchange_notetext nullcreated_attimestamptz not nullcreated_bytext null
Ключи
- primary key:
(operation_id, version) - foreign key:
operation_id -> operations(id) - рекомендованный composite foreign key для связанных таблиц:
(operation_id, version)
Почему так
Для MVP выгоднее хранить version snapshot целиком, а не дробить по десятку связанных таблиц. Это:
- упрощает versioning;
- упрощает откат;
- упрощает YAML export;
- хорошо сочетается с JSON-oriented доменной моделью.
6. Таблица published_operations
Хранит явную published-привязку, которую читает runtime.
Поля
operation_idtext primary keyversioninteger not nullpublished_attimestamptz not nullpublished_bytext null
Назначение
- быстрый доступ к published runtime-view;
- отсутствие двусмысленности, какая именно версия сейчас активна;
- простой invalidation для runtime cache.
Рекомендуемая целостность
operation_id -> operations(id)(operation_id, version) -> operation_versions(operation_id, version)
7. Таблица operation_samples
Хранит метаданные и ссылки на sample artifacts.
Поля
idtext primary keyoperation_idtext not nullversioninteger not nullsample_kindtext not nullstorage_reftext not nullcontent_typetext not nullfile_nametext nullcreated_attimestamptz not null
Варианты sample_kind
input_jsonoutput_jsonyaml_import_source
Назначение
- не класть большие sample payload в основные version records;
- иметь возможность переиспользовать или пересобирать draft mapping;
- отслеживать, из каких sample-данных строился черновик.
Рекомендуемая целостность
operation_id -> operations(id)(operation_id, version) -> operation_versions(operation_id, version)
8. Таблица descriptors
Хранит gRPC schema artifacts.
Поля
idtext primary keyoperation_idtext nullversioninteger nulldescriptor_kindtext not nullstorage_reftext not nullsource_nametext nullpackage_index_jsonjsonb nullcreated_attimestamptz not null
Варианты descriptor_kind
proto_uploaddescriptor_setreflection_snapshot
Назначение
- связывать gRPC operation с конкретной схемой;
- не хранить binary descriptor внутри основной operation version;
- иметь отдельную точку для discovery metadata.
Рекомендуемая целостность
- если descriptor привязан к version, то
(operation_id, version) -> operation_versions(operation_id, version)
9. Таблица yaml_import_jobs
Для MVP можно импортировать YAML синхронно, но таблицу под журнал импорта лучше предусмотреть сразу.
Поля
idtext primary keysource_sample_idtext nullstatustext not nullformat_versiontext not nullmodetext not nullresult_operation_idtext nullresult_versioninteger nullerror_texttext nullcreated_attimestamptz not nullfinished_attimestamptz null
Назначение
- аудит импортов;
- разбор ошибок валидации;
- поддержка будущего async import pipeline.
10. Таблица auth_profiles
Хранит переиспользуемые профили аутентификации для внешних вызовов.
Поля
idtext primary keynametext not null uniquekindtext not nullconfig_jsonjsonb not nullcreated_attimestamptz not nullupdated_attimestamptz not null
Варианты kind
bearerbasicapi_key_headerapi_key_query
Правило
config_json должен содержать только secret_ref, а не открытые секреты.
11. Предлагаемая SQL-форма
create table operations (
id text primary key,
name text not null unique,
display_name text not null,
protocol text not null,
status text not null,
current_draft_version integer not null default 1,
latest_published_version integer null,
created_at timestamptz not null,
updated_at timestamptz not null,
published_at timestamptz null
);
create table operation_versions (
operation_id text not null references operations(id),
version integer not null,
status text not null,
target_json jsonb not null,
input_schema_json jsonb not null,
output_schema_json jsonb not null,
input_mapping_json jsonb not null,
output_mapping_json jsonb not null,
execution_config_json jsonb not null,
tool_description_json jsonb not null,
samples_json jsonb null,
generated_draft_json jsonb null,
config_export_json jsonb null,
change_note text null,
created_at timestamptz not null,
created_by text null,
primary key (operation_id, version)
);
create table published_operations (
operation_id text primary key references operations(id),
version integer not null,
published_at timestamptz not null,
published_by text null,
foreign key (operation_id, version)
references operation_versions(operation_id, version)
);
create table auth_profiles (
id text primary key,
name text not null unique,
kind text not null,
config_json jsonb not null,
created_at timestamptz not null,
updated_at timestamptz not null
);
12. Индексы
Минимально нужны:
- index on
operations(protocol) - index on
operations(status) - index on
operation_versions(operation_id, created_at desc) - index on
published_operations(version) - index on
operation_samples(operation_id, version) - index on
descriptors(operation_id, version) - index on
auth_profiles(kind)
13. Versioning flow
Создание операции
- Создается запись в
operations. - Создается версия
1вoperation_versions. current_draft_version = 1.
Изменение draft
- Читается текущий draft.
- Создается новая версия
n + 1. - В
operations.current_draft_versionпишется новая версия. - Published версия не меняется.
Публикация
- Берется текущий draft version.
- В
published_operationsupsert-ится ссылка на эту версию. - В
operations.latest_published_versionпишется та же версия. - Runtime cache получает сигнал на reload.
Импорт YAML
- YAML валидируется.
- Определяется create или update сценарий.
- Создается новая запись в
operation_versions. - При необходимости создается запись в
yaml_import_jobs.
14. Что не должно храниться в БД в таком виде
- секреты в открытом виде;
- runtime cache;
- скомпилированные adapter clients;
- невалидированные черновики, не приводимые к доменной модели.
15. Практический итог
Для MVP рекомендован такой подход:
operations- стабильная идентичность;operation_versions- полные version snapshots;published_operations- текущая активная версия;operation_samplesиdescriptors- внешние артефакты;auth_profiles- переиспользуемая внешняя аутентификация;yaml_import_jobs- журнал импортов.
Эта схема хорошо ложится на sqlx, не требует избыточной нормализации и соответствует JSON-oriented модели домена.