docs: define secret store and auth profile plan
This commit is contained in:
@@ -44,6 +44,7 @@ Crank - платформа для публикации внешних API в в
|
||||
- `docs/deployment.md` - деплой, reverse proxy и CI/CD.
|
||||
- `docs/demo-runbook.md` - демонстрационный сценарий.
|
||||
- `docs/public-smoke-targets.md` - готовые публичные upstream-сервисы и payload-ы для smoke-проверки MCP.
|
||||
- `docs/secrets-auth-plan.md` - целевая модель upstream secrets, auth profiles и пошаговый план реализации.
|
||||
- `docs/rust-design.md` - правила распределения поведения в Rust.
|
||||
- `docs/development-rules.md` - правила разработки и workflow.
|
||||
- `docs/rust-code-rules.md` - Rust-specific coding rules.
|
||||
|
||||
@@ -2,19 +2,24 @@
|
||||
|
||||
## Current
|
||||
|
||||
### `feat/public-smoke-configs`
|
||||
### `feat/secrets-auth-plan`
|
||||
|
||||
Status: completed
|
||||
|
||||
DoD:
|
||||
- Public REST, GraphQL, and gRPC smoke targets are documented
|
||||
- Repository contains ready-to-use operation payloads for MCP verification
|
||||
- gRPC smoke config includes a runtime-ready descriptor set
|
||||
- Docs describe the target secret store and auth profile model
|
||||
- Backend, runtime, and UI gaps are captured as vertical slices
|
||||
- TASKS and implementation plan reflect the new sequence
|
||||
|
||||
## Next
|
||||
|
||||
- `feat/manual-regression-pass`
|
||||
- `feat/secret-store-foundation`
|
||||
|
||||
## Backlog
|
||||
|
||||
- `feat/secret-store-foundation`
|
||||
- `feat/auth-profile-secret-resolution`
|
||||
- `feat/runtime-upstream-auth`
|
||||
- `feat/secrets-ui`
|
||||
- `feat/wizard-auth-selector`
|
||||
- `feat/manual-regression-pass`
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
- `memberships`
|
||||
- `invitations`
|
||||
- `operations`
|
||||
- `secrets`
|
||||
- `auth-profiles`
|
||||
- `agents`
|
||||
- `platform-api-keys`
|
||||
@@ -116,12 +117,26 @@
|
||||
|
||||
### 5.5. Upstream auth profiles
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/secrets`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/secrets`
|
||||
- `GET /api/admin/workspaces/{workspace_id}/secrets/{secret_id}`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/secrets/{secret_id}/rotate`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/secrets/{secret_id}`
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/auth-profiles`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/auth-profiles`
|
||||
- `GET /api/admin/workspaces/{workspace_id}/auth-profiles/{auth_profile_id}`
|
||||
- `PATCH /api/admin/workspaces/{workspace_id}/auth-profiles/{auth_profile_id}`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/auth-profiles/{auth_profile_id}`
|
||||
|
||||
Контракт:
|
||||
|
||||
- `POST /secrets` принимает metadata и plaintext value, но plaintext возвращается только в create/rotate request path и не выдается повторно;
|
||||
- `GET /secrets` и `GET /secrets/{secret_id}` возвращают только metadata, `kind`, `status`, `current_version`, `created_at`, `updated_at`, `last_used_at` при наличии;
|
||||
- `POST /secrets/{secret_id}/rotate` создает новую secret version;
|
||||
- `DELETE /secrets/{secret_id}` запрещен, если secret используется опубликованными auth profiles или operations;
|
||||
- `AuthProfile.config` хранит ссылки на `secret_id`, а не placeholder-строки `${secrets.*}`.
|
||||
|
||||
### 5.6. Agents
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/agents`
|
||||
@@ -188,6 +203,8 @@
|
||||
- samples;
|
||||
- draft generation;
|
||||
- gRPC descriptor upload и discovery.
|
||||
- upstream auth selector;
|
||||
- quick-create secret / auth profile modal.
|
||||
|
||||
Детальные DTO и response shapes для экранов `Operations` и `Wizard` зафиксированы отдельно в:
|
||||
|
||||
@@ -209,6 +226,15 @@
|
||||
- list/create/revoke/delete platform API keys;
|
||||
- one-time reveal значения ключа при создании.
|
||||
|
||||
### Secrets
|
||||
|
||||
Нужны:
|
||||
|
||||
- list/create/rotate/delete upstream secrets;
|
||||
- metadata-only retrieval после создания;
|
||||
- связь с auth profiles;
|
||||
- usage references, чтобы оператор видел, где секрет используется.
|
||||
|
||||
### Logs
|
||||
|
||||
Нужны:
|
||||
|
||||
+23
-3
@@ -41,6 +41,7 @@ Crank - платформа для публикации внешних API в в
|
||||
Изолирует:
|
||||
|
||||
- операции;
|
||||
- secrets;
|
||||
- auth profiles;
|
||||
- agents;
|
||||
- platform API keys;
|
||||
@@ -84,6 +85,21 @@ Crank - платформа для публикации внешних API в в
|
||||
- `Invitation`
|
||||
- `PlatformApiKey`
|
||||
|
||||
### `Upstream secrets`
|
||||
|
||||
Отдельный слой для доступа к внешним системам:
|
||||
|
||||
- `Secret`
|
||||
- `SecretVersion`
|
||||
- `AuthProfile`
|
||||
|
||||
Принцип:
|
||||
|
||||
- секреты принадлежат workspace;
|
||||
- plaintext не хранится в открытом виде;
|
||||
- `AuthProfile` описывает способ применения секрета к upstream request;
|
||||
- runtime резолвит `auth_profile_ref` в реальный header/query/basic auth только в момент вызова.
|
||||
|
||||
### `Observability`
|
||||
|
||||
Отдельный продуктовый слой:
|
||||
@@ -117,6 +133,7 @@ Crank - платформа для публикации внешних API в в
|
||||
- `Agent` и привязка операций к агенту.
|
||||
- Agent-scoped MCP endpoints.
|
||||
- Platform API keys.
|
||||
- Workspace-scoped encrypted secrets для upstream access.
|
||||
- Workspace-scoped auth profiles для upstream access.
|
||||
- Product logs и usage aggregates.
|
||||
- Импорт и экспорт operation-конфигураций в `YAML`.
|
||||
@@ -137,9 +154,10 @@ Crank - платформа для публикации внешних API в в
|
||||
|
||||
1. Выбирает workspace.
|
||||
2. Создает или редактирует operation.
|
||||
3. Выполняет test run.
|
||||
4. Публикует operation version.
|
||||
5. Привязывает operation к одному или нескольким agents.
|
||||
3. При необходимости выбирает или создает upstream secret / auth profile.
|
||||
4. Выполняет test run.
|
||||
5. Публикует operation version.
|
||||
6. Привязывает operation к одному или нескольким agents.
|
||||
|
||||
### Оператор агентов
|
||||
|
||||
@@ -209,6 +227,8 @@ GraphQL в MCP публикуется как фиксированная опер
|
||||
Базовые сущности:
|
||||
|
||||
- `Workspace`
|
||||
- `Secret`
|
||||
- `SecretVersion`
|
||||
- `Operation`
|
||||
- `OperationVersion`
|
||||
- `Agent`
|
||||
|
||||
+54
-8
@@ -40,6 +40,8 @@
|
||||
|
||||
Минимальный набор workspace-scoped сущностей:
|
||||
|
||||
- `Secret`
|
||||
- `SecretVersion`
|
||||
- `Operation`
|
||||
- `OperationVersion`
|
||||
- `AuthProfile`
|
||||
@@ -143,7 +145,40 @@
|
||||
- `tool_description_override`
|
||||
- `enabled`
|
||||
|
||||
### 3.6. `AuthProfile`
|
||||
### 3.6. `Secret`
|
||||
|
||||
Секрет для доступа к внешней системе.
|
||||
|
||||
Поля:
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `name`
|
||||
- `kind`
|
||||
- `status`
|
||||
- `current_version`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Значение:
|
||||
|
||||
- plaintext не возвращается в list/get endpoints;
|
||||
- текущее значение хранится в зашифрованном виде через `SecretVersion`;
|
||||
- rotate создает новую версию секрета без потери ссылочной целостности.
|
||||
|
||||
### 3.7. `SecretVersion`
|
||||
|
||||
Зашифрованное значение секрета.
|
||||
|
||||
Поля:
|
||||
|
||||
- `secret_id`
|
||||
- `version`
|
||||
- `ciphertext`
|
||||
- `key_version`
|
||||
- `created_at`
|
||||
|
||||
### 3.8. `AuthProfile`
|
||||
|
||||
Используется только для доступа к внешним системам.
|
||||
|
||||
@@ -155,7 +190,13 @@
|
||||
- `kind`
|
||||
- `config`
|
||||
|
||||
### 3.7. `PlatformApiKey`
|
||||
Принцип:
|
||||
|
||||
- `AuthProfile` не хранит plaintext;
|
||||
- config ссылается на `secret_id` или пару `secret_id`, если auth-схема составная;
|
||||
- runtime применяет profile к запросу только в момент вызова upstream.
|
||||
|
||||
### 3.9. `PlatformApiKey`
|
||||
|
||||
Отдельная сущность для доступа к самой платформе.
|
||||
|
||||
@@ -175,7 +216,7 @@
|
||||
- полный secret показывается только один раз при создании;
|
||||
- в persistent storage сохраняется только `secret_hash`.
|
||||
|
||||
### 3.8. `User`
|
||||
### 3.10. `User`
|
||||
|
||||
Поля:
|
||||
|
||||
@@ -192,7 +233,7 @@
|
||||
- plaintext пароль не сохраняется;
|
||||
- верификация использует `password_pepper` из env.
|
||||
|
||||
### 3.9. `UserSession`
|
||||
### 3.11. `UserSession`
|
||||
|
||||
Поля:
|
||||
|
||||
@@ -210,7 +251,7 @@
|
||||
- в persistent storage сохраняется только `secret_hash`;
|
||||
- подпись и верификация используют `session_secret` из env.
|
||||
|
||||
### 3.10. `Membership`
|
||||
### 3.12. `Membership`
|
||||
|
||||
Поля:
|
||||
|
||||
@@ -219,7 +260,7 @@
|
||||
- `role`
|
||||
- `created_at`
|
||||
|
||||
### 3.11. `InvitationToken`
|
||||
### 3.13. `InvitationToken`
|
||||
|
||||
Поля:
|
||||
|
||||
@@ -236,7 +277,7 @@
|
||||
- полный invite token показывается только один раз при создании;
|
||||
- в persistent storage сохраняется только `token_hash`.
|
||||
|
||||
### 3.12. `InvocationLog`
|
||||
### 3.14. `InvocationLog`
|
||||
|
||||
Продуктовая запись о вызове tool.
|
||||
|
||||
@@ -255,7 +296,7 @@
|
||||
- `response_preview`
|
||||
- `created_at`
|
||||
|
||||
### 3.13. `UsageRollup`
|
||||
### 3.15. `UsageRollup`
|
||||
|
||||
Агрегированная статистика по периоду.
|
||||
|
||||
@@ -321,6 +362,11 @@
|
||||
|
||||
Если UI требует сущность, которой нет в текущем backend, эта сущность должна быть сначала явно добавлена в эту модель данных, а уже потом в код и БД.
|
||||
|
||||
Для upstream credentials это означает:
|
||||
|
||||
- placeholder-строки вида `${secrets.API_KEY}` не считаются реальной моделью данных;
|
||||
- рабочая продуктовая модель строится только через `Secret` + `AuthProfile`.
|
||||
|
||||
Для `Operations` и `Wizard` дополнительный уровень контрактной детализации закреплен в:
|
||||
|
||||
- `docs/operations-workspace-contracts.md`
|
||||
|
||||
+38
-6
@@ -26,7 +26,7 @@
|
||||
|
||||
### 2.5. Секреты не хранятся в открытом виде
|
||||
|
||||
- upstream secrets живут за `secret_ref`;
|
||||
- upstream secrets живут в отдельных таблицах и шифруются;
|
||||
- platform API keys хранятся как hash.
|
||||
|
||||
## 3. Основные таблицы
|
||||
@@ -36,6 +36,8 @@
|
||||
- `user_sessions`
|
||||
- `memberships`
|
||||
- `invitation_tokens`
|
||||
- `secrets`
|
||||
- `secret_versions`
|
||||
- `operations`
|
||||
- `operation_versions`
|
||||
- `published_operations`
|
||||
@@ -134,7 +136,30 @@
|
||||
- `created_at`
|
||||
- `finished_at`
|
||||
|
||||
## 6. Upstream auth
|
||||
## 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`
|
||||
|
||||
@@ -146,6 +171,11 @@
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Назначение:
|
||||
|
||||
- `config_json` хранит ссылки на `secret_id`, а не plaintext значения;
|
||||
- допустимы bearer, basic, api-key-header, api-key-query профили.
|
||||
|
||||
Ограничение:
|
||||
|
||||
- `unique (workspace_id, name)`
|
||||
@@ -308,7 +338,9 @@
|
||||
|
||||
1. добавить `workspaces` и заполнить default workspace;
|
||||
2. добавить `workspace_id` в `operations` и `auth_profiles`;
|
||||
3. добавить `agents` и `published_agents`;
|
||||
4. внедрить `platform_api_keys`;
|
||||
5. добавить `invocation_logs` и `usage_rollups`;
|
||||
6. перевести MCP runtime на `published_agents`, а не на глобальный список operations.
|
||||
3. добавить `secrets` и `secret_versions`;
|
||||
4. перевести `auth_profiles` на secret-backed config;
|
||||
5. добавить `agents` и `published_agents`;
|
||||
6. внедрить `platform_api_keys`;
|
||||
7. добавить `invocation_logs` и `usage_rollups`;
|
||||
8. перевести MCP runtime на `published_agents`, а не на глобальный список operations.
|
||||
|
||||
@@ -109,7 +109,21 @@ DoD:
|
||||
- mock JSON больше не используется на критическом пути;
|
||||
- UI, backend и docs синхронизированы.
|
||||
|
||||
## 10. Этап 9. Hardening and demo readiness
|
||||
## 10. Этап 9. Secret store and upstream auth
|
||||
|
||||
Цель:
|
||||
|
||||
- заменить UI placeholder-модель `${secrets.*}` на рабочий backend/runtime слой secrets.
|
||||
|
||||
DoD:
|
||||
|
||||
- есть workspace-scoped `Secrets` resource;
|
||||
- secret values хранятся только в зашифрованном виде;
|
||||
- `AuthProfile` ссылается на `secret_id`, а не на строковый placeholder;
|
||||
- runtime умеет применять bearer/basic/api-key auth к реальному upstream request;
|
||||
- wizard имеет auth selector и quick-create flow для secrets/auth profiles.
|
||||
|
||||
## 11. Этап 10. Hardening and demo readiness
|
||||
|
||||
Цель:
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ crank/
|
||||
Поверх существующих crates должны появиться новые логические поддомены:
|
||||
|
||||
- workspace/access domain;
|
||||
- secret management domain;
|
||||
- agent publishing domain;
|
||||
- observability domain.
|
||||
|
||||
@@ -61,6 +62,7 @@ crank/
|
||||
- `operation`
|
||||
- `agent`
|
||||
- `auth`
|
||||
- `secret`
|
||||
- `observability`
|
||||
- `errors`
|
||||
|
||||
@@ -94,6 +96,7 @@ crank/
|
||||
Назначение:
|
||||
|
||||
- хранение workspace-scoped operations и version snapshots;
|
||||
- хранение workspace-scoped secrets и secret versions;
|
||||
- хранение agents и agent versions;
|
||||
- auth profiles;
|
||||
- platform API keys;
|
||||
@@ -105,6 +108,7 @@ crank/
|
||||
Назначение:
|
||||
|
||||
- исполнение published operation;
|
||||
- резолв `auth_profile_ref -> secret -> request auth`;
|
||||
- запись invocation events;
|
||||
- возврат нормализованного результата.
|
||||
|
||||
@@ -121,6 +125,7 @@ crank/
|
||||
Должен содержать сервисные группы:
|
||||
|
||||
- `workspaces`
|
||||
- `secrets`
|
||||
- `memberships`
|
||||
- `operations`
|
||||
- `auth_profiles`
|
||||
|
||||
+11
-13
@@ -36,22 +36,20 @@ var/crank/
|
||||
|
||||
## 4. Секреты и auth profiles
|
||||
|
||||
Для MVP:
|
||||
Для целевой модели:
|
||||
|
||||
- operation хранит только `auth_profile_ref`;
|
||||
- auth profile хранит только `secret_ref`;
|
||||
- реальные секреты не должны попадать в YAML export;
|
||||
- секреты не должны логироваться.
|
||||
- `AuthProfile` хранит только ссылки на `secret_id`;
|
||||
- plaintext секреты не должны попадать в YAML export;
|
||||
- plaintext секреты не должны логироваться;
|
||||
- runtime получает секрет только на короткое время перед upstream вызовом.
|
||||
|
||||
Допустимые варианты secret storage:
|
||||
Стартовая реализация:
|
||||
|
||||
- env-backed secret store;
|
||||
- encrypted local secret storage.
|
||||
|
||||
Минимальный безопасный вариант для MVP:
|
||||
|
||||
- `secret_ref` указывает на env variable alias или key в локальном secret store;
|
||||
- приложение резолвит его на runtime.
|
||||
- `PostgreSQL`-backed secret store;
|
||||
- `ciphertext` хранится в БД;
|
||||
- шифрование выполняется через `CRANK_MASTER_KEY`;
|
||||
- ключ шифрования приходит только из env.
|
||||
|
||||
## 5. Переменные окружения
|
||||
|
||||
@@ -165,6 +163,6 @@ Demo/deployment:
|
||||
|
||||
- где лежит БД;
|
||||
- где лежат artifacts;
|
||||
- как резолвятся `secret_ref`;
|
||||
- как резолвятся `secret_id` и как ротируется `CRANK_MASTER_KEY`;
|
||||
- на каких bind-address запускаются `admin-api` и `mcp-server`;
|
||||
- какой transport использует MCP server.
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
# Secrets And Upstream Auth Plan
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует полный план доведения upstream secrets и `AuthProfile` до рабочей продуктовой модели.
|
||||
|
||||
Сейчас UI показывает оператору конструкцию вида `${secrets.API_KEY}`, но backend/runtime не резолвит ее в реальный secret. Это создает ложный контракт. Цель этого документа - заменить placeholder UX на рабочую систему.
|
||||
|
||||
## 2. Текущее состояние
|
||||
|
||||
Что уже есть:
|
||||
|
||||
- `AuthProfile` как отдельная workspace-scoped сущность;
|
||||
- `auth_profile_ref` в `ExecutionConfig`;
|
||||
- CRUD endpoints для `auth_profiles`;
|
||||
- UI поля для upstream auth headers;
|
||||
- env `CRANK_SECRET_PROVIDER` и `CRANK_MASTER_KEY` в runtime docs.
|
||||
|
||||
Что еще не работает end-to-end:
|
||||
|
||||
- runtime не резолвит `auth_profile_ref` при выполнении operation;
|
||||
- `secret_ref` не подтягивает фактическое значение секрета;
|
||||
- wizard хранит auth как raw JSON headers;
|
||||
- `${secrets.*}` в UI является только текстовым placeholder;
|
||||
- отдельной страницы `Secrets` нет.
|
||||
|
||||
## 3. Целевая модель
|
||||
|
||||
### 3.1. `Secret`
|
||||
|
||||
Metadata-сущность для upstream credentials.
|
||||
|
||||
Поля:
|
||||
|
||||
- `id`
|
||||
- `workspace_id`
|
||||
- `name`
|
||||
- `kind`
|
||||
- `status`
|
||||
- `current_version`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Типы:
|
||||
|
||||
- `token`
|
||||
- `username_password`
|
||||
- `header`
|
||||
- `generic`
|
||||
|
||||
### 3.2. `SecretVersion`
|
||||
|
||||
Значение секрета, зашифрованное мастер-ключом.
|
||||
|
||||
Поля:
|
||||
|
||||
- `secret_id`
|
||||
- `version`
|
||||
- `ciphertext`
|
||||
- `key_version`
|
||||
- `created_at`
|
||||
|
||||
### 3.3. `AuthProfile`
|
||||
|
||||
`AuthProfile` больше не хранит plaintext или `${secrets.*}`.
|
||||
|
||||
Вместо этого profile описывает:
|
||||
|
||||
- тип auth (`bearer`, `basic`, `api_key_header`, `api_key_query`);
|
||||
- как secret применяется к запросу;
|
||||
- какие `secret_id` для этого нужны.
|
||||
|
||||
Примеры:
|
||||
|
||||
- bearer -> `secret_id`
|
||||
- basic -> `username_secret_id` + `password_secret_id`
|
||||
- api key header -> `header_name` + `secret_id`
|
||||
- api key query -> `param_name` + `secret_id`
|
||||
|
||||
## 4. Хранение и шифрование
|
||||
|
||||
### 4.1. Где хранить
|
||||
|
||||
Стартовый вариант:
|
||||
|
||||
- metadata в `PostgreSQL`
|
||||
- ciphertext в `PostgreSQL`
|
||||
|
||||
Это проще, чем отдельный Vault, и достаточно для текущего продукта.
|
||||
|
||||
### 4.2. Чем шифровать
|
||||
|
||||
- `AES-256-GCM`
|
||||
- мастер-ключ в `CRANK_MASTER_KEY`
|
||||
- поддержка `key_version` для будущей ротации
|
||||
|
||||
### 4.3. Что нельзя делать
|
||||
|
||||
- не хранить plaintext в БД;
|
||||
- не возвращать plaintext в list/get endpoints;
|
||||
- не писать plaintext в logs;
|
||||
- не включать plaintext в YAML export/import.
|
||||
|
||||
## 5. Backend API
|
||||
|
||||
### 5.1. Secrets endpoints
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/secrets`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/secrets`
|
||||
- `GET /api/admin/workspaces/{workspace_id}/secrets/{secret_id}`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/secrets/{secret_id}/rotate`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/secrets/{secret_id}`
|
||||
|
||||
### 5.2. Auth profiles
|
||||
|
||||
Нужно доработать:
|
||||
|
||||
- `POST /auth-profiles`
|
||||
- `PATCH /auth-profiles/{auth_profile_id}`
|
||||
|
||||
Чтобы `config_json` ссылался на `secret_id`, а не на строковые placeholders.
|
||||
|
||||
### 5.3. Validation rules
|
||||
|
||||
- нельзя удалить secret, если на него ссылается auth profile;
|
||||
- нельзя удалить auth profile, если на него ссылается опубликованная operation, без явного подтверждения migration path;
|
||||
- rotate не должен ломать существующие published operations.
|
||||
|
||||
## 6. Runtime changes
|
||||
|
||||
Перед upstream-вызовом runtime должен:
|
||||
|
||||
1. проверить `auth_profile_ref`;
|
||||
2. загрузить `AuthProfile`;
|
||||
3. загрузить и расшифровать нужный secret;
|
||||
4. применить auth к request:
|
||||
- bearer -> `Authorization: Bearer ...`
|
||||
- basic -> `Authorization: Basic ...`
|
||||
- api key header -> произвольный header
|
||||
- api key query -> query param
|
||||
|
||||
Это изменение должно жить в runtime/orchestration слое, а не в UI.
|
||||
|
||||
## 7. UI placement
|
||||
|
||||
### 7.1. Отдельная страница `Secrets`
|
||||
|
||||
Нужна как основное место управления:
|
||||
|
||||
- list
|
||||
- create
|
||||
- rotate
|
||||
- disable/delete
|
||||
- usage references
|
||||
|
||||
Эта страница должна появиться рядом с `API Keys`.
|
||||
|
||||
### 7.2. Quick create в wizard
|
||||
|
||||
На шаге upstream вместо raw `Auth headers` нужен selector:
|
||||
|
||||
- `No auth`
|
||||
- `Bearer token`
|
||||
- `API key header`
|
||||
- `Basic auth`
|
||||
|
||||
Дальше:
|
||||
|
||||
- `Select existing auth profile`
|
||||
- `Create auth profile`
|
||||
- `Create secret`
|
||||
|
||||
Это позволяет не вырывать оператора из flow создания operation.
|
||||
|
||||
### 7.3. Что убрать
|
||||
|
||||
Нужно убрать из UX:
|
||||
|
||||
- `${secrets.API_KEY}` как рекомендованный путь;
|
||||
- raw JSON headers как основной способ настройки auth.
|
||||
|
||||
Raw headers можно оставить только как advanced override, но не как primary flow.
|
||||
|
||||
## 8. Вертикальные срезы реализации
|
||||
|
||||
### Срез 1. Secret store foundation
|
||||
|
||||
DoD:
|
||||
|
||||
- таблицы `secrets` и `secret_versions`;
|
||||
- encryption/decryption service;
|
||||
- CRUD/rotate endpoints;
|
||||
- integration tests на create/get/rotate/delete.
|
||||
|
||||
### Срез 2. Auth profile refactor
|
||||
|
||||
DoD:
|
||||
|
||||
- auth profile config ссылается на `secret_id`;
|
||||
- миграция со старой модели `secret_ref`/placeholder;
|
||||
- validation на dangling references.
|
||||
|
||||
### Срез 3. Runtime auth resolution
|
||||
|
||||
DoD:
|
||||
|
||||
- `auth_profile_ref` применяется при `REST`, `GraphQL` и `gRPC` вызовах;
|
||||
- test-run использует тот же кодовый путь;
|
||||
- runtime tests покрывают bearer/basic/api-key-header/api-key-query.
|
||||
|
||||
### Срез 4. Secrets UI
|
||||
|
||||
DoD:
|
||||
|
||||
- новая страница `Secrets`;
|
||||
- list/create/rotate/delete;
|
||||
- no plaintext leaks after creation.
|
||||
|
||||
### Срез 5. Wizard auth UX
|
||||
|
||||
DoD:
|
||||
|
||||
- step 2 получает auth selector;
|
||||
- quick-create secret/profile flow;
|
||||
- public upstreams можно оставлять без auth;
|
||||
- placeholder `${secrets.*}` исчезает из primary UX.
|
||||
|
||||
## 9. Риски
|
||||
|
||||
- без аккуратной миграции можно сломать уже созданные auth profiles;
|
||||
- если шифрование сделать без `key_version`, потом будет болезненная ротация;
|
||||
- если secrets page сделать без quick-create в wizard, UX снова станет медленным;
|
||||
- если quick-create сделать без отдельной страницы, управляемость secrets будет плохой.
|
||||
|
||||
## 10. Практический итог
|
||||
|
||||
Следующий правильный roadmap:
|
||||
|
||||
1. `feat/secret-store-foundation`
|
||||
2. `feat/auth-profile-secret-resolution`
|
||||
3. `feat/runtime-upstream-auth`
|
||||
4. `feat/secrets-ui`
|
||||
5. `feat/wizard-auth-selector`
|
||||
|
||||
Только после этого upstream auth можно считать реально реализованным.
|
||||
Reference in New Issue
Block a user