ConfigManager 技术设计
# ConfigManager 技术设计
修订记录
| 版本 | 日期 | 修订说明 |
|---|---|---|
| v0.1 | 2026-05-01 | 建立当前设计基线;延续 kunora-wiki 作为 llm-wiki 方案的既有产品封板和工程设计,不推倒重来。 |
1. 摘要
ConfigManager 是 kunora-wiki 自研系统的配置入口和配置契约 owner。它负责读取、校验、归一化和发布配置对象,向其他自研模块提供稳定的 ConfigBundle,并在配置变更时输出 ConfigImpactReport 供 review 和维护者判断影响范围。
ConfigManager 不直接执行同步、发布、索引、问答或 agent 写入。它只保证这些模块拿到的配置已经经过 schema 校验、路径校验、交叉引用校验和安全策略校验。
2. 模块目标
- 统一管理
SourceConfig、PublishConfig、IndexConfig、RagflowConfig、AgentAccessConfig、ModelPolicy。 - 生成运行时
ConfigBundle,并提供稳定configHash。 - 在配置进入下游模块前拒绝非法路径、重复目标、缺失必填字段和不安全授权。
- 为配置变更生成
ConfigImpactReport,用于 PR 摘要、check report 和人工 review。 - 为所有配置错误输出标准
ErrorObject,避免 下游模块重复定义配置错误。
3. 非目标
- 不管理 GitHub、Docusaurus、RAGFlow、Meilisearch 的产品级部署配置。
- 不持有密钥明文;密钥解析属于运行环境或 secret provider,ConfigManager 只验证引用结构。
- 不决定内容是否同步、发布或索引;它只输出配置和影响判断。
- 不绕过 Git review 直接修改
config/**。 - 不把外部产品私有配置结构直接暴露给自研模块。
4. 上下文边界
ConfigManager 位于 L0 Common Foundation 层。除 common 规则外,它不依赖其他自研业务模块。
5. 输入与输出
5.1 输入
| 输入 | 来源 | 说明 |
|---|---|---|
config/sources.yaml | Git 中人工维护配置 | 文档来源、目标 publish path、同步策略。 |
config/publish.yaml | Git 中人工维护配置 | 展示后端、baseUrl、managedPath。 |
config/index.yaml | Git 中人工维护配置 | RAGFlow/Meilisearch 索引目标和可索引范围。 |
config/ragflow.yaml | Git 中人工维护配置 | RAGFlow dataset、endpoint 引用、能力开关。 |
config/agent-access.yaml | Git 中人工维护配置 | agent policy、scope、tool 权限。 |
config/model-policy.yaml | Git 中人工维护配置 | 模型使用策略和 fallback 规则。 |
| runtime env / secret refs | 运行时注入 | endpoint、token、私密连接信息的引用和值解析状态。 |
| previous config bundle | 可选 | 生成配置影响报告时用于 diff。 |
5.2 输出
| 输出 | 消费者 | 说明 |
|---|---|---|
ConfigBundle | 所有自研模块 | 已校验、已归一化的运行时配置对象。 |
ConfigImpactReport | ReviewBridge、维护者 | 配置变更影响范围、风险等级和需要人工确认的项目。 |
ErrorObject[] | 调用方、ReviewBridge、CI | 标准配置错误和警告。 |
configHash | 下游模块、审计记录 | canonical bundle hash,用于追踪本次运行使用的配置版本。 |
6. 依赖的 common 契约
| 契约 | 用途 |
|---|---|
SourceConfig | 读取并校验来源配置。 |
PublishConfig | 读取并校验展示发布配置。 |
IndexConfig | 读取并校验索引目标。 |
RagflowConfig | 读取并校验 RAGFlow adapter 所需配置引用。 |
AgentAccessConfig | 读取并校验 agent policy。 |
ModelPolicy | 读取并校验模型策略。 |
ConfigBundle | 对下游模块发布统一配置。 |
ConfigImpactReport | 输出配置变更影响。 |
NormalizedPath | 校验所有路径字段。 |
ContentHash | 生成 configHash。 |
ErrorObject | 表达配置错误、警告和阻断原因。 |
7. 核心流程
7.1 加载与校验流程
校验顺序固定为:
- 文件存在性和 YAML 解析。
- schema 版本和字段类型。
- 单文件内部校验。
- 路径归一化和路径安全校验。
- 多配置交叉校验。
- secret 引用存在性校验。
- canonical bundle 生成和
configHash计算。
任何阻断性错误出现后,不向下游模块发布 ConfigBundle。
7.2 配置影响分析流程
影响等级:
| 等级 | 含义 | 示例 |
|---|---|---|
none | 不影响运行行为 | 注释、顺序变化、等价默认值。 |
low | 只影响非关键展示或可回滚配置 | 增加 disabled source。 |
medium | 影响同步、发布或索引范围 | 新增 source、调整 include/exclude。 |
high | 可能造成删除、权限扩大或索引大规模重建 | 删除 source、扩大 agent allowedPaths。 |
blocking | 配置非法或安全风险不可接受 | publishPath 冲突、secret 缺失、越权 policy。 |
8. 校验规则
8.1 SourceConfig
sources[].id必须唯一。sources[].publishPath必须唯一。- 不同
publishPath不能互为父子目录。 publishPath必须位于publish/**。sourcePath不能指向仓库根目录,除非显式配置allowRepositoryRoot=true。- disabled source 仍需通过 schema 校验,但可跳过连接性校验。
deletePolicy默认report-only,MVP 不允许默认物理删除正式内容。
8.2 PublishConfig
backendMVP 只允许docusaurus。managedPath必须等于或位于publish/**管理范围,不得指向state/**、config/**。baseUrl必须可规范化为站点相对 URL 或绝对 URL。buildOutputPath不能位于publish/**,避免构建产物污染正式内容。
8.3 IndexConfig 与 RagflowConfig
targets[].id必须唯一。- enabled target 必须具备对应 adapter 所需的最小字段。
- RAGFlow target 必须能解析 dataset 引用,但不得把 token 明文写入 bundle。
- Meilisearch target 必须声明
indexName。 includeQualityStatus为空时使用默认可索引状态,不允许隐式包含 rejected/draft 内容。
8.4 AgentAccessConfig 与 ModelPolicy
agents[].agentId必须唯一。allowedPaths必须是受控相对路径,不能越界到config/**或未授权state/**。allowedTools必须属于 Agent Access API 已声明工具集合。writePermissions只能授予创建反馈、创建改进任务、创建候选 PR 等受控写能力。includeWorkingDocs=true必须显式标记为 high impact。ModelPolicy只能声明模型策略,不允许保存模型供应商 token 明文。
9. 接口设计
本文只定义模块接口语义,不绑定具体语言。
| 接口 | 输入 | 输出 | 说明 |
|---|---|---|---|
loadConfig | config root、runtime env、strict mode | ConfigBundle 或 ErrorObject[] | 加载当前配置。 |
validateConfig | raw config files | validation result | 只校验,不生成运行时 bundle。 |
diffConfig | old bundle、new bundle | ConfigImpactReport | 生成配置影响报告。 |
getEffectivePolicy | agentId、request context | resolved policy 或错误 | Agent Access API 使用。 |
getIndexTargets | optional filter | enabled index targets | Index Adapter 和 Answer API 使用。 |
getSourceByPublishPath | normalized publish path | source entry 或 none | WorkspaceStore/SyncEngine 使用。 |
接口要求:
- 所有读取接口必须是无副作用的。
loadConfig对相同输入必须输出相同configHash。strict mode用于 CI 和 PR check,warning 可升级为 error。- 运行时 secret value 不进入
ConfigBundle的可序列化 canonical 结构。
10. 状态与持久化
ConfigManager 自身不拥有长期状态文件。
| 数据 | 是否持久化 | 位置 | 说明 |
|---|---|---|---|
| 原始配置 | 是 | config/*.yaml | 由人工 PR 修改。 |
ConfigBundle | 否 | in-memory | 运行时对象,可从配置重建。 |
configHash | 可被下游记录 | audit/manifest/check report | 用于追踪运行时配置版本。 |
ConfigImpactReport | 可被 ReviewBridge 写入 | PR body/check summary | 配置变更审查材料。 |
ConfigManager 不写 publish/**、state/** 或外部产品状态。
11. 错误处理
ConfigManager 使用 04-error-and-status-model.md 定义的 ErrorObject。
| 错误码 | retryable | 场景 | 处理 |
|---|---|---|---|
config.missing_file | false | 必需配置文件缺失 | 阻断 bundle 发布。 |
config.invalid_yaml | false | YAML 解析失败 | 返回文件路径和行列信息。 |
config.invalid_schema | false | 字段类型或必填项不满足 schema | 阻断。 |
config.unsupported_version | false | schemaVersion 不支持 | 阻断并提示迁移。 |
config.duplicate_id | false | source、target 或 agent id 重复 | 阻断。 |
config.duplicate_path | false | 多个 source 写入同一 publish path | 阻断。 |
config.path_overlap | false | publish path 互为父子目录 | 阻断。 |
config.secret_missing | true | secret 引用运行时不可用 | CI 可阻断;本地可降级为 warning。 |
config.unsafe_policy | false | agent policy 权限过大或越界 | 阻断。 |
config.cross_reference_missing | false | index/model/access 引用不存在 | 阻断。 |
错误输出必须包含 module=ConfigManager 和具体 operation。
12. 幂等与确定性
ConfigManager 没有外部写副作用,但必须保证确定性:
- 相同配置文件、相同默认值、相同运行模式生成相同
ConfigBundle。 configHash基于 canonical bundle 计算,字段顺序和 YAML 原始顺序不影响结果。- warning 顺序必须稳定,按文件、路径、字段排序。
- diff 输出必须稳定,避免 PR check 反复产生无意义变化。
- secret 实际值不参与
configHash,只有 secret reference 参与 hash。
13. 安全与隐私
- 不在错误详情、日志、audit 或 report 中输出 secret value。
- 对 agent policy 采用默认拒绝:未声明 agent、tool、path、dataset 时均拒绝。
includeWorkingDocs、扩大allowedPaths、新增写权限 属于高风险配置变更。- 配置中不允许出现绝对文件路径、用户本地路径或机器相关路径。
- 任何指向
config/**的 agent 读取权限默认非法,除非后续 ADR 明确允许只读白名单。
14. 测试要求
ConfigManager 必须通过 common fixture 中的配置类测试,并为下游模块提供稳定 contract。
| 测试 | Fixture | 预期 |
|---|---|---|
| valid sources | fixtures/common/config/sources.single.valid.yaml | 生成 SourceConfig。 |
| duplicate publish path | fixtures/common/config/sources.duplicate-publish-path.invalid.yaml | 返回 config.duplicate_path。 |
| index disabled | fixtures/common/config/index.disabled.valid.yaml | target 不进入 enabled 输出。 |
| unsafe agent path | fixtures/common/access/forbidden-scope.json | policy resolution 拒绝。 |
| config hash stable | future config golden fixture | 等价 YAML 顺序生成相同 configHash。 |
| secret missing | future secret reference fixture | 返回 config.secret_missing,不泄漏 secret name 之外信息。 |
模块验收标准:
- 所有配置对象都有 schema contract test。
- 所有 path 字段复用 common path normalization test。
- 所有高风险配置变更能出现在
ConfigImpactReport。 - 所有错误使用标准
ErrorObject。 - strict mode 下 warning 升级规则可测试。
15. 设计决策
| 决策 | 说明 | 取舍 |
|---|---|---|
| 配置通过 Git PR 修改 | 保持配置变更可审计、可回滚。 | 不支持后台 UI 直接热修改。 |
ConfigBundle 不持久化 | 避免派生状态和源配置不一致。 | 每次运行需要重新加载和校验。 |
| secret value 不进入 bundle hash | 避免 hash 泄漏 secret 变化和敏感信息。 | secret 轮换不会改变 configHash。 |
| policy 默认拒绝 | 降低 agent 越权风险。 | 配置初期需要更明确授权。 |
16. 待确认问题
RagflowConfig和ModelPolicy是否需要拆成 Public Contract,还是保持 Internal Contract。- 是否允许本地开发模式下缺失 secret 但继续生成部分
ConfigBundle。 includeWorkingDocs=true是否在 MVP 禁止,还是只作为 high impact 配置变更。- 配置 schemaVersion 的迁移窗口和兼容版本数量。