Files
supply-intelligence/tech/PRODUCTION_P0_P1_P2_BOARD_2026-05-08.md

161 lines
7.9 KiB
Markdown
Raw Normal View History

2026-05-12 18:49:52 +08:00
# Supply-Intelligence 生产上线 P0/P1/P2 收敛板2026-05-08
状态:当前有效
仓库:`/home/long/project/立交桥/projects/supply-intelligence`
目标:把当前已完成的 B2/B3/B4 实现闭环,继续推进到“可生产上线判定”所需的最小生产门禁。
## 0. 当前结论
当前结论REQUEST_CHANGES
已完成事实:
- publish 已不再只是 event append已驱动 candidate `test_passed -> published`、package `draft -> active`
- admission-state 已能反映 publish 后组合态以及 ack 后 gateway_sync_status 变化
- 相关 targeted tests 已通过:
- `go test ./internal/publish ./internal/httpapi ./internal/app ./internal/repository`
仍不能宣称可生产上线的原因:
- PostgreSQL 持久化路径与内存仓储语义未收敛,当前 publish 主链路缺少数据库事务/并发保护证据
- 发布幂等、重复发布、冲突发布、ack 重放/乱序等生产失败路径证据不足
- 缺少基于 PostgreSQL 的真实端到端链路验证与上线证据包
## 1. 已复核事实基线
### 1.1 代码级事实
- `internal/publish/service.go` 已存在 `PublishDraft(ctx, PublishDraftInput)` 主入口
- `internal/httpapi/server.go``/internal/supply-intelligence/publish/package-event` 已切到真实发布语义
- `internal/httpapi/admission_state_api_test.go` 已验证 publish 后 `published + active + pending` 以及 ack 后 `applied`
- `internal/gatewayconsumer/service.go` 已具备最小 `consume-once -> ack -> snapshot` 路径
### 1.2 当前生产差距(实测/读码得出)
1. `internal/repository/postgres.go`
- `AppendPackageEventContext()` 仍是 `ON CONFLICT (event_id) DO NOTHING`,但上层未把冲突解释为幂等成功/重复请求拒绝的明确产品语义
- `UpdateCandidateStatus()``UpsertSupplyPackage()``AppendPackageEventContext()` 彼此独立执行,未处于同一数据库事务
- 全文件未见 `Begin/Commit/Rollback/FOR UPDATE`,说明 publish 主链路当前没有 PostgreSQL 事务级一致性保护
2. 目前通过的测试主要基于内存仓储;尚未看到 PostgreSQL 集成测试证明:
- 并发双发布只会成功一次
- 重复 event_id 的幂等语义稳定
- package/candidate/event 在异常中不会出现部分提交
3. 仓库虽已有 `docker-compose.yml``migrations/``internal/repository/postgres.go`,但未形成 production gate 所需的真实 E2E 证据链
## 2. 分级任务板
## P0. 生产阻塞项(不上这些,不能判定可上线)
### P0-1. PostgreSQL 发布事务原子化
- OwnerEngineer
- 目标:把 publish 主链路收敛为单事务提交,而不是多次独立写入
- 代码落点:
- `internal/repository/interfaces.go`
- `internal/repository/postgres.go`
- `internal/publish/service.go`
- 可能新增 `internal/repository/postgres_publish_tx_test.go`
- 必须达成:
- candidate 状态更新、package 状态更新、event append 在同一 DB 事务中完成
- 任一步失败时整体回滚
- 明确重复 publish 的返回语义(幂等成功或冲突失败,必须固定)
- 验证:
- `go test ./internal/publish ./internal/repository`
- 至少一条 PostgreSQL 集成测试证明回滚语义
- 当前状态:**completed** — `PostgresRepository.PublishPackageAtomically` 已实现 `BEGIN/UPDATE/UPSERT/INSERT/COMMIT``TestPostgresPublishPackageAtomicallyRollsBackOnDuplicateEvent` 通过
### P0-2. 重复发布/并发发布保护
- OwnerEngineer
- 目标:防止同一 `platform+model` 或同一 draft package 被重复发布
- 代码落点:
- `internal/publish/service.go`
- `internal/repository/postgres.go`
- `internal/repository/memory.go`
- 相关 `*_test.go`
- 必须达成:
- candidate 已 `published` 或 package 已 `active` 时再次发布,有明确拒绝/幂等语义
- 并发双发布测试下,最终只能有一个成功结果
- event 不可重复污染 downstream queue
- 验证:
- 并发测试 / 重复调用测试通过
- 当前状态:**completed** — 已补充 `TestPostgresPublishPackageAtomicallyConcurrentDoublePublish`,验证并发双发布时仅一个成功、无脏数据
### P0-3. PostgreSQL 真实链路 E2E
- OwnerQA
- 目标:在 PostgreSQL 环境下验证最小生产主链路
- 链路candidate -> admission(test_passed) -> publish -> package-changes -> consume-once -> ack -> admission-state
- 代码/资产落点:
- 现有 `docker-compose.yml`
- `migrations/`
- 新增 `internal/...` PostgreSQL 集成测试或 `scripts/` 验证脚本
- 必须达成:
- 不是仅 `go test ./...`,而是真实 PostgreSQL 状态可读回
- admission-state 能反映 pending/applied/failed
- gateway snapshot 与 event ack 状态一致
- 验证:
- 可复现命令 + 实际输出
- 当前状态:**completed** — `TestPostgresE2EPublishConsumeAckAdmissionState` 已覆盖完整链路,`TestPostgresE2EPublishConsumeAckAdmissionStateRequiresAuthorizedConsumer` 验证未授权消费过滤
## P1. 上线前必须补齐项P0 完成后,仍建议上线前补齐)
### P1-1. 失败补偿与错误语义收敛
- OwnerTechLead -> Engineer
- 目标:补明确的失败模型,而不是只靠 internal_error
- 范围:
- 发布冲突
- event 已存在
- ack 重放
- ack 目标不存在
- consumer apply failed 的重试/终态语义
- 交付:错误码/状态机/handler 响应语义收敛
- 验证:针对失败路径的 HTTP/API 测试
- 当前状态:**completed** — 已有明确错误码(`ErrInvalidPublishInput`/`ErrCandidateNotPublishable`/`ErrPackageNotPublishable`/`ErrDuplicatePublishRequest`/`ErrPackageAlreadyPublished`、重试策略1m/5m/15m最多2次、终态定义applied/pending/failedconsumer 测试覆盖所有失败路径
### P1-2. gateway consumer 生产约束验证
- OwnerQA
- 目标:验证 gateway 侧不是“最小骨架可跑”,而是生产语义可解释
- 必查:
- 未授权 account 过滤
- pending-only 消费
- apply failed 后状态可见
- snapshot 与 event ack 不漂移
- 验证definition -> assembly -> call -> entry 四层核查 + targeted tests
- 当前状态:**completed** — `TestServiceConsumeOnceSkipsUnauthorizedEvents``TestPostgresE2EPublishConsumeAckAdmissionStateRequiresAuthorizedConsumer``TestServiceConsumeOnceFailedDoesNotDriftSnapshot` 等已覆盖
### P1-3. 上线证据包
- OwnerXL
- 目标:形成真正可用于上线判定的证据包
- 必须包含:
- 通过命令
- 覆盖的关键链路
- 明确未覆盖项
- 可宣称项 / 不可宣称项
- 回滚方式
- 当前状态:**completed** — 已归档 `reports/production/SHARED_ENV_EVIDENCE_RUN_2026-05-09.md` 及 tksea 版本,含 G1-G3 证据
## P2. 可上线后补项(不阻塞首版上线判定)
### P2-1. actor / 审批链 / 审计增强
- OwnerPM -> TechLead -> Engineer
- 说明:当前 publish 语义可先无完整审批产品化,但上线后应补 actor、审批来源、审计追踪
- 当前状态pending
### P2-2. 真实远端 gateway 集成
- OwnerDevOps/Engineer
- 说明:当前 `consume-once` 仍偏本地 apply/ack 语义,后续应补真实下游系统契约
- 当前状态:**conditional_debt** — 首版上线允许携带,必须在第一个迭代周期内补清(建议 2 周内)
### P2-3. 观测与运行基线
- OwnerDevOps
- 说明:补指标、告警、日志字段、发布/ack 异常观测面
- 当前状态pending
## 3. 推荐执行顺序
1. P0-1 PostgreSQL 发布事务原子化
2. P0-2 重复发布/并发发布保护
3. P0-3 PostgreSQL 真实链路 E2E
4. P1-1 / P1-2
5. P1-3 上线证据包
## 4. 明确禁止的错误结论
- 不得把内存仓储测试通过等同于 PostgreSQL 生产可用
- 不得把 `published` 等同于 `gateway applied`
- 不得把 `ON CONFLICT DO NOTHING` 视为已完成幂等设计
- 不得把缺少事务保护的多次独立写入视为“发布事务已完成”
- 不得在缺少 PostgreSQL E2E 证据时宣称可上线