完成40%
This commit is contained in:
+149
-11
@@ -1,9 +1,9 @@
|
||||
# 家谱项目全量治理实施计划
|
||||
|
||||
> **执行要求:** 实施时使用 `superpowers:executing-plans` 按任务顺序执行,并在每个批次结束后由主代理、Lagrange、Bernoulli 三人复核;宣称批次或阶段完成前必须使用 `superpowers:verification-before-completion`。步骤使用复选框跟踪。用户已明确授权三人依据证据直接确定技术方案,不再为可从页面、接口和现有合同推出的细节反复请示。
|
||||
> **执行要求:** 实施时使用 `superpowers:executing-plans` 按任务顺序执行,并在每个批次结束后由主代理和两位只读评审者三人复核;宣称批次或阶段完成前必须使用 `superpowers:verification-before-completion`。步骤使用复选框跟踪。用户已明确授权三人依据证据直接确定技术方案,不再为可从页面、接口和现有合同推出的细节反复请示。
|
||||
>
|
||||
> 日期:2026-07-22
|
||||
> 状态:阶段 0、导航任务 1—10、TAC 认证客户端任务 20—22、领域上下文任务 24 与 M07 反馈客户端任务 25 已完成;家谱工作区任务 26、M06 帮助任务 27、个人资料读取任务 28、通知读取任务 29、通知已读写入任务 30、个人资料写入任务 31、M10 服务端退出任务 32、M04 密码凭证任务 33、M05 手机号换绑任务 34 和 G03 原子创建任务 35 已完成三人审查及 OpenAPI 红灯;T01、认证、工作区、G03、帮助、profile、通知、logout、password 与 phone-change 后端门禁明确阻塞,MuMu 原生矩阵待执行;当前继续无依赖业务域接口审查
|
||||
> 状态:阶段 0、导航任务 1—10、TAC 认证客户端任务 20—22、领域上下文任务 24 与 M07 反馈客户端任务 25 已完成;任务 26—39 已逐域完成工作区、帮助、资料、通知、退出、密码、换绑、G03、普通加入、邀请码直入、G11 设置与 G12 字辈集合的三人审查及 OpenAPI 红灯;任务 40 正在审查 F01/F03 家族动态列表、详情与一级评论读取边界。这些后端门禁和 MuMu 原生矩阵仍明确阻塞,继续后续无依赖业务域接口审查
|
||||
|
||||
**目标:** 以测试先行方式消除全项目导航栈歧义,完成可安全上线的认证闭环,并在新后端图窗口合同通过后,把 T01 建成可稳定阅读几十代、几百代且连接线连续的大规模世系图;随后逐域关闭真实接口、领域持久化、无障碍与发布门禁。
|
||||
|
||||
@@ -1247,7 +1247,7 @@ T05 的真实更新必须在本步骤一次性拆分宿主页身份 A 与编辑
|
||||
|
||||
- [x] **步骤 1:短信登录、注册和找回密码测试先行接线**
|
||||
|
||||
A01 默认短信登录并以 `APP_SMS_LOGIN` 发码;A04/A05 分别使用 `APP_REGISTER/APP_FORGOT_PASSWORD`。三页当前均按“本地校验→require→TAC challenge/verify→携 `validToken` 发短信→4 位码提交”执行,手机号改变作废旧验证上下文,注册和重设提交不重复 TAC;任务 34 已把生产目标收紧为统一 6 位 `SmsCodeSecret`,后端、生成器、模板与全部消费者必须同版原子替换,当前代码不提前双读。A01 密码登录因 `API-AUTH-TAC-001` 保持可见但不可用;A04 成功保存 `AppLoginVo.access_token` 后直接 `goRoot("G01")`,不能先回 A01 再让用户重复登录;A05 成功使用同一 `AppDialog` 返回 A01。
|
||||
A01 默认密码登录,开发/联调链执行“本地校验→static TAC→线上密码登录 wire→保存 `AppLoginVo.access_token`→`goRoot("G01")`”;默认 mode 保持 mock。当前登录端点不接收/消费 `validToken`,因此客户端 TAC 只是测试前置,`API-AUTH-TAC-001` 继续阻止生产发布。A01 短信发码仍使用 `APP_SMS_LOGIN`,A04/A05 分别使用 `APP_REGISTER/APP_FORGOT_PASSWORD`;三页短信链按“本地校验→require→TAC challenge/verify→携 `validToken` 发短信→4 位码提交”执行,手机号改变作废旧上下文,注册和重设提交不重复 TAC。任务 34 已把生产目标收紧为统一 6 位 `SmsCodeSecret`,后端、生成器、模板与全部消费者必须同版原子替换,当前代码不提前双读。
|
||||
|
||||
- [x] **步骤 2:收紧认证传输生命周期**
|
||||
|
||||
@@ -1305,11 +1305,11 @@ M07 以提交前规范快照锁定请求,提交中禁用类型、内容、联
|
||||
|
||||
- [x] **步骤 2:先写失败合同并固定最小闭包**
|
||||
|
||||
`tests/genealogy-workspace-openapi-contract.ps1` 同时读取受保护 JSON/YAML,要求 `/mine → RListAppGenealogyVo`、`/overview → RAppGenealogyVo`,两层 envelope 的 `code/data` 必填,`data` 精确指向 `AppGenealogyVo`。首批消费字段固定为必填 `genealogyId/genealogyName/canView/canManage/canEditContent/roleType`:ID 和名称为非空字符串,三项 capability 为 boolean,角色是至少两个稳定非空值的 enum。测试当前输出 `GENEALOGY-WORKSPACE-OPENAPI-CONTRACT BLOCKED`;不得删除测试或手改双导出变绿。
|
||||
`tests/genealogy-workspace-openapi-contract.ps1` 先执行受保护 JSON/YAML 深比较,再要求唯一 `appListMyGenealogies/appGetGenealogyOverview`、GET-only/no-body、required SaToken/clientid、词法 `GenealogyId` path、`/mine → RListAppGenealogyVo`、`/overview → RAppGenealogyVo`。两个成功 envelope 精确关闭为 `{code,data}` 且 code=200,data 指向 `AppGenealogyVo`;首批消费字段固定为必填 `genealogyId/genealogyName/canView/canManage/canEditContent/roleType`,ID/名称引用共享 owner,三项 capability 为 boolean,角色是至少两个稳定非空值的 enum。响应使用 exact local component ref、固定 private/no-store 和 typed HTTP;测试当前输出 `GENEALOGY-WORKSPACE-OPENAPI-CONTRACT BLOCKED`,不得删除测试或手改双导出变绿。
|
||||
|
||||
- [ ] **步骤 3:后端关闭 `API-GENEALOGY-WORKSPACE-001`—`003`**
|
||||
|
||||
`001` 关闭 JSON int64 身份失真并补 typed required 闭包;`002` 让 `/mine` 以 required `canView` 或可自动证明的等价 active-only 投影成为当前账号可访问集合真相,并提供稳定角色/能力;`003` 让认证失效、对象无权/撤权、删除和服务异常在文档与部署中可稳定区分。错误可以使用规范 HTTP 状态,也可以继续 HTTP 200+业务码,但 JSON/YAML、运行时 validator 与有效 token 集成反例必须一致。后端必须从同一版本重新导出两份受保护源文件;本地不手工补 schema。
|
||||
`001` 关闭 JSON int64 身份失真并补 typed required 闭包;`002` 让 `/mine` 用 `x-current-account-viewable-only=true` 与 `OMIT_ONLY_AFTER_CONFIRMED_ACCESS_LOSS` 成为当前账号可访问集合真相,并提供稳定角色/能力;`003` 收口为 typed HTTP,不再允许 HTTP 200+业务错误。`/mine` 精确 200/401/429/500,overview 精确 200/400/401/404/429/500;400 为 `GENEALOGY_ID_INVALID`,对象无权/撤权/不存在统一 `NON_DISCLOSING_GENEALOGY_NOT_AVAILABLE`,每个响应只允许 JSON、固定 private/no-store,429 另带 Retry-After。后端必须从同一版本重新导出两份受保护源文件;本地不手工补 schema。
|
||||
|
||||
- [ ] **步骤 4:门禁通过后测试先行接入 G01/G05**
|
||||
|
||||
@@ -1317,7 +1317,7 @@ M07 以提交前规范快照锁定请求,提交中禁用类型、内容、联
|
||||
|
||||
- [ ] **步骤 5:真实账号与 MuMu 验收**
|
||||
|
||||
用至少两个有效账号验证本人列表、跨账号 ID、撤权、删除、401、403/404 或等价业务码、5xx、超时、畸形 JSON、快速切谱与离页取消;再在用户现有 MuMu 中验证加载/空/失败/失效/重选、G01 列表与切换弹层、G05 权限入口和 Android 返回。浏览器和静态合同均不能替代。
|
||||
用至少两个有效账号验证本人列表、跨账号 ID、撤权、删除、typed 400/401/404/429/500、超时、畸形 JSON、快速切谱与离页取消;再在用户现有 MuMu 中验证加载/空/失败/失效/重选、G01 列表与切换弹层、G05 权限入口和 Android 返回。浏览器和静态合同均不能替代。
|
||||
|
||||
### 任务 27:建立 M06 帮助内容远端硬门禁
|
||||
|
||||
@@ -1561,6 +1561,140 @@ G03 当前同页两步只写内存预览,第一步缺可信 regionCode,始
|
||||
|
||||
地区选择覆盖加载/搜索/无结果/失败/迟到/失效;输入具有 label、aria-invalid/describedby、首错聚焦,访问预设使用 radio,所有动作至少 44dp,弹层使用 AppDialog 焦点圈定/恢复,提交中冻结输入与返回并播报 PENDING/unknown/fatal/committed。后端在 control claim、quota、谱、OWNER、根、receipt、终态 CAS 每个写点做 fault injection,验证零残留、同 key 并发唯一、不同 body 409、跨账号/tenant/client status 非泄漏 404、截止前 404 不换 key、截止后 GET 纯计算 FAILED 且数据库零写、迟到 POST 永久拒绝、watchdog 后旧 worker 因 fencing 无法提交;另覆盖 collection/PUT/DELETE/parents 的根身份绕过,并证明根 PUT 仅 `name/sex/birthDate/biography` 四项可编辑、其余字段一律 422。MuMu 固定覆盖 320/360/412 宽度、系统字号、TalkBack、软键盘、日期、双击、慢网/断网/杀进程、Android 返回、context/导航失败;浏览器或源码检查不能代替原生结论。
|
||||
|
||||
### 任务 36:建立普通加入申请闭环远端硬门禁
|
||||
|
||||
- [x] **步骤 1:三人只读核对 G06/G08/G09/G10、双导出、线上部署与现有测试**
|
||||
|
||||
三人确认受保护快照和 2026-07-23 复核的当前线上部署都只有六条宽松 operation,缺少 request-status;身份仍为 int64,申请体含 phone/inviterUserId,mine/pending 共用泄漏 PII 的宽 VO,审核仍是数字 status/auditRemark,成功使用通用 List/Object/Void,匿名 GET 实际 HTTP 200+业务 401 又与文档 401 string 冲突。当前页面仍有 G10 手机号与三处消息中心承诺,但本批不改页面、不接宽松接口。
|
||||
|
||||
- [x] **步骤 2:三人交叉反驳并固定七个 operation、幂等与 CAS 方案**
|
||||
|
||||
七个稳定 operationId、三个专用 cursor page、词法 ID、mine 四状态 discriminator、pending 最小投影和审核两个闭合分支按设计 23.10 固定。普通申请与邀请码直入硬隔离;不引入 applicationVersion/If-Match/审核详情。requestKey 采用 `gja`+issuedAt+至少 128 位 CSPRNG,600/300/120 秒边界机器锁定;canonical scope 覆盖 method/path/genealogyId/tenant/account/client/body。申请+SUCCEEDED、成员+APPROVED 各自在同一业务事务提交,撤回/审核用 `status=PENDING` CAS;静态扩展只登记合同,数据库真实实现另由集成门禁证明。
|
||||
|
||||
- [x] **步骤 3:测试先行新增唯一失败门禁并移交旧 owner**
|
||||
|
||||
新增 `tests/join-application-openapi-contract.ps1`,先执行并取得精确 `JOIN-APPLICATION-OPENAPI-CONTRACT BLOCKED`。门禁先运行完整 JSON/YAML 深比较,再检查七个 method/path/operationId、精确参数、required SaToken/clientid、词法 ID、请求体、三个 cursor page、mine/status/mutation discriminator、无 PII schema 闭包、精确成功/错误 response ref、private/no-store、Retry-After 及机器扩展。parameter/response 组件只按 exact local 分区解析,缺 owner 直接失败;幂等、唯一 scope、事务、重验、状态迁移与 cursor 集合必须是真实 JSON 数组,不能用逗号字符串伪装。`g-series-openapi-contract.ps1` 与 `core-flow-contract.ps1` 同轮删除对旧 phone/inviterUserId、数字 status/auditRemark 的正向锁定;专项门禁成为 APP 加入合同唯一 owner。受保护 OpenAPI 未修改。
|
||||
|
||||
- [x] **步骤 4:写入 API-JOIN-001—006 与文档合同**
|
||||
|
||||
`001` 拥有七个 operation、稳定 cursor、词法身份与专用投影;`002` 拥有闭合申请体、JOIN_APPLICATION_TEXT_V1 和旧 schema 删除;`003` 拥有 requestKey、canonical identity、活动 PENDING 唯一约束、三态恢复、同事务 receipt 与零写 FAILED;`004` 拥有撤回 CAS/幂等;`005` 拥有审核分支、事务内权限重验、唯一成员与竞态;`006` 拥有 typed JSON、安全头、部署/数据库反例、客户端状态机和 MuMu 发布门槛。四份中文权威文档与 `current-documentation-contract.ps1` 必须同步,否则本步骤不完成。
|
||||
|
||||
- [ ] **步骤 5:后端关闭 `API-JOIN-001`—`006` 并同版本重导双文件**
|
||||
|
||||
后端须发布七个稳定 owner,删除旧 APP DTO/通用响应/PII 投影,完成 cursor、数据库唯一约束、request control record、fencing/watchdog、PENDING CAS、批准事务和非泄漏错误;以真实账号执行跨账号/tenant/client、同 key 跨谱、并发申请、撤回/审核/反向决定竞态、权限撤销、PUBLIC_APPLY 关闭、超时/5xx/畸形响应、DB fault injection、GET 零写、真实 HTTP/CORS 反例。只接受同版本重导 `APP.openapi.json/yaml`,禁止手改受保护文件。
|
||||
|
||||
- [ ] **步骤 6:门禁通过后测试先行实现客户端状态机与 MuMu 发布验收**
|
||||
|
||||
先写 request marker/status normalizer、cursor、mine/pending、withdraw/review 收敛的纯 Node 失败测试,再实现唯一 adapter/coordinator。POST unknown 查专用 status;撤回 unknown 刷新 mine 并可重放同一 DELETE;审核 unknown 刷新 pending,行消失只称状态变化。账号 epoch 隔离旧 marker,invite source 硬拒普通 POST。原子删除遗留 adapter、G10 手机号、消息中心承诺和 LOCAL_WITHDRAWN;补原生按钮、44dp、提交冻结、aria-invalid/describedby、首错聚焦与状态播报。MuMu 覆盖 320/360/412、1.3 倍字号、TalkBack、软键盘、返回、双击、慢网、断网、杀进程和长拒绝理由。
|
||||
|
||||
### 任务 37:建立邀请码签发与直接加入远端硬门禁
|
||||
|
||||
- [x] **步骤 1:三人只读核对 G06/G08/M08、双导出、当前线上部署与测试**
|
||||
|
||||
受保护双导出和 2026-07-23 复核的线上 OpenAPI 都没有家谱邀请码签发、解析、撤销或直接加入 operation;通用 promotions 和礼仪邀请不属于本域。G06 仍以 `JP2026` 和首个 fixture 假校验,G08 仍信任 `source=invite` 并复用普通申请资格,M08 正确保持不可用。本批不把页面接到不存在的接口。
|
||||
|
||||
- [x] **步骤 2:三方反驳并统一六 operation、G06 直兑和秘密恢复方案**
|
||||
|
||||
三方最终否决邀请码进入 G08:G08 的唯一 owner 收紧为任务 36 普通申请,邀请只在 G06 完成 resolve、可信目标展示、明确确认、redeem 与 status 收敛。首版固定单次、24 小时、至少 128 位随机量;列表/日志不返原码,签发 unknown 只以 marker 中原 genealogyId 和同一 `gii` key 重放无 body POST。600 秒只限制不存在 key 的首次认领;已存在 key 始终定位同一票据,窗内用隔离 KMS 密文恢复原码,窗后返回 metadata+秘密不可恢复且绝不新建,不设并行 issue-status owner。resolve 允许写一个短时 grant 摘要但不消费票据或产生领域写。兑换无姓名/关系 body,以敏感 redemption token+`gir` key 直接创建账号 MEMBER 关系,绝不创建申请或人物关系。
|
||||
|
||||
- [x] **步骤 3:测试先行新增唯一 OpenAPI 失败门禁**
|
||||
|
||||
新增 `tests/invite-ticket-openapi-contract.ps1` 并先取得精确 `INVITE-TICKET-OPENAPI-CONTRACT BLOCKED`。门禁先执行双导出深比较,再锁定六个 method/path/operationId、精确参数与响应、SaToken/clientid、票据/请求 key、单次 24 小时、KMS 幂等重放、仅允许短时 grant 安全写的 resolve、敏感 token、兑换事务、PENDING/SUCCEEDED/FAILED_NO_COMMIT、普通申请字段隔离和 URL/query 零秘密。受保护 OpenAPI 未修改。
|
||||
|
||||
- [x] **步骤 4:写入 `API-INVITE-001`—`006` 与中文权威文档**
|
||||
|
||||
设计 23.11、接口映射 2.15/5.14、总览断点与本实施任务同步记录六 owner、生命周期、签发/撤销、兑换事务、unknown 恢复、隐私限流、页面原子迁移和 MuMu 门槛;文档合同必须锁定这些事实,不能只靠自然语言承诺。
|
||||
|
||||
- [ ] **步骤 5:后端关闭问题单并同版本重导受保护双文件**
|
||||
|
||||
后端发布六个专用 owner、词法 ID、专用 projection/envelope/error,完成 HMAC 查找、KMS 幂等回执、活动票据上限、authorization epoch、单次消费/成员唯一约束、control record、fencing/watchdog 与非枚举限流。真实集成必须覆盖猜码、跨主体、两人同码、同人两码、撤销/兑换、权限降级、活动普通申请、每个事务写点 fault injection、GET 零写、日志零秘密和正式 HTTPS/CORS。只接受同版本重导 JSON/YAML,禁止手改保护文件。
|
||||
|
||||
- [ ] **步骤 6:门禁通过后测试先行原子迁移 M08/G06/G08**
|
||||
|
||||
先写 issue/revoke/resolve/redeem/status normalizer 与 coordinator 纯 Node 失败测试,再接唯一 API adapter。M08 只从 workspace 选谱;G06 删除 `JP2026`、fixture target 与 invite→G08,增加可信确认和 unknown 恢复;G08 原子删除全部 invite source/文案/返回分支,只保留普通申请。SUCCEEDED 必须按 receipt→刷新 `/mine`→安装 context→G01/G05 收口;context/导航失败只重试本地步骤。补原生按钮、44dp、tab/label/aria、首错聚焦、状态播报和 MuMu 完整矩阵。
|
||||
|
||||
### 任务 38:建立 G11 家谱设置版本化写入远端硬门禁
|
||||
|
||||
- [x] **步骤 1:三人只读核对 G11、workspace/G03 共享 owner、双导出、线上部署与现有测试**
|
||||
|
||||
G11 当前只从 fixture 读取,保存仅重置本页 baseline 并用 1800ms timer 显示本地成功;访问预设、保存和结果动作仍是 clickable view。受保护 `PUT /genealogy/app/genealogies/{genealogyId}` 使用宽 `GenealogyUpdateBody`、int64 path、通用 RObject 且只列 200;2026-07-23 线上同路径虽改名 `AppGenealogyUpdateBody → RAppGenealogyVo`,仍有 10 个宽字段、旧 `visibility/joinMode`、int64、无 closed/minProperties/version/If-Match/security/clientid,只有 200/401 与 `*/*`。单谱读取已由任务 26 选定 `/overview`,不能复活通用 GET。后端门禁前不修改页面或接宽松接口。
|
||||
|
||||
- [x] **步骤 2:三人交叉反驳并固定 merge PUT、统一版本与待审迁移方案**
|
||||
|
||||
保留现有 PUT,不新增 PATCH;它只做出现字段的原子 dirty-only merge,不是整资源替换。三方先比较强 ETag+412 与项目既有版本模型,最终统一沿用 T01/M02:`AppGenealogyVo.settingsVersion+required If-Match+typed 409`,不用第二套并发语义。名称统一 G03 的 24 code point,简介 80 且精确空串清空;成功和版本冲突 current 均复用 `AppGenealogyVo`,不新建重复 snapshot。409 精确 three-way oneOf;实际 `PUBLIC_APPLY→MEMBER_ONLY` 遇活动 PENDING 整笔拒绝并引导 G10,检查与申请准入串行化。
|
||||
|
||||
- [x] **步骤 3:测试先行新增唯一 OpenAPI 失败门禁并移交 owner**
|
||||
|
||||
新增 `tests/g11-settings-openapi-contract.ps1`,修复门禁自身集合错误并吸收两位评审的伪绿反例后取得稳定 `G11-SETTINGS-OPENAPI-CONTRACT BLOCKED`、`Issues: 48`。门禁先执行受保护 JSON/YAML 深比较并消费 workspace 唯一门禁结论,再递归锁全局唯一 PUT/operationId/设置 body owner:`/genealogy/app/genealogies...` 写 body 根层的 `intro` 被设置合同保留,任一单字段设置写、外部或错分区同名 `$ref`、generic GET/PATCH/旁路 settings 写都失败;workspace 对全部 APP GET 递归响应闭包并合并 allOf 属性,拒绝旁路详情。随后检查 exact local `$ref`、精确参数、SaToken/clientid、非 null `GenealogyName/GenealogyIntro/GenealogySettingsVersion`、名称控制字符与简介内部 LF、闭合 1—3 字段 body、If-Match/CAS、canonical 设置实际变化版本范围、冲突 precedence、纯 409 discriminator、typed envelope、required cache headers、固定 private/no-store 与 Retry-After。标量、引用、envelope、fieldErrors 与 role 枚举用 allowed-key 集拒绝 `nullable`、readOnly/writeOnly、冲突组合或额外验证关键字;附加 header 只允许 `traceparent/tracestate/x-request-id/x-correlation-id`,禁止 ETag 与其他语义 header;其 component 必须 exact local,内联 Header Object 必须 allowed-key 关闭并带非 null 的 string schema。任务 36 POST 同轮补 `ATOMIC_SINGLE_WINNER` 反向准入协调、纯 local ref/union 与真实 JSON 数组约束;任务 35 门禁只保留 bootstrap、纯 ref 的非 null 共享 accessPreset 与旧 DTO 删除,G-series 注释同步声明专项 owner。受保护双文件未修改。
|
||||
|
||||
- [x] **步骤 4:写入 `API-SETTINGS-001`—`006` 与机器化中文文档合同**
|
||||
|
||||
设计 23.12、映射 2.16/5.15、总览断点和本任务同步记录全局唯一 read/write、workspace typed HTTP 与旁路详情前置、共享文本/版本 owner、内部 LF/控制字符、dirty merge、canonical 设置实际变化、409 三分支、`ATOMIC_SINGLE_WINNER`、exact local ref、nullable/组合/readOnly/writeOnly 关闭、required 缓存 header、四种允许非语义 tracing header、禁止 ETag、unknown 对账、缓存/context、无障碍与 MuMu 激活条件。`current-documentation-contract.ps1` 和 `interface-page-mapping-contract.ps1` 必须锁定这些事实。三方同时统一:本批不新增无法执行生产 coordinator 的占位 client gate;后端绿后客户端第一项写操作才是实际执行生产模块的纯 Node 失败测试,禁止恒红或源码 token 假门禁。
|
||||
|
||||
- [ ] **步骤 5:后端关闭 `API-SETTINGS-001`—`006` 并同版本重导双文件**
|
||||
|
||||
后端发布全局唯一 `appUpdateGenealogySettings`,删除 generic GET、宽 update DTO、旧 pair 和任何旁路 owner,提供共享字段与 canonical `AppGenealogyVo`;实现当前主体/tenant/权限重验、只在三个 canonical 设置实际变化时更新的 settingsVersion CAS、READY 与待审迁移检查、原子 merge/no-op,以及设置 PUT/普通申请 POST 共同的 `ATOMIC_SINGLE_WINNER` 准入协调。真实集成覆盖单字段/多字段/清空/内部 LF/控制字符/no-op、旧版本、权限撤销、跨主体、活动 PENDING、设置与新申请竞态、每个事务写点 fault injection、500 unknown、正式 HTTP/CORS `If-Match`。只接受同版本重导 JSON/YAML,禁止手改保护文件。
|
||||
|
||||
- [ ] **步骤 6:门禁通过后先写可执行客户端失败测试,再原子迁移 G11**
|
||||
|
||||
第一项写操作必须新增直接执行生产 normalizer/coordinator 的纯 Node 失败测试,覆盖 24/80 Unicode、dirty/clear、If-Match、三个 409、三方比较、unknown 后 overview 对账、401/403/404、重复点击、取消/迟到响应、sessionEpoch、canonical 回填、缓存失效与 context 重验;不允许测试内嵌参考实现或只查函数名。随后实现唯一 adapter/coordinator,原子删除 fixture access、数字 pair、timer、本地成功分支和旧“禁止 appApi”断言。页面迁移到完整状态机、原生 button/radio、label/错误关联/首错聚焦、busy/live/44dp;最后通过 workspace/shared owner、聚焦/全量回归和 MuMu 原生矩阵。OpenAPI 绿只允许开始本步骤,不允许直接接线。
|
||||
|
||||
### 任务 39:建立 G12 字辈集合版本化保存远端硬门禁
|
||||
|
||||
- [x] **步骤 1:三人只读核对 G12、字辈共享 owner、受保护双导出与现有测试**
|
||||
|
||||
页面仍以 fixture、本地快照和 timer 表达未提交预览;受保护导出同时存在 collection POST、单行 PUT、batch preview/save 和 management 多入口,schema 又混用 `{poemText,disableMissing}`、状态 `0/1` 与宽响应,无法证明完整 ACTIVE 集合、稳定 ID、版本 CAS 或 unknown 恢复。三方确认后端门禁前不改页面、不接当前宽松接口,`runtimeConfig.mode` 保持 mock。
|
||||
|
||||
- [x] **步骤 2:交叉反驳并固定唯一 GET/PUT、完整候选与三方对账**
|
||||
|
||||
唯一 owner 固定为 `GET/PUT /genealogy/app/genealogies/{genealogyId}/generation-poems` 与 `appGetGenerationPoemSet/appUpdateGenerationPoemSet`;不引入 preview token/status。GET/PUT 共用 ACTIVE-only `GenerationPoemSetSnapshot`,PUT body 精确 `{items,disableMissing}`。generationNo 唯一排序、声明严格升序;false 保留遗漏 baseline、true 软停用,empty false no-op、empty true 清空 ACTIVE。服务端先校验声明严格升序,再构造声明目标与 merged candidate,随后验证唯一/slot/连续/最终容量、分配新 ID 并原子写;swap 显式声明全部受影响行。唯一并发为 `GenerationPoemSetVersion+If-Match+typed 409`,no-op 保持版本,语义变化版本永不复用;unknown 执行 effective target/old/current 三方比较且不自动 PUT。
|
||||
|
||||
- [x] **步骤 3:测试先行建立唯一 OpenAPI、对抗与 Unicode 门禁并完成 owner 移交**
|
||||
|
||||
新增 `tests/g12-generation-poem-openapi-contract.ps1`、`tests/g12-generation-poem-openapi-adversarial-contract.ps1` 与 `tests/g12-generation-poem-unicode-contract-runtime-smoke.js`。主门禁锁定唯一路径、全局 owner/ref 图、SaToken/clientid、typed HTTP、schema/版本/候选/unknown 与 `APP_GATEWAY_PREFLIGHT`;对抗合同以完整 zero issues seed 逐个验证多跳 ref、callback、HEAD/OPTIONS/TRACE、Reference Object、严格大小写 JSON Pointer、security 数组、schema type、候选顺序、CORS 与 annotation 非 owner;Unicode 冒烟覆盖 NFC、孤立 surrogate、控制/bidi/zero-width 和 50/51 个补充平面 code point。G-series 删除旧 G12 owner,只保留移交说明。已关闭评审复现的大小写假绿、非数组 security 和 example 误杀;当前主门禁保持 `BLOCKED Issues: 72`,对抗与 Unicode 均 PASS。
|
||||
|
||||
- [x] **步骤 4:写入 `API-POEM-001`—`006` 与机器化中文文档合同**
|
||||
|
||||
设计 23.13、映射 2.17/5.16、总览断点和本任务同步记录唯一 owner、ACTIVE-only 模型、complete candidate、disableMissing、软停用、版本 CAS、Unicode、typed HTTP、CORS owner、`FRESH_GET_THREE_WAY_NO_AUTO_PUT`、客户端原子迁移、无障碍与 MuMu 激活条件。`current-documentation-contract.ps1` 和 `interface-page-mapping-contract.ps1` 必须先红后绿,并锁定物理库存与当前发布红灯。
|
||||
|
||||
- [ ] **步骤 5:后端关闭 `API-POEM-001`—`006` 并同版本重导双文件**
|
||||
|
||||
后端删除旧五类旁路,发布唯一 GET/PUT、closed schemas、stable poemId、opaque version、软停用历史与真实权限/READY/CAS 事务;提供顶层 gateway policy 并在部署环境证明 OPTIONS/preflight。集成反例覆盖 0/1/500×50、重复文字、ID move/swap、遗漏策略、碰撞/非连续/超容量、no-op、旧版本、权限/READY 竞态、每个写点 fault injection、500 unknown、跨账号/tenant/client、缓存和日志。只接受同版本重导 JSON/YAML,不手改保护文件。
|
||||
|
||||
- [ ] **步骤 6:后端门禁绿后先写生产行为失败测试,再原子迁移 G12**
|
||||
|
||||
第一项客户端写操作必须直接执行生产 normalizer/coordinator,覆盖 Unicode、请求严格排序、effective target、If-Match、409/422、unknown 三方比较、sessionEpoch、取消/迟到响应、canonical 回填与缓存失效;禁止测试内参考实现或源码 token 假门禁。随后实现唯一 adapter/coordinator,并同轮删除 fixture/timer/本地成功、旧 preview/save 断言和兼容分支。页面补清空确认、saving/unknown/conflict、live region、焦点、44dp 与返回冻结;MuMu 完成宽度、字号、TalkBack、键盘、0/1/500×50、swap、慢网/断网/杀进程、权限撤销、READY 与账号切换矩阵。
|
||||
|
||||
### 任务 40:建立 F01/F03 家族动态读取远端硬门禁
|
||||
|
||||
- [x] **步骤 1:三人只读核对 F01/F03、fixture、受保护双导出、线上 OpenAPI 与现有测试**
|
||||
|
||||
F01 同步调用 `listFamilyFeedFixtures`,query.state 只切换视觉状态,失败重试只是再次读 fixture;F03 通过 `(genealogyId,feedId)` 深拷贝单条 fixture,comments 嵌在 feed 内,失败操作只恢复 ready,评论 timer 只生成明确未提交的本地预览。`utils/api.js` 虽有 dormant `getFeeds` 宽远端分支,但页面没有消费。受保护导出存在 feeds list/page 与 comments list/page 双 GET、无 operationId、int64、通用响应和开放评论模型;线上 3.1.0 仍无 required,评论 DTO 含手机号与内部审核字段。现有 fixture、F01/F03 业务/导航/视觉合同及 JSON/YAML parity 均通过,只证明当前本地预览安全,不证明生产接口可接。
|
||||
|
||||
- [x] **步骤 2:交叉反驳并固定谱内三 owner、最小投影与 cursor 窗口**
|
||||
|
||||
三方否决全局 feed 路由和 offset page,统一保留谱上下文 collection:`appListFamilyFeeds`、`appGetFamilyFeed`、`appListFamilyFeedRootComments`;删除两个 `/page` GET。Feed 最小 closed required 投影为 `{feedId,feedContent,authorDisplayName,publishedAt,hasMedia}`,评论为 `{commentId,commentContent,authorDisplayName,publishedAt}`;不凭 fixture 发明 title/tag,不返回 phone/user/status/audit。`hasMedia` 保证媒体动态不会被静默伪装成完整纯文字。两个列表用默认 20、1—50 的 opaque keyset cursor、无 total,排序分别为 publishedAt/feedId DESC 与 publishedAt/commentId ASC;窗口固定为 `UPPER_BOUND_KEYSET_LATEST_VISIBLE`,不冒充 MVCC snapshot。
|
||||
|
||||
- [x] **步骤 3:测试先行新增唯一 OpenAPI 失败门禁**
|
||||
|
||||
第一项本批写操作新增 `tests/family-feed-read-openapi-contract.ps1`,取得精确 `FAMILY-FEED-READ-OPENAPI-CONTRACT BLOCKED`、`Issues: 85`。门禁先验证受保护 JSON/YAML parity,再锁三个全局唯一 operationId、两个旧 `/page` GET 删除、精确参数、SaToken/clientid、词法 ID、closed projection、正文/作者/时间/媒体存在性、两个 cursor page、逐页鉴权、非泄露 404、typed 200/400/401/404/429/500、application/json、private/no-store、Retry-After、CORS owner 与成功 schema 无 PII/审核字段。受保护双文件、runtimeConfig 和页面均未修改。
|
||||
|
||||
- [x] **步骤 4:写入 `API-FEED-READ-001`—`006` 与机器化中文文档合同**
|
||||
|
||||
设计 23.14、映射 2.18/5.17、总览断点和本任务同步记录三 owner、词法身份、最小 projection、`hasMedia`、正常一级评论、cursor scope/order/window、每页 fresh 权限、non-disclosing 404、typed HTTP、部署 CORS、后端/客户端激活顺序、无障碍与 MuMu。`current-documentation-contract.ps1` 和 `interface-page-mapping-contract.ps1` 先红后绿;基线登记新增发布红灯,不能把旧双导出内部 parity 或线上宽 DTO 冒充接口通过。
|
||||
|
||||
- [ ] **步骤 5:用 zero issues 种子、对抗反例和两位评审关闭门禁自身风险**
|
||||
|
||||
`tests/family-feed-read-openapi-adversarial-contract.ps1` 已让完整合法种子返回 zero issues,并以 58 个独立变异拒绝旧 owner、外部/多跳 ref、大小写 Path Item/security/schema、HEAD/OPTIONS/callback 旁路、duplicate operationId、int64、开放 DTO、PII/审核字段、offset/total、cursor 跨作用域、403 资源分流、wildcard 和缺失 cache header,当前输出 `FAMILY-FEED-READ-OPENAPI-ADVERSARIAL-CONTRACT PASS MUTANTS=58`。两位评审仍须分别实跑主红灯与对抗套件,主代理只在两方都无 P0/P1 后标记完成。
|
||||
|
||||
- [ ] **步骤 6:后端关闭 `API-FEED-READ-001`—`006` 并提供同版本三份证据**
|
||||
|
||||
后端删除两个旧 `/page` GET 和通用/开放/PII 投影,发布三个稳定 operation、词法 ID、closed typed schemas 与 cursor。真实实现逐页重验 tenant/genealogy/membership/feed ownership/visibility,cursor 绑定 actor/session/client/scope/order/window 并验证完整性和过期;覆盖并发新增、删除、编辑、审核隐藏、权限撤销、错谱/跨账号/跨 feed 重放和 400/404 非泄露。只接受同一部署版本重导的 JSON/YAML 与 live `/v3/api-docs`,并以真实账号、正式 HTTP/CORS/OPTIONS 证明,不手改受保护文件。
|
||||
|
||||
- [ ] **步骤 7:门禁绿后先写生产读取失败测试,再原子迁移 F01/F03**
|
||||
|
||||
第一项客户端写操作必须新增直接执行生产 read normalizer/coordinator 的纯 Node 失败测试,覆盖 exact schema、词法 ID、cursor、loading/refresh/load-more/end、详情与评论局部失败、401/404/429/500、畸形 2xx、离页取消、sessionEpoch、切谱/切账号迟到响应、权限撤销、`hasMedia` 诚实占位和缓存键。随后一次性替换 F01/F03,删除 feed 内嵌 comments、fixture 读取锁、伪重试和旧“必须 fixture”断言;远端失败不得回退 fixture。补原生 button、44dp、live region、焦点/滚动恢复、长文/换行及 MuMu 320/360/412、字号、TalkBack、键盘、慢网/断网/返回矩阵。评论写 timer 仍只属于后续独立写批,不得混入读取成功。
|
||||
|
||||
## 后续独立阶段边界
|
||||
|
||||
T01、认证、家谱工作区、M06、个人资料读写、通知、服务端退出和密码凭证当前都被外部合同红灯阻塞,不在本地空等。其余阶段仍逐个重新执行三人只读审查、方案比较、失败测试和最小实施;不得把两个业务域混入同一批:
|
||||
@@ -1574,16 +1708,20 @@ T01、认证、家谱工作区、M06、个人资料读写、通知、服务端
|
||||
7. M04 密码凭证:任务 33 已建立 raw wire、15—64 策略、ALL 会话撤销与崩溃 marker 红灯;必须与登录/注册/找回同批迁移,M04 不单页双轨。
|
||||
8. M05 手机号换绑:任务 34 已建立专用受保护发码、全活动六位 OTP、currentPassword、ALL 会话撤销与旧号 outbox 红灯;必须等认证/M04/profile 前置合同共同通过后原子实施。
|
||||
9. G03 原子创建:任务 35 已建立 atomic bootstrap、无 PII operation-status、统一 accessPreset、可信地区和词法 ID 红灯;必须等本门禁与工作区读取门禁通过后再实现 context/G05/G01 完整回流。
|
||||
10. G、F、R、N/M 其余真实接口:逐页核对页面、业务闭环与线上/双导出三方,缺失合同先形成后端问题单;当前从 G/F/R 选择不依赖既有红灯的下一域。
|
||||
11. 全局文字层级与无障碍第二轮:字号层级、系统字号放大、焦点顺序、读屏语义、对比度和 44dp 触控目标。
|
||||
12. 发布收口:真实环境配置、隐私与权限声明、错误观测、构建签名、升级/回滚、MuMu 全流程回归和三人终审。
|
||||
10. 普通加入与邀请码直入:任务 36/37 已分别建立专项红灯并三人终审;后端关闭后仍须先写可执行客户端状态机测试,再原子迁移页面,两个域始终隔离。
|
||||
11. G11 设置:任务 38 已建立 merge PUT、版本 CAS、待审串行化与 unknown 红灯;后端绿后第一写才建立实际生产 coordinator 行为测试,不复制 G03 空壳门禁。
|
||||
12. G12 字辈集合:任务 39 已固定唯一 GET/PUT、完整候选、版本 CAS、unknown 与 CORS owner;完成门禁/文档/三人终审后等待 API-POEM,同样禁止提前接页。
|
||||
13. F01/F03 家族动态读取:任务 40 已固定谱内三个 cursor GET、无 PII 最小 projection、逐页鉴权与非泄露 404;完成对抗门禁和双评审后等待 API-FEED-READ,后端绿前不接 dormant 宽接口。
|
||||
14. G、F、R、N/M 其余真实接口:继续逐页核对页面、业务闭环与线上/双导出三方,缺失合同先形成后端问题单;从下一个独立业务域继续。
|
||||
15. 全局文字层级与无障碍第二轮:字号层级、系统字号放大、焦点顺序、读屏语义、对比度和 44dp 触控目标。
|
||||
16. 发布收口:真实环境配置、隐私与权限声明、错误观测、构建签名、升级/回滚、MuMu 全流程回归和三人终审。
|
||||
|
||||
不得在同一实现批次混合以上阶段,也不得借后续阶段返工已经通过且无回归证据的响应式页面。
|
||||
|
||||
## 当前计划完成条件
|
||||
|
||||
- 阶段 0 的五份权威中文文档仍是唯一长期入口,没有新建旧版、备份或平行计划。
|
||||
- 导航、T01、认证/TAC、家谱工作区、G03 原子创建、M06 帮助、个人资料读写、通知读写、M10 服务端退出、M04 密码凭证与 M05 手机号换绑的所有者、旧路径删除条件、测试、MuMu 矩阵和后端接口缺口均已精确写明。
|
||||
- 导航、T01、认证/TAC、家谱工作区、G03 原子创建、普通加入、邀请码直入、G11 设置、G12 字辈集合、F01/F03 家族动态读取、M06 帮助、个人资料读写、通知读写、M10 服务端退出、M04 密码凭证与 M05 手机号换绑的所有者、旧路径删除条件、测试、MuMu 矩阵和后端接口缺口均已精确写明。
|
||||
- 导航任务 1—10 已按测试先行完成两个共享所有者、共享组件、退役入口、认证、G、T、F、R、N/M 系列静态迁移与零债务门禁;没有手工改写 OpenAPI 导出,MuMu 原生矩阵仍按明确边界待执行。
|
||||
- 三人对业务正确性、全局一致性、回归风险、维护成本和 MuMu 可验证性形成一致结论。
|
||||
- T01、认证、家谱工作区、G03 原子创建、M06 帮助、个人资料读写、通知读写、M10 服务端退出、M04 密码凭证与 M05 手机号换绑 OpenAPI 门禁已经建立并取得预期红灯;TAC 客户端任务 20—22 已完成,任务 23 等待后端合同与 MuMu 原生证据。领域上下文任务 24、M07 客户端任务 25、工作区任务 26、M06 任务 27、profile 读取任务 28、通知任务 29/30、profile 写入任务 31、logout 任务 32、password 任务 33、phone 任务 34 与 G03 任务 35 已完成各自可本地完成的部分;等待后端期间转向 G/F/R 下一域,不把两个阶段混在同一变更中。
|
||||
- T01、认证、家谱工作区、G03 原子创建、普通加入、邀请码直入、G11 设置、G12 字辈集合、F01/F03 家族动态读取、M06 帮助、个人资料读写、通知读写、M10 服务端退出、M04 密码凭证与 M05 手机号换绑 OpenAPI 门禁均须取得预期红灯;TAC 客户端任务 20—22 已完成,任务 23 等待后端合同与 MuMu 原生证据。领域上下文任务 24、M07 客户端任务 25、工作区任务 26、M06 任务 27、profile 读取任务 28、通知任务 29/30、profile 写入任务 31、logout 任务 32、password 任务 33、phone 任务 34、G03 任务 35、加入任务 36、邀请任务 37、G11 任务 38 与 G12 任务 39 已完成各自可本地完成的部分;任务 40 完成对抗门禁和三人终审后立即转向下一个独立业务域,不把两个阶段混在同一变更中。
|
||||
|
||||
Reference in New Issue
Block a user