Files
supply-intelligence/tech/B2_B3_B4_IMPLEMENTATION_SPEC_2026-05-07.md

155 lines
5.2 KiB
Markdown
Raw Permalink Normal View History

2026-05-12 18:49:52 +08:00
# B2/B3/B4 实施规格2026-05-07
状态:当前有效
范围candidate 状态收敛、publish 事务闭环、admission-state API 真正接线
真源:
- tech/CURRENT_SOURCE_OF_TRUTH_2026-05.md
- tech/BASELINE_TECHLEAD_V2.md
- tech/GATEWAY_CONSUMER_DECISION_2026-05.md
## 1. 目标
把 supply-intelligence 从“各子模块最小骨架存在”推进到“candidate -> admission -> draft package -> publish -> gateway sync state -> admission-state 查询”这一条真实生产闭环更接近可验状态。
本轮不扩范围到独立平台化、重基础设施、自动注册,只做当前收口板 B2/B3/B4。
## 2. 当前已验证现状
1. `go test ./...` 当前通过。
2. `internal/domain/types.go` 中 candidate 状态枚举已不包含 `pending_admission` / `admitted`
3. `internal/httpapi/server.go``parseDiscoveryCandidateStatus()` 已只接受:
- discovered
- testing
- test_passed
- test_failed
- retry_pending
- ignored
- published
- deprecated
- closed
4. `internal/httpapi/server.go` 已存在 `/internal/supply-intelligence/models/{platform}/{model}/admission-state` 路由与 handler。
5. `internal/publish/service.go` 目前只支持“追加 package published event”还不是“运营确认上架事务”。
6. `internal/admission/service.go` 在测试通过后会创建/更新 draft package并把 candidate 置为 `test_passed`
7. `internal/httpapi/admission_state_api_test.go` 目前只验证 candidate/package/event 聚合读取,不验证真实 publish 事务。
## 3. 本轮必须收敛的缺口
### B2. candidate 状态与 admission 流转
必须满足:
- admission 只允许 `discovered` / `retry_pending` 进入执行。
- admission 执行开始后置为 `testing`
- admission 失败后置为 `test_failed``retry_pending`(本轮沿用现状失败归 `test_failed`)。
- admission 成功后置为 `test_passed`
- publish 成功后 candidate 必须从 `test_passed` -> `published`
- 不允许重新引入旧状态口径。
### B3. publish 事务闭环
必须新增真实语义:
- 输入不再只是 event append 所需字段。
-`platform + model`(必要时 package/candidate为主键读取当前真实状态。
- 仅当 candidate 最新状态为 `test_passed` 且 package 当前为 `draft` 时允许发布。
- 发布动作要同时完成:
1. package `draft -> active`
2. candidate `test_passed -> published`
3. 追加 `supply_package_published` event默认 `gateway_sync_status=pending`
- 明确 `published != applied`gateway applied 仍由 ack 驱动。
### B4. admission-state API
必须返回当前组合真相:
- latest candidate truth
- current package truth
- latest matching package event truth
- gateway sync status
并在 publish 事务跑完后能够体现:
- candidate_status = published
- package_status = active
- gateway_sync_status = pending直到 ack
## 4. 最小改动设计
### 4.1 repository / app 适配层
尽量不改 repository 主接口的大结构,只补 publish service 所需最小能力,优先复用已有:
- `GetLatestDiscoveryCandidateContext()`
- `GetSupplyPackage()`
- `UpsertSupplyPackage()`
- `UpdateCandidateStatus()`
- `AppendPackageEventContext()`
如 publish 包直接依赖 domain/repository 成本更低,可在 publish 内定义更完整 repo interface再由现有 repository.Repository 满足。
### 4.2 publish service 新增主入口
建议新增:
- `PublishDraft(ctx, PublishDraftInput) (PublishDraftOutput, error)`
输入最小字段:
- event_id
- platform
- model
- actor/source可选本轮如无真实审计先留空
- occurred_at可选
输出最小字段:
- candidate
- package
- event
- gateway_sync_status
保留 `RecordPackagePublished()` 兼容测试/已有接口,但 HTTP 主入口要逐步切换为真正发布语义,而不是“外部直接塞 event”。
### 4.3 HTTP API
当前 `/internal/supply-intelligence/publish/package-event` 若继续存在,本轮将其语义提升为“确认发布 draft package”不再允许脱离 candidate/package 真相直接伪造 event。
请求体建议最小化为:
- event_id
- platform
- model
- occurred_at
如果保留 package_id/version 也应以服务端真相为准,不信任调用方覆盖 package 当前状态。
## 5. 验证标准
必须新增/更新测试覆盖:
1. publish 成功:
- candidate `test_passed -> published`
- package `draft -> active`
- event appended with pending sync
2. publish 拒绝:
- candidate 不是 `test_passed` 时拒绝
- package 不是 `draft` 时拒绝
- candidate/package 不存在时拒绝
3. admission-state
- publish 后查询可看到 `published + active + pending`
- ack 后查询可看到 `applied/failed`
4. 全量验证:
- `go test ./...`
## 6. 不做项
本轮明确不做:
- 审计表完整补齐
- actor/审批链完整产品化
- DB 事务级锁语义重构
- gateway 实际远端集成
- auto-supply / deep registration
## 7. 完成定义
仅当以下同时成立B2/B3/B4 才能算完成:
- 代码不再只有“event append 记录器”语义
- publish 真正驱动 candidate/package 状态变化
- admission-state 能反映 publish 后组合真相
- 新增测试通过
- `go test ./...` 通过