478 lines
9.2 KiB
Markdown
478 lines
9.2 KiB
Markdown
# Схема БД
|
||
|
||
## 1. Назначение документа
|
||
|
||
Этот документ фиксирует целевую структуру хранения workspace-scoped конфигураций, агентов, ключей доступа и observability-данных. Базовая СУБД - `PostgreSQL`.
|
||
|
||
## 2. Общие принципы хранения
|
||
|
||
### 2.1. Версионирование обязательно
|
||
|
||
Конфигурация operation и agent не хранится только в одной "живой" записи. Каждое существенное изменение создает новую версию.
|
||
|
||
### 2.2. Published и draft разделяются логически
|
||
|
||
- `draft` может меняться;
|
||
- `published` всегда указывает на конкретную version;
|
||
- runtime читает только опубликованные представления.
|
||
|
||
### 2.3. Workspace scoping обязателен
|
||
|
||
Все продуктовые таблицы должны ссылаться на `workspaces`.
|
||
|
||
### 2.4. Артефакты и конфигурация не смешиваются
|
||
|
||
`.proto`, descriptor set, sample JSON и YAML payload не хранятся в тех же строках, что runtime-ready configuration.
|
||
|
||
### 2.5. Секреты не хранятся в открытом виде
|
||
|
||
- upstream secrets живут в отдельных таблицах и шифруются;
|
||
- agent keys и credentials доверенных клиентов хранятся как hash;
|
||
- короткоживущие токены хранятся в форме, пригодной для отзыва и учета использования.
|
||
|
||
## 3. Основные таблицы
|
||
|
||
- `workspaces`
|
||
- `users`
|
||
- `user_sessions`
|
||
- `memberships`
|
||
- `invitation_tokens`
|
||
- `secrets`
|
||
- `secret_versions`
|
||
- `operations`
|
||
- `operation_versions`
|
||
- `published_operations`
|
||
- `operation_samples`
|
||
- `descriptors`
|
||
- `auth_profiles`
|
||
- `agents`
|
||
- `agent_versions`
|
||
- `agent_operation_bindings`
|
||
- `published_agents`
|
||
- `agent_keys`
|
||
- `issued_agent_tokens`
|
||
- `platform_client_credentials`
|
||
- `stream_sessions`
|
||
- `async_jobs`
|
||
- `invocation_logs`
|
||
- `usage_rollups`
|
||
- `yaml_import_jobs`
|
||
|
||
## 4. Operations
|
||
|
||
### `operations`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `name`
|
||
- `display_name`
|
||
- `protocol`
|
||
- `status`
|
||
- `security_level`
|
||
- `current_draft_version`
|
||
- `latest_published_version`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `published_at`
|
||
|
||
Ограничение:
|
||
|
||
- `unique (workspace_id, name)`
|
||
|
||
### `operation_versions`
|
||
|
||
- `operation_id`
|
||
- `version`
|
||
- `status`
|
||
- `target_json`
|
||
- `input_schema_json`
|
||
- `output_schema_json`
|
||
- `input_mapping_json`
|
||
- `output_mapping_json`
|
||
- `execution_config_json`
|
||
- `tool_description_json`
|
||
- `samples_json`
|
||
- `generated_draft_json`
|
||
- `config_export_json`
|
||
- `change_note`
|
||
- `created_at`
|
||
- `created_by`
|
||
|
||
### `published_operations`
|
||
|
||
- `operation_id`
|
||
- `version`
|
||
- `published_at`
|
||
- `published_by`
|
||
|
||
## 5. Operation artifacts
|
||
|
||
### `operation_samples`
|
||
|
||
- `id`
|
||
- `operation_id`
|
||
- `version`
|
||
- `sample_kind`
|
||
- `storage_ref`
|
||
- `content_type`
|
||
- `file_name`
|
||
- `created_at`
|
||
|
||
### `descriptors`
|
||
|
||
- `id`
|
||
- `operation_id`
|
||
- `version`
|
||
- `descriptor_kind`
|
||
- `storage_ref`
|
||
- `source_name`
|
||
- `package_index_json`
|
||
- `created_at`
|
||
|
||
`descriptor_kind` дополнительно поддерживает:
|
||
|
||
- `wsdl_upload`
|
||
- `xsd_upload`
|
||
|
||
`package_index_json` для `wsdl_upload` хранит нормализованный inspection result:
|
||
|
||
- `service_name`
|
||
- `port_name`
|
||
- `binding_name`
|
||
- `endpoint`
|
||
- `soap_version`
|
||
- `operations[]`
|
||
|
||
### `yaml_import_jobs`
|
||
|
||
- `id`
|
||
- `source_sample_id`
|
||
- `status`
|
||
- `format_version`
|
||
- `mode`
|
||
- `result_operation_id`
|
||
- `result_version`
|
||
- `error_text`
|
||
- `created_at`
|
||
- `finished_at`
|
||
|
||
## 6. Upstream secrets and auth
|
||
|
||
### `secrets`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `name`
|
||
- `kind`
|
||
- `status`
|
||
- `current_version`
|
||
- `created_at`
|
||
- `updated_at`
|
||
|
||
Ограничение:
|
||
|
||
- `unique (workspace_id, name)`
|
||
|
||
### `secret_versions`
|
||
|
||
- `secret_id`
|
||
- `version`
|
||
- `ciphertext`
|
||
- `key_version`
|
||
- `created_at`
|
||
|
||
### `auth_profiles`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `name`
|
||
- `kind`
|
||
- `config_json`
|
||
- `created_at`
|
||
- `updated_at`
|
||
|
||
Назначение:
|
||
|
||
- `config_json` хранит ссылки на `secret_id`, а не plaintext значения;
|
||
- допустимы bearer, basic, api-key-header, api-key-query профили.
|
||
|
||
Ограничение:
|
||
|
||
- `unique (workspace_id, name)`
|
||
|
||
### `agent_keys`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `name`
|
||
- `prefix`
|
||
- `secret_hash`
|
||
- `scopes_json`
|
||
- `status`
|
||
- `expires_at`
|
||
- `created_at`
|
||
- `last_used_at`
|
||
|
||
Ограничения:
|
||
|
||
- `unique (agent_id, name)`
|
||
- `prefix` уникален глобально
|
||
|
||
Назначение:
|
||
|
||
- длинноживущий ключ принадлежит одному агенту;
|
||
- ключ используется как исходное основание для выпуска короткоживущего токена;
|
||
- прямой вызов MCP по такому ключу допускается только в переходном режиме.
|
||
|
||
### `issued_agent_tokens`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `agent_key_id`
|
||
- `token_kind`
|
||
- `status`
|
||
- `scopes_json`
|
||
- `max_uses`
|
||
- `used_count`
|
||
- `cnf_jkt`
|
||
- `expires_at`
|
||
- `created_at`
|
||
- `used_at`
|
||
|
||
Индексы:
|
||
|
||
- `(agent_id, status, expires_at)`
|
||
- `(workspace_id, status, expires_at)`
|
||
- `(cnf_jkt)` при включенной привязке токена к ключевой паре клиента
|
||
|
||
Назначение:
|
||
|
||
- учет выданных короткоживущих токенов;
|
||
- поддержка одноразовых токенов;
|
||
- поддержка отзыва и проверки повторного использования.
|
||
|
||
### `stream_sessions`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `operation_id`
|
||
- `mode`
|
||
- `status`
|
||
- `cursor_json`
|
||
- `state_json`
|
||
- `expires_at`
|
||
- `last_poll_at`
|
||
- `created_at`
|
||
- `closed_at`
|
||
|
||
Индексы:
|
||
|
||
- `(workspace_id, status, expires_at)`
|
||
- `(operation_id, status)`
|
||
|
||
### `async_jobs`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `operation_id`
|
||
- `status`
|
||
- `progress_json`
|
||
- `result_json`
|
||
- `error_json`
|
||
- `expires_at`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `finished_at`
|
||
|
||
Индексы:
|
||
|
||
- `(workspace_id, status, expires_at)`
|
||
- `(operation_id, status)`
|
||
|
||
## 7. Workspaces and access layer
|
||
|
||
### `workspaces`
|
||
|
||
- `id`
|
||
- `slug`
|
||
- `display_name`
|
||
- `status`
|
||
- `settings_json`
|
||
- `created_at`
|
||
- `updated_at`
|
||
|
||
### `users`
|
||
|
||
- `id`
|
||
- `email`
|
||
- `display_name`
|
||
- `password_hash`
|
||
- `status`
|
||
- `created_at`
|
||
|
||
### `user_sessions`
|
||
|
||
- `id`
|
||
- `user_id`
|
||
- `secret_hash`
|
||
- `status`
|
||
- `expires_at`
|
||
- `last_seen_at`
|
||
- `created_at`
|
||
|
||
Ограничения:
|
||
|
||
- `unique (user_id, id)`
|
||
|
||
### `memberships`
|
||
|
||
- `workspace_id`
|
||
- `user_id`
|
||
- `role`
|
||
- `created_at`
|
||
|
||
### `invitation_tokens`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `email`
|
||
- `role`
|
||
- `status`
|
||
- `token_hash`
|
||
- `expires_at`
|
||
- `created_at`
|
||
|
||
## 8. Agents
|
||
|
||
### `agents`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `slug`
|
||
- `display_name`
|
||
- `description`
|
||
- `status`
|
||
- `current_draft_version`
|
||
- `latest_published_version`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `published_at`
|
||
|
||
Ограничение:
|
||
|
||
- `unique (workspace_id, slug)`
|
||
|
||
### `agent_versions`
|
||
|
||
- `agent_id`
|
||
- `version`
|
||
- `status`
|
||
- `instructions_json`
|
||
- `tool_selection_policy_json`
|
||
- `created_at`
|
||
|
||
### `agent_operation_bindings`
|
||
|
||
- `agent_id`
|
||
- `agent_version`
|
||
- `operation_id`
|
||
- `operation_version`
|
||
- `tool_name`
|
||
- `tool_title`
|
||
- `tool_description_override`
|
||
- `enabled`
|
||
|
||
### `published_agents`
|
||
|
||
- `agent_id`
|
||
- `version`
|
||
- `published_at`
|
||
- `published_by`
|
||
|
||
## 9. Machine access and observability
|
||
|
||
### `agent_keys`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `name`
|
||
- `prefix`
|
||
- `secret_hash`
|
||
- `scopes_json`
|
||
- `status`
|
||
- `expires_at`
|
||
- `created_at`
|
||
- `last_used_at`
|
||
|
||
### `issued_agent_tokens`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `agent_key_id`
|
||
- `token_kind`
|
||
- `status`
|
||
- `scopes_json`
|
||
- `max_uses`
|
||
- `used_count`
|
||
- `cnf_jkt`
|
||
- `expires_at`
|
||
- `created_at`
|
||
- `used_at`
|
||
|
||
### `invocation_logs`
|
||
|
||
- `id`
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `operation_id`
|
||
- `source`
|
||
- `request_id`
|
||
- `level`
|
||
- `status`
|
||
- `tool_name`
|
||
- `message`
|
||
- `status_code`
|
||
- `duration_ms`
|
||
- `error_kind`
|
||
- `request_preview_json`
|
||
- `response_preview_json`
|
||
- `created_at`
|
||
|
||
### `usage_rollups`
|
||
|
||
- `workspace_id`
|
||
- `agent_id`
|
||
- `operation_id`
|
||
- `period_kind`
|
||
- `period_start`
|
||
- `calls_total`
|
||
- `calls_ok`
|
||
- `calls_error`
|
||
- `p50_ms`
|
||
- `p95_ms`
|
||
- `p99_ms`
|
||
|
||
Замечание:
|
||
|
||
- в MVP usage read-model может вычисляться напрямую из `invocation_logs`;
|
||
- `usage_rollups` сохраняется как совместимая таблица под materialized aggregates и дальнейшую оптимизацию.
|
||
|
||
## 10. Migration strategy
|
||
|
||
Переход от текущей схемы к целевой идет так:
|
||
|
||
1. добавить `workspaces` и заполнить default workspace;
|
||
2. добавить `workspace_id` в `operations` и `auth_profiles`;
|
||
3. добавить `secrets` и `secret_versions`;
|
||
4. перевести `auth_profiles` на secret-backed config;
|
||
5. добавить `agents` и `published_agents`;
|
||
6. внедрить `agent_keys`, `platform_client_credentials` и `issued_agent_tokens`;
|
||
7. добавить `invocation_logs` и `usage_rollups`;
|
||
8. перевести MCP runtime на `published_agents`, а не на глобальный список operations.
|