Files
chis_osi/tasks.md
T

108 lines
10 KiB
Markdown
Raw Normal View History

2026-07-06 20:09:54 +08:00
# 任务看板(Tasks)
> 把 `docs/05-实施路线图.md` 的阶段拆成小步、可独立交付、可验收的任务。
> 每轮只领取**一个**状态为 `TODO` 且依赖均 `DONE` 的任务(取最靠前的)。
## 使用规则
1. 开工前读 `docs/current-state.md`(当前快照)与 `CLAUDE.md`(硬规则)。
2. 领取任务时把状态改为 `DOING`(同一时间最多 1 个)。
3. 标 `DONE` 前必须有**可运行证据**:验证命令和结果追加到 [`progress.md`](progress.md);只有"代码已写"不算完成。
4. 完成后:更新本文状态 → 追加 `progress.md` → 覆盖更新 `docs/current-state.md`。
5. 代码现实与看板冲突时,先说明冲突,不擅自跳步。
状态图例:`TODO` 待开始 · `DOING` 进行中 · `DONE` 完成并验收 · `BLOCKED` 受阻(注明原因)
---
## Phase B · 基线(接入 harness,先于一切新功能)
| ID | 任务 | 依赖 | 验收要点 | 状态 |
| --- | --- | --- | --- | --- |
| T-000 | 处理失效测试 `tests/test_query_health_record.py` | - | 它 import 的旧脚本 API 已删除(脚本已重写为硬编码版):要么删除,要么改写为校验新信封结构的最小测试;`pytest tests/` 通过或目录清空 | DONE |
2026-07-06 20:09:54 +08:00
## Phase 0 · 脚手架与契约骨架(路线图阶段 0)
| ID | 任务 | 依赖 | 验收要点 | 状态 |
| --- | --- | --- | --- | --- |
2026-07-06 20:54:23 +08:00
| T-001 | 初始化 go module + `main.go` 双子命令骨架 + `config/`(viper) | - | `go build ./...` 通过;`-mode server\|deliver` 可解析;`config.yaml.example` 占位值就绪 | DONE |
| T-002 | `osi/sign.go` MD5 头签名 + 单测 | T-001 | 单测校验 `password=md5("ts=<ts>&ask=<ask>")` 32 位小写;与 Python 脚本(scripts/,本地)产出比对一致 | DONE |
| T-003 | `osi/transport.go`:从 chis_upload 移植传输层 | T-001 | 保留 SOCKS5/超时;去掉 cookiejar 与网页拟态头;单测或最小连通验证 | DONE |
| T-004 | `osi/client.go` `Call` + `osi/codes.go` + `contract/envelope.go` | T-002, T-003 | 信封为 `serviceId`+`uploadinfo{baseInfo,manageInfo,...}`(docs/04 §8);成功码按去前导零 == `"1"` 判定(实测 `"01"`,docs/01 §1);`405` 归类可重试 | DONE |
| T-005 | 阶段 0 验收:Go 侧真实请求打通 + 配置 `init.sh` | T-004 | 用 JKDA00002(Python 已验证的同一查询)发真实请求拿到 `code="01"`;`./init.sh` 三命令替换完成,本机 Git Bash 运行限制见 progress 记录 | DONE |
| T-006 | Phase 0 review hardening | T-005 | 处理审核指出的 gzip 声明、传输层死代码、命令行 PII、Envelope 冗余;`go test ./...` 通过 | DONE |
2026-07-06 20:09:54 +08:00
> **执行顺序说明(2026-07-06 重排,查询先行)**:原路线图"阶段1字典 → 阶段2档案"的顺序假设了先建字典。
> 但**查询档案(Find)根本不依赖字典**,**映射纯函数单测**也只需码表 + 注入假字典快照。
> 真正需要字典查询接口(网格/责任医生/机构反查)的只有**真实创建闭环**。
> 故按能力重排为 Q(查询)→ M(映射)→ D(字典+创建);ID 保持不变,`osi/jkda.go` 的 Find 与 Create 拆成 T-203 / T-206。
> 字母命名的执行阶段(B/0/Q/M/D)区别于 Backlog 里的"路线图阶段 3~6"。
## Phase Q · 查询档案打通(Find,不依赖字典)
| ID | 任务 | 依赖 | 验收要点 | 状态 |
| --- | --- | --- | --- | --- |
| T-201 | `contract/jkda.go`:以 docs/04 §8 实测契约建**查询响应**结构体 | T-004 | Find 响应能完整反序列化本地联调样本(`data` 数组、null 字段用指针/omitempty、`adressNumber` 坑点拼写);创建请求结构体延到 T-206 补 | DONE |
| T-203 | `osi/jkda.go`:**Find + FindRqbj** | T-201 | 用 JKDA00002 真实请求打通,拿到 `code="01"` 与档案数据,与 Python 脚本结果一致 | DONE |
| T-208 | `server` 模式健康档案查询端点 `GET /api/health-record/find` | T-203 | server 模式起 HTTP 服务,curl 按 idCard/phrid/personName/empiId 查询返回平台完整档案 JSON;默认仅绑本机 | DONE |
| T-209 | 优化人群分类查询 JKDA00005(路径/契约/HTTP 端点) | T-203, T-208 | 按实测 `auto/jkda/findrqbj` 查询,响应结构含 `personSign/idCard/phrId`;server 模式提供人群分类查询端点并原样回写平台 JSON | DONE |
## Phase M · 映射层(码表 + 纯函数,注入假字典快照)
| ID | 任务 | 依赖 | 验收要点 | 状态 |
| --- | --- | --- | --- | --- |
| T-102 | `mapping/dict.go` 全量码表(含 56 项民族) | T-001 | 双向查表;未命中显式 ValidationError;单测覆盖(静态枚举,不走网络) | DONE |
| T-202 | `mapping/health_record.go` + `mapping/checkid.go` | T-102, T-201 | 映射纯函数 + 结构化校验错误;主数据经 `MapContext` 字典快照注入(单测塞假快照);checkId 确定性生成单测 | DONE |
| T-205 | 映射单测基线:docx 样例 + 联调样本 | T-202 | `go test ./mapping/...` 全绿;必填/码表/格式校验生效 | DONE |
## Phase D · 字典服务与创建闭环(真实主数据反查)
2026-07-06 20:09:54 +08:00
> **读先行调整(2026-07-08)**:档案**创建/更新**(T-206/T-204)真实验收依赖厂家写入授权 + 安全测试档案(docs/06 D3),当前锁死。
> 故把**其余业务线的查询**(Phase Q2)提到写入之前先做——读路径不被授权阻塞,且顺带摸清各业务线响应字段,为将来写入去风险。
> T-206 创建代码已完成并入库,保持不动,授权到位后再回来验收。
2026-07-06 20:09:54 +08:00
| ID | 任务 | 依赖 | 验收要点 | 状态 |
| --- | --- | --- | --- | --- |
| T-101 | `osi/public.go` 四个字典查询(网格/责任医生/药品/机构) | T-005 | 真实机构码能查到下级网格、责任医生、机构树 | DONE |
| T-103 | 字典缓存(内存 + redis 可选) | T-101, T-102 | 映射层能反查 `regionCode/manaDoctorId/manaUnitId`;redis 不可用不阻断 | DONE |
2026-07-09 21:17:16 +08:00
| T-210 | 公开查询 HTTP API(人群分类、网格地址、责任医生、药品目录、机构) | T-101, T-209 | server 模式暴露人群分类与四类公开查询 HTTP API;原样回写平台 JSON;同步 `docs/07` 与 `docs/openapi.yaml`;按内网部署场景明确绑定地址/鉴权边界 | TODO |
| T-206 | `osi/jkda.go`:**Create/Update** + `contract/jkda.go` 补创建请求结构体 | T-201, T-202, T-103 | 一条档案经映射(真实字典快照)→ create → 平台返回成功码与 `phrId`;Update 沿用 checkId | BLOCKED(代码完成;待写入授权/测试档案,排在 Phase Q2 之后) |
| T-204 | `handler`+`router`:`/api/health-record/save` | T-206 | server 模式起服务,curl 全链路返回投递结果 | TODO(待 T-206 解阻塞) |
## Phase Q2 · 其余业务线查询(读先行)
> 每条查询任务都顺带把响应真实字段记入 `docs/04`(像 §8),作为将来对应业务线 create 映射的事实基线。
| ID | 任务 | 依赖 | 验收要点 | 状态 |
| --- | --- | --- | --- | --- |
| T-301 | 体检查询打通:`contract/jktj.go` + `osi/jktj.go`(最近一次 JKTJLSJL00002) | T-004 | 真实请求拿到 `code="01"` 与体检数据;响应字段(~260 项/7 节点)记入 docs/04 §11 | DONE(单条 JKTJ00002 平台未部署,见 §11) |
| T-302 | 体检 HTTP 查询端点(复用 T-208 handler 模式) | T-301 | server 模式 `GET /api/health-check/last`+`/all`+`/list` curl 返回完整 JSON;默认仅绑本机 | DONE |
| T-306 | 某人全部体检查询 JKTJ00002(`osi.QueryHealthChecks` + `/api/health-check/all`)| T-004 | 实测已部署,按 idCard 返回全部体检数组;驼峰 idCard、历史记录 checkId 可空,契约见 docs/04 §11.1 | DONE |
| T-303 | 老年人查询打通:自理 LNRZLPG / 体质 LNRZYTZ(查询 serviceId 部分待确认) | T-004 | 真实请求打通;缺失 serviceId 先向厂家确认(docs/06 B4) | TODO(部分待 B4) |
| T-305 | 体检已检/未检名单查询 JKTJLIST00002(`osi` 方法 + 契约)| T-004 | `auto/jktjlist/query` 探针实测已部署(code=01 返回名单);`osi.ListHealthCheckPeople` 按 checkYear+idCard 返回名单(含 checkType 状态),契约见 docs/04 §11.4 | DONE |
| T-304 | 列表类查询(**档案 / 老年人自理·体质 / 中医指导** 列表,serviceId docx 缺漏)| T-004 | 各列表路径+serviceId 到位后返回分页数组 | BLOCKED(待 docs/06 B1/B2 厂家回填)|
2026-07-06 20:09:54 +08:00
## 里程碑
- M1 = T-005:Go 客户端与平台真实握手成功(签名/信封/判码全对)。
- M2 = T-203:**Go 版查询档案打通**(Find,不碰字典)。
- M3 = T-205:映射层就绪 + 单测基线(假字典快照)。
- M4 = T-301:**体检查询打通**(其余业务线读先行第一条)。
- M5 = T-206:真实创建闭环 + 幂等(授权到位后,字典反查主数据 → create → phrId)。
2026-07-06 20:09:54 +08:00
## 待办池(Backlog,按路线图阶段 3~6 展开,进入时再拆小任务)
- 阶段 3:投递流水线(retry/idempotency/circuit/report + `-mode deliver`)。
- 阶段 4:其余业务线(体检 JKTJ 字段最多、老年人自理、中医体质、中医指导——B1/B2/B5 契约到位后拆)。
- 阶段 5:PHIS 真实接入与状态回写。
- 阶段 6:加固与交接(完整度定论、密钥环境变量化、运维文档、全绿)。
- 联调依赖跟踪见 `docs/06-厂家联调清单.md`(B 组契约缺口会阻塞阶段 4)。
### 已登记的延期任务(带 ID,条件满足即提升到对应 Phase)
| ID | 任务 | 触发条件 | 验收要点 | 状态 |
| --- | --- | --- | --- | --- |
| T-007 | 传输层支持 https/TLS | **生产环境地址确认为 https 时必须先做**(沙箱是 http,不阻塞当前开发) | `osi/transport.go` 裸 HTTP/1.1 写目前仅支持 http(明文 TCP、`scheme != "http"` 直接报错)。需在 TLS 下同样保留 `orgCode/deviceSN/userName` 头名大小写策略;对 https 目标能发起真实请求并拿到 `code`;单测覆盖 https 路径 | TODO(生产前 gate) |
> 来源:`docs/review/2026-07-06-phase0-review.md` P1-2。向厂家确认生产地址协议(见 `docs/06` A10)后,若为 https 则本任务提升为阻断项;若确认生产仍是 http,则关闭本任务并在传输层注释说明。