155 lines
5.2 KiB
Markdown
155 lines
5.2 KiB
Markdown
|
|
# 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 ./...` 通过
|