diff --git a/docs/superpowers/specs/2026-04-29-third-party-services-design.md b/docs/superpowers/specs/2026-04-29-third-party-services-design.md new file mode 100644 index 0000000..30c5ba6 --- /dev/null +++ b/docs/superpowers/specs/2026-04-29-third-party-services-design.md @@ -0,0 +1,366 @@ +# 第三方服务结构化设计 + +## 背景 + +当前后台已经将配置相关能力拆分为两层: + +- `场景配置`:定义一个最终要运行的业务场景 +- `基础配置`:承载场景配置引用的公共配置 + +在现有项目中,第三方服务相关配置仍然散落在模板参数中,没有独立的结构和复用关系。当前已确认存在的第三方服务参数包括: + +- 对象存储:`minio_endpoint`、`minio_bucket`、`minio_access_key`、`minio_secret_key` +- 认证服务:`external_get_token_url` +- 告警服务:`external_put_message_url` +- 租户字段:`tenant_code` + +这些配置本质上不是某个单独场景私有的内容,而是会被多个场景反复引用的基础服务配置。继续把它们直接放在模板或场景参数里,会带来几个问题: + +- 相同服务地址和密钥在多个场景中重复填写 +- 修改服务地址或凭据时,需要逐个场景同步修改 +- 难以判断某个第三方服务被哪些场景使用 +- 服务配置与识别模板逻辑混在一起,页面职责不清楚 + +因此,这一轮设计的目标是把“第三方服务”独立为一类可复用的基础配置。 + +## 目标 + +本次设计只解决下面这些问题: + +1. 为第三方服务建立统一、结构化的数据模型 +2. 在 `基础配置` 中提供独立的 `第三方服务` 管理入口 +3. 让 `场景配置` 通过引用第三方服务完成配置,而不是直接填写服务参数 +4. 在生成最终 agent 配置时,将服务引用展开为现有模板参数 + +## 非目标 + +本次不包含以下内容: + +- 不引入多环境字段,如 `prod / test` +- 不引入适用范围字段,如客户 / 项目 / 站点 +- 不做复杂权限模型 +- 不做服务连通性探测 +- 不做密码加密存储方案升级 +- 不支持自定义服务类型 + +第一版只覆盖项目中已经真实存在的三类第三方服务。 + +## 服务类型 + +第一版支持以下三种服务类型: + +1. `object_storage`:对象存储 +2. `token_service`:认证服务 +3. `alarm_service`:告警服务 + +页面文案使用中文: + +- 对象存储 +- 认证服务 +- 告警服务 + +## 数据模型 + +### 顶层公共字段 + +所有第三方服务共享以下字段: + +- `name`:服务名称,唯一标识 +- `type`:服务类型 +- `description`:描述 +- `enabled`:是否启用 +- `config`:按服务类型存储的结构化字段 + +推荐的数据结构如下: + +```json +{ + "name": "minio_prod_main", + "type": "object_storage", + "description": "主对象存储", + "enabled": true, + "config": { + "endpoint": "http://10.0.0.49:9000", + "bucket": "myminio", + "access_key": "admin", + "secret_key": "password" + } +} +``` + +这种设计的关键点是: + +- 顶层字段保持简单,便于列表展示和统一管理 +- 类型差异收纳在 `config` 中,避免一张平表容纳所有服务字段 +- 后续增加新服务类型时,不需要推翻已有结构 + +### 类型字段 + +#### 对象存储 + +字段: + +- `endpoint` +- `bucket` +- `access_key` +- `secret_key` + +#### 认证服务 + +字段: + +- `get_token_url` +- `username` +- `password` +- `tenant_code` + +#### 告警服务 + +字段: + +- `put_message_url` +- `username` +- `password` +- `tenant_code` + +## 与现有模板参数的映射 + +为了兼容当前 agent 模板,第三方服务字段需要在预览和下发阶段映射回模板参数。 + +映射关系如下: + +### 对象存储 + +- `config.endpoint` -> `minio_endpoint` +- `config.bucket` -> `minio_bucket` +- `config.access_key` -> `minio_access_key` +- `config.secret_key` -> `minio_secret_key` + +### 认证服务 + +- `config.get_token_url` -> `external_get_token_url` +- `config.tenant_code` -> `tenant_code` + +### 告警服务 + +- `config.put_message_url` -> `external_put_message_url` +- `config.tenant_code` -> `tenant_code` + +说明: + +- `username` 和 `password` 在第一版中先作为结构化存储字段保留 +- 是否映射到模板参数,取决于具体模板是否已经定义对应参数 +- 如果当前模板没有用到用户名和密码,这两个字段暂时只在后台维护,不强制写入模板参数 + +## 场景配置中的引用方式 + +场景配置不再直接保存第三方服务的 URL、密钥和租户字段,而是保存服务引用。 + +建议增加以下引用字段: + +- `object_storage_ref` +- `token_service_ref` +- `alarm_service_ref` + +示例: + +```json +{ + "object_storage_ref": "minio_prod_main", + "token_service_ref": "token_service_prod", + "alarm_service_ref": "alarm_center_prod" +} +``` + +这样做的好处是: + +- 多个场景可以复用同一组基础服务 +- 修改服务地址或凭据时,无需逐个调整场景 +- 后台可以反查“某个服务被哪些场景引用” +- 场景配置页面更聚焦于业务场景本身,而不是堆满连接参数 + +## 预览与下发的数据流 + +生成最终 agent 配置时,数据流按以下顺序处理: + +1. 读取场景配置 +2. 解析场景中引用的第三方服务名称 +3. 加载对应第三方服务配置 +4. 按服务类型展开为模板参数 +5. 合并模板默认参数、场景参数、调试参数和第三方服务参数 +6. 生成最终配置预览或下发内容 + +参数优先级建议保持清晰: + +1. 模板默认参数 +2. 场景配置显式参数 +3. 第三方服务展开参数 +4. 调试参数覆盖 + +如果同名字段冲突,后面的层级覆盖前面的层级。 + +## 存储设计 + +后台当前 `assets_repo` 已经持久化模板、场景配置和调试参数。第一版建议延续这个模式,为第三方服务新增独立存储。 + +建议新增一类持久化对象: + +- 表名可使用 `integration_services` + +每条记录至少包含: + +- `name` +- `type` +- `description` +- `enabled` +- `config_json` +- `created_at` +- `updated_at` + +其中 `config_json` 保存类型字段。 + +这样可以避免在数据库层为三类服务各建一张表,保持实现简单,同时保留后续扩展空间。 + +## 后端结构建议 + +建议在服务层新增一个明确模型,例如: + +```go +type ThirdPartyServiceAsset struct { + Name string + Type string + Description string + Enabled bool + Config map[string]any +} +``` + +如果后续需要更强约束,可以进一步拆出按类型的辅助结构,但第一版不必过度设计。 + +建议新增以下能力: + +- 列表读取 +- 单项读取 +- 新建 / 编辑 / 删除 +- 引用计数查询 +- 按场景展开为模板参数 + +## UI 设计 + +### 入口位置 + +主入口保持在: + +- `基础配置 -> 第三方服务` + +### 列表页 + +列表页先展示最重要的信息,字段建议如下: + +- 服务名称 +- 服务类型 +- 描述 +- 地址摘要 +- 启用状态 +- 引用数量 + +地址摘要按类型生成: + +- 对象存储:显示 `endpoint / bucket` +- 认证服务:显示 `get_token_url` +- 告警服务:显示 `put_message_url` + +这样用户可以快速判断服务是做什么的,以及是否大致配置正确。 + +### 详情 / 编辑页 + +详情和编辑页分为两块: + +1. 基本信息 + - 名称 + - 类型 + - 描述 + - 启用状态 + +2. 服务配置 + - 根据服务类型显示不同字段 + +字段展示规则: + +- 密码和 `secret_key` 默认掩码显示 +- 列表页不展示敏感字段 +- 类型切换时动态切换表单字段 + +## 校验规则 + +### 通用校验 + +- 名称不能为空 +- 名称必须唯一 +- 类型不能为空 + +### 对象存储校验 + +- `endpoint` 必填 +- `bucket` 必填 +- `access_key` 必填 +- `secret_key` 必填 + +### 认证服务校验 + +- `get_token_url` 必填 +- `tenant_code` 可选 +- `username`、`password` 可选 + +### 告警服务校验 + +- `put_message_url` 必填 +- `tenant_code` 可选 +- `username`、`password` 可选 + +## 删除与引用约束 + +第三方服务被场景配置引用时,不应允许直接删除。 + +删除前需要检查: + +- 是否有场景配置正在引用该服务 + +如果存在引用,应提示: + +- 当前服务已被某些场景配置使用,不能删除 + +这与模板删除前检查引用的现有交互保持一致。 + +## 第一阶段实施范围 + +第一阶段只实现以下能力: + +1. 第三方服务的数据结构和存储 +2. `基础配置 -> 第三方服务` 列表与详情编辑 +3. 场景配置对第三方服务的引用 +4. 配置预览与下发时的参数展开 +5. 删除前引用检查 + +## 后续扩展方向 + +本设计为后续扩展保留空间,但不在第一阶段实现: + +- 新增更多服务类型,如 MQTT、Kafka、Webhook +- 服务连通性测试按钮 +- 敏感字段加密存储 +- 按客户或项目进行服务分组 +- 服务变更审计 + +## 结论 + +第三方服务应当被视为一类可复用的基础配置,而不是模板参数的零散集合。 + +通过引入独立的第三方服务结构: + +- 可以降低场景配置的重复录入 +- 可以集中管理 URL、租户和凭据 +- 可以让模板、场景和服务的职责分离 +- 可以为后续更完整的配置治理打下基础 + +第一版只支持对象存储、认证服务、告警服务三类,已经足够覆盖当前项目里的真实需求,并且能与现有 agent 模板参数平滑兼容。