dcdc8d1ddd
全栈知识治理平台首次入库(P1-P10 + 发布链路模拟验证闭环): - 治理核心:源目录/变更集/人工审核/发布批次/发布执行(fail-closed 闸口) - 测试通道:WeKnora 测试 KB 上传/轮询/验收;poll 完成时写入 parser_generation/index_generation,修复 manual/seed 路径发布闸口永久拦截 - 发布适配器 v071(本地 source=测试角色 / 云端 target=生产角色 模拟验证通过): * ES 导出/导入 mapping 自适应(.keyword 子字段、可选 tenant_id) * OSS locator 支持嵌套 scheme;chunks.seq_id 由目标序列分配 * bundle 归档同身份重试原子替换;verifier 按 bundle chunk_type 计数 * 回滚 job payload 支持 prior_execution_id(strict 解码) - 三通道发布+回滚演练实测:publish 4/4 verified,检索命中, rollback 4/4 rolled_back,目标端 PG is_enabled=false、ES is_enabled=false - 前端 A·Data-console 风格全站统一,120 用例通过 - 门禁:go vet / go test 全包通过,gofmt 干净
294 lines
10 KiB
Markdown
294 lines
10 KiB
Markdown
# 知识治理平台领域对象契约
|
||
|
||
## 目的
|
||
|
||
本文件是知识治理平台当前实现的唯一领域对象映射。它将产品术语映射到现有Go模型、PostgreSQL表和外部边界;后续模块不得另造一套身份、时间或状态语义。
|
||
|
||
本文件不把“代码存在”“容器健康”写成已完成能力。尚未存在的对象或关联明确列在 [Current implementation gaps](#current-implementation-gaps)。
|
||
|
||
## 统一主链
|
||
|
||
```text
|
||
SourceConnection → SourceItem → SourceItemVersion → ContentObject
|
||
SourceConnection → SourceCatalogSnapshot → SourceCatalogNode
|
||
SourceCatalogChangeSet → SourceCatalogChangeItem
|
||
SourceItemVersion → TestPublication → AcceptanceResult
|
||
ReleaseBatch → ReleaseExecution → ReleaseItemExecution
|
||
```
|
||
|
||
完整目标主链将在后续工作包补齐为:
|
||
|
||
```text
|
||
SourceConnection
|
||
→ SourceItem / SourceItemVersion / ContentObject
|
||
→ SourceCatalogSnapshot
|
||
→ SourceCatalogChangeSet
|
||
→ ProcessingExecution / Job
|
||
→ TestPublication / AcceptanceResult
|
||
→ ReleaseChangeSet
|
||
→ ProductionSnapshot
|
||
→ ReleaseBatch / ReleaseExecution
|
||
```
|
||
|
||
## 全局身份与时间规则
|
||
|
||
| 规则 | 契约 |
|
||
| --- | --- |
|
||
| ID | 所有主对象使用服务端生成的不透明ID;页面和Job Payload只能传递ID,不能传递受保护来源URL、Token或Cookie。 |
|
||
| 时间 | `created_at`表示治理对象创建;`updated_at`表示本对象最后治理状态变化;来源侧时间必须单独使用`updated_at_source`或`source_updated_at`。 |
|
||
| 内容Hash | 只有`content_objects.sha256`是文件内容SHA-256。`canonical_uri_hash`、`source_locator_hash`和`snapshot_sha256`绝不能作为内容Hash展示或用于内容去重。 |
|
||
| 删除 | 来源不可用不等于来源删除。只有权威来源删除事件或经人工确认的删除ChangeSet才可进入目标移除流程。 |
|
||
| 目标写入 | 普通治理层不直接写WeKnora数据库;测试写入通过官方API/受控适配器;生产发布由独立Release Worker和门禁处理。 |
|
||
|
||
## Source
|
||
|
||
**产品含义:**一个独立配置、独立健康状态、独立刷新策略的资料来源。
|
||
|
||
**当前实现:**
|
||
|
||
| 项目 | 当前映射 |
|
||
| --- | --- |
|
||
| Go模型 | `governance.SourceConnection` |
|
||
| 数据表 | `source_connections` |
|
||
| 主键 | `source_connections.id` |
|
||
| 类型 | `source_type`:当前为`pp`、`alist`、`dingtalk`;`manual`是Go层支持的扩展类型。 |
|
||
| 时间 | `created_at`、`updated_at` |
|
||
| 可变配置 | `enabled`、`schedule`、`last_health` |
|
||
| 敏感字段 | `base_url`、`secret_ref`;不得返回前端或日志。 |
|
||
|
||
**不可变/关系约束:**
|
||
|
||
```text
|
||
一个SourceConnection可以有多个SourceItem。
|
||
一个SourceConnection可以有多个SourceCatalogSnapshot。
|
||
SourceItem、Snapshot、ChangeSet不得跨SourceConnection关联。
|
||
```
|
||
|
||
## SourceFile
|
||
|
||
**产品含义:**来源中的一份可治理资料,以及该资料的每个来源版本和内容对象。
|
||
|
||
SourceFile不是一个单表对象,当前由三个对象组成:
|
||
|
||
| 逻辑层 | Go模型 | 数据表 | 稳定身份 |
|
||
| --- | --- | --- | --- |
|
||
| 文件身份 | `governance.SourceItem` | `source_items` | `(source_connection_id, stable_external_id)` |
|
||
| 文件版本 | `governance.SourceItemVersion` | `source_item_versions` | `(source_item_id, revision)` |
|
||
| 内容对象 | `governance.ContentObject` | `content_objects` | 全局`sha256` |
|
||
|
||
**关键字段:**
|
||
|
||
```text
|
||
SourceItem:
|
||
- source_connection_id
|
||
- stable_external_id
|
||
- canonical_uri_hash
|
||
- normalized_path
|
||
- revision
|
||
- updated_at_source
|
||
- source_change
|
||
|
||
SourceItemVersion:
|
||
- source_item_id
|
||
- revision
|
||
- content_object_id(内容尚未下载或验证前允许为空)
|
||
- content_state
|
||
- source_updated_at
|
||
|
||
ContentObject:
|
||
- sha256
|
||
- size_bytes
|
||
- mime
|
||
- validated_format
|
||
- local_spool_ref
|
||
- content_state
|
||
```
|
||
|
||
**关系规则:**
|
||
|
||
```text
|
||
路径变化不必然产生新SourceItem。
|
||
内容Hash变化产生新的SourceItemVersion或新的内容关联。
|
||
同一内容Hash可以被多个SourceItemVersion复用,但每个版本仍保留自己的来源身份和来源时间。
|
||
TestPublication必须引用一个SourceItemVersion,不能直接引用路径或ContentObject。
|
||
```
|
||
|
||
## Snapshot
|
||
|
||
**产品含义:**一次来源目录扫描获得的不可变目录事实;它记录当时看到的文件/目录,而不是文件正文副本。
|
||
|
||
**当前实现:**
|
||
|
||
| 项目 | 当前映射 |
|
||
| --- | --- |
|
||
| 快照表 | `source_catalog_snapshots` |
|
||
| 节点表 | `source_catalog_nodes` |
|
||
| 当前指针 | `source_catalog_heads` |
|
||
| 快照主键 | `source_catalog_snapshots.id` |
|
||
| 来源约束 | `(source_connection_id, snapshot_sha256)`唯一 |
|
||
| 时间 | `observed_at`、`created_at`;Head使用`activated_at` |
|
||
| 目录节点 | `node_type=folder` |
|
||
| 文件节点 | `node_type=file` |
|
||
|
||
**Snapshot规则:**
|
||
|
||
```text
|
||
SourceConnection → SourceCatalogSnapshot → SourceCatalogNode
|
||
Head只指向一个当前快照;切换Head不得修改旧快照。
|
||
节点的source_locator_hash是来源定位摘要,不是内容Hash。
|
||
节点可选关联source_item_id;未关联节点仍可作为目录事实展示。
|
||
```
|
||
|
||
**操作记录补充:**`source_scans`和`source_scan_changes`是旧扫描运行记录,不能替代当前不可变目录快照。
|
||
|
||
## ChangeSet
|
||
|
||
**产品含义:**两个不可变来源Snapshot之间的可审查差异计划。
|
||
|
||
**当前实现:**
|
||
|
||
| 项目 | 当前映射 |
|
||
| --- | --- |
|
||
| 主表 | `source_catalog_change_sets` |
|
||
| 条目表 | `source_catalog_change_items` |
|
||
| Go投影 | `governance.CatalogChangeSet`、`CatalogChangeItem` |
|
||
| 主键 | `source_catalog_change_sets.id` |
|
||
| 快照关系 | `from_snapshot_id`、`to_snapshot_id` |
|
||
| 动作 | `add`、`update`、`move_scope`、`delete`、`no_change` |
|
||
| 时间 | `created_at`、`confirmed_at`、`applied_at` |
|
||
| 当前状态字段 | `planned`、`confirmed`、`applied`、`cancelled` |
|
||
|
||
**ChangeSet规则:**
|
||
|
||
```text
|
||
一个ChangeSet只能属于一个SourceConnection。
|
||
from_snapshot_id和to_snapshot_id必须属于同一SourceConnection。
|
||
to_snapshot_id当前唯一,因此一份激活快照最多对应一份目录ChangeSet。
|
||
ChangeItem当前使用(change_set_id, source_locator_hash)唯一。
|
||
ChangeSet只表达比较结果;它本身不等于已经上传、解析或删除。
|
||
```
|
||
|
||
**后续目标:**S8/P3/P5会补充SourceItemVersion、内容Hash、旧新范围、确认执行和Job关联。
|
||
|
||
## Job
|
||
|
||
**产品含义:**可租约、可重试、可恢复的异步工作项;Job只保存安全业务ID和进度,不保存敏感连接数据。
|
||
|
||
**当前实现:**
|
||
|
||
| 项目 | 当前映射 |
|
||
| --- | --- |
|
||
| Go模型 | `jobs.Job`(`internal/jobs`) |
|
||
| 数据表 | `jobs` |
|
||
| 主键 | `jobs.id` |
|
||
| 幂等 | `idempotency_key`唯一 |
|
||
| 调度 | `priority`、`available_at` |
|
||
| 租约 | `lease_owner`、`lease_until` |
|
||
| 尝试 | `attempt`、`max_attempts` |
|
||
| 时间 | `created_at`、`updated_at`、`started_at`、`completed_at` |
|
||
|
||
**当前Job类型示例:**
|
||
|
||
```text
|
||
source.catalog.refresh
|
||
test.upload
|
||
test.poll
|
||
test.validate
|
||
test.remove
|
||
release.publish
|
||
release.rollback
|
||
```
|
||
|
||
**Job规则:**
|
||
|
||
```text
|
||
Job完成只表示本地处理器完成;对于WeKnora解析,必须继续由test.poll确认远端终态。
|
||
Job payload不允许保存Token、Cookie、签名URL、原始文件内容或生产凭据。
|
||
ReleaseExecution通过job_id外键绑定发布Job。
|
||
```
|
||
|
||
## Release
|
||
|
||
**产品含义:**把经过测试验收的知识,以可追溯、可验证、可回滚方式发布到生产。
|
||
|
||
当前Release由批次、执行和执行项组成:
|
||
|
||
| 逻辑层 | Go模型 | 数据表 | 主键 |
|
||
| --- | --- | --- | --- |
|
||
| 发布批次 | `governance.ReleaseBatch` | `release_batches` | `id` |
|
||
| 批次条目 | `ReleaseBatchItemView`投影 | `release_batch_items` | `(release_batch_id, publication_id)` |
|
||
| 发布执行 | `governance.ReleaseExecution` | `release_executions` | `id` |
|
||
| 执行条目 | `ReleaseItemExecutionView`投影 | `release_item_executions` | `id` |
|
||
|
||
**Release关系:**
|
||
|
||
```text
|
||
ReleaseBatch → ReleaseExecution → ReleaseItemExecution
|
||
ReleaseExecution → Job(通过job_id)
|
||
ReleaseItemExecution → TestPublication(通过publication_id)
|
||
Rollback ReleaseExecution → prior publish ReleaseExecution
|
||
```
|
||
|
||
**Release规则:**
|
||
|
||
```text
|
||
ReleaseBatch sealed后内容不可变。
|
||
一个批次最多有一个publish execution。
|
||
一个publish execution最多有一个rollback execution。
|
||
ReleaseItemExecution记录生产前后revision和安全错误码。
|
||
只有独立生产门禁、备份恢复验证和Release Worker均满足时才可以请求生产执行。
|
||
```
|
||
|
||
## TestPublication和验收(辅助对象)
|
||
|
||
TestPublication不是原始SourceFile,也不是生产Release;它表示某个SourceItemVersion在指定测试知识库中的处理实例。
|
||
|
||
```text
|
||
SourceItemVersion → TestPublication → AcceptanceResult
|
||
```
|
||
|
||
| 项目 | 当前映射 |
|
||
| --- | --- |
|
||
| 测试发布 | `governance.Publication` / API投影`TestPublication` / 表`test_publications` |
|
||
| 验收结果 | `governance.AcceptanceResult` / 表`acceptance_results` |
|
||
| 身份 | `(source_item_version_id, test_kb_id)`唯一 |
|
||
| 处理维度 | ingest_state、processing_state、retrieval_state |
|
||
| 版本维度 | parser_generation、index_generation |
|
||
|
||
## 当前实现缺口
|
||
|
||
### Current implementation gaps
|
||
|
||
以下缺口是已知事实,不能在任何页面、报告或测试中标为“已完成”:
|
||
|
||
1. `SourceCatalogNode`尚不能为所有来源绑定`SourceItem`和`SourceItemVersion`。
|
||
2. 目录Snapshot节点尚未持久保存文件内容SHA-256;`snapshot_sha256`不是文件内容Hash。
|
||
3. `SourceCatalogChangeItem`尚未保存旧新内容Hash、旧新范围和SourceItemVersion关联。
|
||
4. ChangeSet确认尚未直接创建Processing Job;当前Processing Confirmation仅绑定TestPublication。
|
||
5. Job尚未通过统一外键绑定ChangeSet、文件版本、目标和动作;该工作属于P3/P5。
|
||
6. `ReleaseChangeSet`和`ProductionSnapshot`尚未实现;当前Release Plan是实时计算,不能冒充不可变发布ChangeSet。
|
||
7. 当前ReleaseExecution没有来源Snapshot、来源ChangeSet、发布ChangeSet和生产Snapshot的完整外键链;该工作属于R1、R2、R6。
|
||
8. Source配置、SourceFile身份和内容Hash的运行时证据仍需后续S2、P1、P2补齐。
|
||
|
||
## C1验收边界
|
||
|
||
C1只完成以下内容:
|
||
|
||
```text
|
||
冻结当前对象术语和真实映射
|
||
明确身份、时间和关系规则
|
||
标出当前不存在的对象和关联
|
||
用测试防止领域契约文档丢失关键对象
|
||
```
|
||
|
||
C1不完成:
|
||
|
||
```text
|
||
统一状态机(C2)
|
||
OpenAPI(C3)
|
||
写操作幂等(C4)
|
||
内容Hash闭环(P1)
|
||
ChangeSet执行(P3)
|
||
发布ChangeSet或Production Snapshot(R1/R2)
|
||
```
|