docs(g4): acceptance record for uniservice user source integration
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# G4 验收记录:用户接口对接(uniservice /open/v1/users)
|
||||
|
||||
对应方案:[2026-09-22-G4-用户接口对接-实施计划](../2026-09-22-G4-用户接口对接-实施计划.md)
|
||||
执行日期:2026-09-22
|
||||
外部契约:[open-v1-users-api.md](../../open-v1-users-api.md)(服务方 uniservice,合塑/新友合集团统一后台)
|
||||
|
||||
## 0 基线与保护
|
||||
|
||||
- 基线 commit:f193e4f(fix(viewer): remove extra closing brace)。
|
||||
- 工作树既有改动收编:起始时工作树存在 G4 半成品未提交改动
|
||||
(docs/open-v1-users-api.md、http-user-source.ts 草稿、user-sync.service.ts 引擎
|
||||
V1.1 行为变更、.env 两示例新增变量)——本任务全部收编重写/对齐后分批提交。
|
||||
- 契约/schema 零改动:packages/contracts、db-cn/db-ov schema、main-ov.ts、
|
||||
同步账本(outbox/sync_inbox/sync_state)均未触碰;引擎红线 1-4 逐条维持
|
||||
(e2e ①-⑫ 全量断言仍守护)。
|
||||
|
||||
## 1 关键决策及依据
|
||||
|
||||
| 决策 | 依据 |
|
||||
|---|---|
|
||||
| V1.1 初始凭据:同步新建用户直接 `credentialStatus=active`,账号=手机号,初始密码=手机号后 6 位(不足回退 '000000'),**全局生效(含 mock 源)** | 用户拍板(2026-09-22,真实接口上线即用);P4a「待激活+哨兵哈希」闭环退役,auth.service 等代价 dummy verify 防御保留兼容历史行;activate 端点对 active 用户幂等,reset-password 仍为管理员轮换出口 |
|
||||
| HTTP 源**每批全量拉取**,不做增量 | 上游 API 无增量过滤参数(仅 page/page_size/company_id/status/keyword/ids);幂等由引擎既有行级 sourceVersion 比较保证(213 用户/200 每页≈2 页,成本可忽略) |
|
||||
| 游标协议:续翻块编码 `p:N`;**纯数值水位绝不解析为页码** | 半成品草稿的严重 bug:引擎增量批传入水位(epoch 秒,如 "1758520000")被 `parseInt` 当页号→请求第 17 亿页→空页"成功"空转。单测有专项回归用例 |
|
||||
| 一人多档按 phone **全局**(跨上游页)去重,保留 updated_at 最新行 | 草稿仅页内去重:同 phone 两行分落两页时后应用的旧行(如离职档)会覆盖新行状态。全量先拉齐再切块,消除跨页分裂 |
|
||||
| `external_user_mappings.sourceSystem` 随源:mock=`'mock'`、http=`'uniservice'` | UserSourcePort 新增只读 `sourceSystem`;映射锚点 (sourceSystem, externalUserId) 命名空间按源隔离,既有 `mock:` 映射自然成为孤儿(预期,见 §5) |
|
||||
| 模块装配 env 开关 `USER_SYNC_SOURCE=mock|http`,缺省 mock | e2e/本地默认零变化(app.get(MockUserSource) 注入场景依赖);生产显式切换 |
|
||||
|
||||
## 2 改动清单(提交序列)
|
||||
|
||||
| commit | 内容 |
|
||||
|---|---|
|
||||
| 42878f1 | docs(g4):接口文档 + 实施计划入库 |
|
||||
| b7754d5 | test(api):e2e ①⑤⑪ + 文件头按 V1.1 重写(新增"同步即可登录"断言,强度不低于旧哨兵断言) |
|
||||
| 52cd316 | refactor(api):端口 sourceSystem + 引擎收编(initialPassword helper、删哨兵死代码、注释 V1.1 化、auth.service 注释历史化) |
|
||||
| d732caa | feat(api):HttpUserSource 适配器(全量拉取+全局去重+分块续翻缓存+页数护栏)+ 5 单测(fetch mock) |
|
||||
| 8c255eb | feat(api):USER_SYNC_SOURCE 开关装配 + .env.example / .env.production.example-cn |
|
||||
| (本提交) | docs(g4):本验收记录 |
|
||||
|
||||
文件:user-source.port.ts、mock-user-source.ts、user-sync.service.ts、http-user-source.ts(重写)、user-sync.module.ts、auth.service.ts(仅注释)、test/user-sync.e2e-spec.ts、test/http-user-source.spec.ts(新增)、.env 两示例。
|
||||
|
||||
## 3 测试证据
|
||||
|
||||
- `pnpm --filter @photo/api-cn typecheck`:0 error。
|
||||
- 单测全量:`pnpm --filter @photo/api-cn test` → **8 套件 / 56 用例全绿**(含 http-user-source.spec 5 用例:跨页去重/水位不当页码回归/分块续翻缓存/401·500·success=false·env 缺失/无手机号跳过)。
|
||||
- user-sync e2e:`test:e2e -- user-sync.e2e-spec` → **12/12 全绿**(红线逐条断言维持;⑪ 新语义:初始密码登录 200 → activate 幂等 → reset-password 轮换后初始密码 401)。
|
||||
- 全量 e2e:`test:e2e` → **22/24 套件通过(249/257 用例)**,2 个失败均与本分支无关(见 §5 残留,均已取证)。
|
||||
|
||||
### 环境事件登记(复现性说明)
|
||||
|
||||
首次全量 e2e 出现 8 套件失败,排查定位为**本地游离 `pnpm dev:worker` 进程(PID 56112)抢消费 e2e 照片处理队列**(测试自行直调 PublishService,worker 抢先将照片置 ready → `processPhoto` 返回 'already')。经用户确认终止该进程后复跑:uploads/watermark/batch-ops/full-chain/likes-realtime/public-ov 全部恢复绿。本地跑全量 e2e 前须确认无游离 worker。
|
||||
|
||||
## 4 部署注意(P5 线)
|
||||
|
||||
- 生产/测试服务器 cn 侧 env 三变量:`USER_SYNC_SOURCE=http` +
|
||||
`OPEN_API_USERS_URL=https://uniservice.server.hnxinyouhe.com/open/v1/users` +
|
||||
`OPEN_API_USERS_KEY=<服务方下发>`(key 仅服务端持有,勿入前端/仓库)。
|
||||
- **本地开发 .env 切勿设 `USER_SYNC_SOURCE=http`**——模块 import 时读 env,会导致
|
||||
user-sync e2e 的 `app.get(MockUserSource)` 解析失败。
|
||||
- key 未配置/错误的表现:每批 sync failed(批次行 error 落"鉴权失败/HTTP 401"),
|
||||
不影响任何既有用户/会话——引擎批次级故障隔离语义。
|
||||
- 测试服务器(219.157.255.213)换真实 key 后建议手动触发一批
|
||||
(POST /v1/admin/user-sync/runs)并核对 status/runs/errors 与 users 新增
|
||||
(账号=手机号、可手机号后 6 位登录)——属 P5 待办。
|
||||
|
||||
## 5 残留与登记偏差
|
||||
|
||||
- **embed.e2e-spec 失败(既有,非本分支)**:API settings 响应含 UI-04 线新增
|
||||
`displayMode` 字段而该 spec 期望对象未更新——基线 f193e4f 上复现同样失败
|
||||
(取证:checkout 基线单跑 exit 1)。归属 UI-04 线待修。
|
||||
- **health.e2e-spec 全量长跑偶发(非本分支)**:两次全量中出现一次,单独跑恒
|
||||
6/6 绿;长跑资源竞争瞬时问题,登记观察。
|
||||
- admin UI `sourceVersion` 展示从 mock 自增版本(1,2,3…)变为 epoch 秒
|
||||
(如 1758520000)——纯展示差异,契约仍 int64。
|
||||
- 无 phone 上游行被跳过(warn 日志)——V1.1 账号=手机号下无法登录故不同步;
|
||||
数量可观时人工复核。
|
||||
- `RECONCILE_EVERY_N_RUNS` 周期对账对 http 源语义弱化(每批本就全量)——
|
||||
引擎机制保留不动,无害。
|
||||
- 飞书登录对接(union_id/open_id 议题,接口文档 §5)未做——后续可选线,
|
||||
YAGNI登记。
|
||||
Reference in New Issue
Block a user