Files
supply-intelligence/tech/B2_B3_B4_IMPLEMENTATION_SPEC_2026-05-07.md
2026-05-12 18:49:52 +08:00

155 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 ./...` 通过