Files
jiapuapp/docs/项目当前总览.md
T
2026-07-23 08:24:07 +08:00

60 KiB
Raw Blame History

项目当前总览

当前阶段:导航任务 1—10、TAC 认证客户端、领域上下文基础与 M07 反馈客户端已经完成;T01、认证、家谱工作区、G03 原子创建、M06 帮助、个人资料读写、通知读写、M10 服务端退出、M04 登录态改密和 M05 手机号换绑后端接口门禁均为红灯,继续逐域关闭真实接口 当前状态:A01/A04/A05 已接入统一 TAC、真实短信和认证请求代码,M07 已接真实反馈提交 ownerG01/G05、G03、M06、M01/M02/M03 个人资料读写、N01/N02/M01/G01 通知域、M10 退出域、M04 密码凭证域与 M05 换绑域已完成三人接口审查和失败门禁,均未猜测接线;runtimeConfig.mode 仍为 mock,MuMu 原生矩阵和真实环境联调待执行 当前基准 HEAD:9b0ad62df467f4e2c58b7689087683c77755e07bmain,工作区有本轮未提交变更) 更新日期:2026-07-23

2026-07-23 换机续作断点

总目标与完成定义

本项目的总目标不可缩减为“只写规划”或“只让静态测试通过”:必须在 main 工作区内持续推进整个 UniApp 家谱项目,按测试先行和三人交叉评审完成导航、T01 长世代世系树、TAC/认证、家谱领域数据、G/T/F/R/N/M 全量页面与接口、异常恢复、无障碍、构建及上线验证,最终交付能够正常上线使用的项目。若本地可完成的工作全部完成后只剩后端合同重导、有效测试账号、应用签名、发布凭证或 MuMu 人工操作等外部状态,才允许停在明确硬阻塞;每项阻塞必须有失败门禁、复现证据、唯一所有者、解除条件和继续步骤,不能用 mock、fixture、定时器或宽松兼容伪装完成。

协作固定为当前主代理加两位评审者,共三人。三人都必须独立检查接口/字段、页面/业务闭环、交互/异常/视觉,再交叉质询并统一结论;主代理是唯一写入者,不再创建旧专家身份或增加并发评审者。普通技术取舍由三人自行收敛,不反复交给用户。系统保存的目标记录仍存在,但在 2026-07-23 读取时状态为 paused;换机后的执行者不得据此把任务视为取消,应以上述总目标和本节断点继续。只有项目真实达到完成定义时才能标记完成。

仓库与保护基线

  • 当前分支为 mainHEAD 为 9b0ad62df467f4e2c58b7689087683c77755e07b,上游显示 main...origin/main。工作区含大量本轮未提交的修改、删除和新增文件,均属于当前连续治理成果;换机后先运行 git status -sbgit rev-parse HEAD 核对,禁止用 restore/checkout/reset 清理,也禁止自行改分支或 worktree。
  • 本节仅记录断点,没有执行 git add/commit/push。由用户自行上传;换机后必须保留当前完整工作区,而不能只依赖旧远端基线。
  • 后端唯一目标地址是 https://backend-api.ddxcjp.cn/。受保护 APP.openapi.yaml 的 SHA-256 为 8964CD583CE172425B63BBFD802F7EB587EB3641EADFD6F9D3B264FAA8090C6CAPP.openapi.json87DB1DC148C5E6E877815AFF7B3A7FC7C7ECA95A2CEC50A88B42F3908961F31A;两文件相对 HEAD 无差异。不得修改、格式化、覆盖或删除,只接受后端同一版本重新导出的双文件。
  • 不得启动、关闭或调整 MuMu。浏览器截图和源码检查不能冒充 Android 原生视觉、TalkBack、系统字号、软键盘或返回键验收。
  • 当前物理测试库存仍是 PowerShell 140、Node 47。最近一次完整记录为 PowerShell 126/140,14 项均是预期发布红灯;Node 语法 47/47、纯 Node 19/19、活动 Vue 脚本 64/64 通过。G03 最后一次布尔类型加固后又单独通过聚焦合同;换机后应先重跑完整套件,不能把这些历史数字冒充新机器证据。

已完成到哪里

导航任务 1—10、统一 TAC 客户端、领域上下文基础和 M07 真实反馈客户端已经完成本地可完成部分。T01、认证/TAC、家谱工作区、M06、个人资料读写、通知读写、退出、密码、手机号换绑均已经三人审查并建立明确 OpenAPI 红灯。任务 35 已完成 G03 原子创建合同:否决空谱加通用人物的两写方案,固定一次 atomic bootstrap、无 PII operation-status、统一 accessPreset、可信地区、词法 ID、始祖不变量及客户端激活门禁;openapi-yaml-json-parity-runtime-smoke.js 已升级为严格 YAML mapping 和任意精度数字的完整双源深比较。尚未批量把这些红灯域接到宽松线上接口,runtimeConfig.mode 仍诚实保持 mock

当前精确断点:任务 36 普通加入申请闭环

三人已经完成 G06/G08/G09/G10 与 2026-07-22 线上 OpenAPI 的只读核对,范围只包括“鉴权搜索公开可申请家谱 → 普通申请 → 我的申请/撤回 → 待审列表/单条审核”。邀请码校验和直接加入仍是后续独立任务,产品结论保持“邀请码成功后直接加入且不生成审核记录”,不得混入普通审核合同。

已统一的最小正确方案如下:

  • 搜索、我的申请和待审列表使用各自专用最小投影与稳定 cursor 分页,不返回 total,所有 genealogyId/applyId 都是有界词法字符串。搜索项只暴露识别家谱所需字段和当前查看者状态;我的申请完整表达 PENDING/APPROVED/REJECTED/WITHDRAWN;待审项只含 applyId/applicantName/relationDesc/applyReason?/submittedAt,不得泄漏手机号、用户 ID、邀请人或审核人内部字段。
  • 申请 body 闭合为 applicantName/relationDesc/applyReason?,前两项必填;删除 phone/inviterUserId。同账号、租户、家谱最多一个活动 PENDING,由数据库唯一约束而非先查后插保证。
  • 申请 POST 必须带无 PII 的 Idempotency-Key。同 key、同 canonical body 重放同一结果;同 key、不同 body 返回 409。客户端只持久 {sessionEpoch,requestKey,startedAt},不持久姓名、关系和理由。
  • 冷启动恢复不复用 mine 查询,也不持久表单 PII;新增唯一只读 owner GET /genealogy/app/genealogies/join-apply-requests/{requestKey},以显式 discriminator 返回 PENDING {resolveBy,retryAfterSeconds}SUCCEEDED {applyId/genealogyId/...无 PII 回执}FAILED_NO_COMMIT。只允许 ABSENT→PENDING→SUCCEEDED/FAILED_NO_COMMIT,两个终态不可变;GET 纯读,跨账号/租户/client 统一非泄漏 404,PENDING 必须有收敛期限,从未到达的 key 也必须在可计算时间边界后成为零写 FAILED_NO_COMMIT
  • 不引入 applicationVersionIf-Match 或审核详情端点。申请在 PENDING 时不可编辑,撤回、通过和拒绝都以 WHERE status=PENDING 的数据库 CAS 决定唯一赢家。重复相同撤回返回同一 200;重复相同审核决定返回原 200,拒绝时只有规范化后理由相同才算相同动作;相反决定、不同拒绝理由或撤回/审核竞态败方返回 typed 409 和当前最小状态。终态不可改,重新申请创建新 applyId
  • 审核 body 只允许 APPROVE,或 REJECT+必填申请人可见 rejectionReason。批准必须在同一事务完成唯一成员关系和申请终态;G05 的 canReviewJoinApplications 只是入口 capability,服务端在事务/CAS 时仍重新验证权限、家谱状态和 PUBLIC_APPLY
  • 所有操作 required SaToken 和非空 clientid,仅使用 application/jsonCache-Control: private, no-store429 带 Retry-After。线上三个匿名 GET 当前实测为 HTTP 200 加业务 code=401,却与文档 HTTP 401 string 冲突;发布合同必须统一为真实 HTTP 状态与 typed JSON,禁止 */*、200 包装认证错误、default 响应和 int64 JSON 身份。
  • 客户端结果未知时禁止乐观改列表:申请查专用 operation;撤回刷新 mine 并可安全重放同一 DELETE;审核刷新 pending,行消失只能说“状态已变化/已被处理”,不能冒充本次审核成功。首版不承诺消息中心通知;G09 的 onShow 与手动刷新是当前业务真相。

尚未实施的边界必须原样保留: tests/join-application-openapi-contract.ps1 还没有创建,任务 36 尚未写入实施计划和接口映射,测试计数仍为 140/47G06/G08/G09/G10 业务代码也没有在本任务中修改。换机后的第一项写操作应是用 apply_patch 新增该 OpenAPI 失败门禁,先运行并取得精确 JOIN-APPLICATION-OPENAPI-CONTRACT BLOCKED,再把 API-JOIN-001006、七个 operation、状态机、隐私投影、竞态和部署反例同步写入现有四份中文权威文档及文档合同。后端门禁通过前页面继续保持诚实本地预览,不写只适配当前宽松线上模型的临时代码。

完成任务 36 的本地门禁、全量回归和三人终审后,继续按独立批次推进邀请码直入、G11 设置写入、G12 字辈真实保存,以及其余 G/T/F/R/N/M 业务域;不得一次混合导航、验证码、领域持久化和无障碍多个阶段。最终仍须完成真实后端联调、构建、签名/隐私配置、MuMu 全流程矩阵和发布终审。

当前目标

阶段 0 的清理和验证基线已经完成。当前主代理与两位固定评审者已完成导航任务 1—10,建立路由注册表、导航网关和零债务门禁,并迁移共享组件与认证、G、T、F、R、N/M 全部活动页面。T01、认证/TAC、G01/G05 家谱工作区、G03 原子创建、M06 帮助、M01/M02/M03 个人资料读取、M02 个人资料写入、N01/N02/M01/G01 通知读写、M10 当前设备退出、M04/全认证密码凭证及 M05 手机号换绑的规范 OpenAPI 合同都已测试先行落地;TAC 客户端批次已经完成,A01 短信登录、A04 注册和 A05 忘记密码当前共用严格验证组件、服务端 validToken、4 位短信码与可取消请求,但生产 OTP 目标已收紧为统一 6 位,须等待后端同版原子迁移后再替换客户端,禁止 4/6 双接受。领域基础已把会话与当前家谱 ID 收紧为词法字符串:账号切换和损坏存储清理上下文;给定新列表发现历史 ID 消失或显式目标无权时写入持久失效标记,跨重载也禁止静默切谱;T01 也会在写入路由家谱前拒绝已有失效标记和无访问权限的夹具。M07 已按 POST /genealogy/app/feedback 接入严格真实提交,mock 模式固定返回 WRITE_UNAVAILABLE,不再伪造成功。后端认证门禁未关闭前保持 mock;其余尚未接真实写接口的页面仍是明确本地预览或硬关闭。

当前权威资料

  • 治理设计:docs/家谱项目全量治理设计.md
  • 当前实施计划:docs/家谱项目全量治理实施计划.md
  • 视觉资产与构建:docs/视觉资产与构建基线.md
  • 页面、流程与接口关系:docs/接口与页面映射总表.md
  • 接口导出:APP.openapi.jsonAPP.openapi.yaml
  • schema v3 视觉资产注册表:design-pipeline/manifests/runtime-assets.json
  • 九宫格所有者:styles/adaptive-frame-profiles.scss
  • 当前预览密码策略所有者:utils/validation.js;生产目标 wire/policy owner 等待 API-PASSWORD-001005 关闭后原子替换,禁止单页双轨。
  • 响应式覆盖:tests/responsive-layout-coverage.json
  • 固定尺寸例外:tests/responsive-layout-allowlist.json
  • 活动路由:pages.json;项目固定使用 Vue 3uni.scss 是 Sass 设计令牌唯一入口。

阶段 0 的临时清理清单已在长期结论迁入当前唯一所有者后删除。旧设计记录、规格、计划、交接和 H5/静态设计图中的有效事实已经迁移,旧文件已删除,不再存在并行入口。

接口文档所有权

后端维护的 Apifox 项目是接口合同的唯一编辑源。APP.openapi.json 用于离线自动扫描和测试,APP.openapi.yaml 用于人工阅读与跨工具导入;两份文件都只接受来自同一后端版本的重新导出,不得分别手工维护。部署地址的 /v3/api-docs 只作为当前线上实现证据,发现差异时必须推动同版本双导出更新,不能反向覆盖受保护文件。

当前 JSON 文档为 OpenAPI 3.0.1,包含 112 条路径、153 个操作和 72 个模型。tests/openapi-yaml-json-parity-runtime-smoke.js 已使用无第三方依赖、无损任意精度数字且严格校验 mapping 分隔符的结构化解析器深比较完整 JSON/YAML;相邻不安全大整数差一反例已先红后绿,当前两份受保护快照语义一致。后端今后必须同版本双导出,任何单边漂移都会在领域合同前失败。

后端在 2026-07-22 新提供 https://backend-api.ddxcjp.cn/。同日 21:52Asia/Shanghai)只读获取其 /v3/api-docs,线上为 OpenAPI 3.1.0722 条路径、858 个操作和 507 个模型;本地 112 条路径中有 109 条仍在线,/genealogy/app/files/reference/genealogy/app/files/upload/genealogy/pc/files/upload 三条不在当前线上文档,线上另有 613 条路径。线上模型已把部分 Genealogy*Body 重命名为 AppGenealogy*BodyGenerationPoemBatchBody 也新增了由路径写入的 genealogyId 字段,因此本地双导出是明确的旧快照,不能再代表当前部署的完整合同。utils/config.js 的唯一 baseUrl 已更新为无尾斜杠的 HTTPS 地址;mode 仍保持 mock,在页面接口和安全合同逐批闭合前不得提前切换远端。

线上文档已经提供 /captcha/require/captcha/challenge/captcha/verify:挑战与校验绑定 tenantId/clientId/sceneCode/subject,校验成功响应可返回 validToken,而发送短信的 AppSmsCodeBody 已把 validToken 列为必填。客户端已按 APP_SMS_LOGIN/APP_REGISTER/APP_FORGOT_PASSWORD 三个精确场景实现“查询要求→取得挑战→供应商完成→服务端校验→携票发送短信”,注册和找回提交不重复执行 TAC;认证请求只接受 HTTP 200 的严格 JSON envelope,统一 15 秒超时,离页或返回会中止当前 RequestTask。密码登录体尚无 validToken,因此 A01 以短信登录为默认且密码登录入口保持不可用,绝不以客户端先滑动冒充服务端强制校验。

认证后端门禁仍有四组问题:API-AUTH-TAC-001 要求密码登录加入服务端可消费的同语义票据;API-AUTH-TAC-002 记录线上 /captcha/challengeAPP_REGISTER 实测返回 HTTP 500 且空响应;API-AUTH-TAC-003 要求验证请求以 provider discriminator/oneOf 严格关闭根对象和各 payload 的额外字段,并补齐必填 providerCode/captchaType/payloadAPI-AUTH-TAC-004 要求同一验证中心返回服务端绑定的 verification session、可验证方法和同一类短时单次 validTokenrequired=false 也必须直接签发可供短信接口消费的票据,不得形成无障碍绕过。tests/auth-tac-openapi-contract.ps1 当前输出 AUTH-TAC-OPENAPI-CONTRACT BLOCKED。密码登录、短信登录和注册的线上成功响应已统一为 RAppLoginVo → AppLoginVo.access_token,客户端旧令牌字段读取已删除。线上文档自身仍发布 http://backend-api.ddxcjp.cn server URL,与已验证可用的 HTTPS 地址不一致;客户端只能使用显式 HTTPS,后端还需修正文档 server 声明。对 http://localhost:5173 的预检已返回允许 content-type/clientid,这不能替代正式 H5 域名的 CORS 验证。

家谱工作区只读审查已固定 /genealogy/app/genealogies/mine 为可访问集合 owner、/genealogy/app/genealogies/{genealogyId}/overview 为 G05 唯一详情 owner;首批不同时请求语义重复的 /{genealogyId}。线上 AppGenealogyVo.genealogyId 仍是 JSON integer/int64,最大合法值进入 JavaScript 后会不可逆失真;三个相关模型均无 required,也没有必填 canViewroleType 无枚举。无令牌实测三条读取均返回 HTTP 200、application/json;charset=UTF-8{code:401,msg,data:null},但文档只列 200/401 且 401 为字符串,尚不能稳定区分登录失效、对象无权、已删除和服务故障。问题单 API-GENEALOGY-WORKSPACE-001003tests/genealogy-workspace-openapi-contract.ps1 已建立;同版本双导出通过前不写 G01/G05 专属 adapter,不用本地字段猜测替代服务端 owner。

M06 三人审查选择 GET /genealogy/app/help-articles 的完整列表作为唯一远端 owner;线上列表模型已经包含 helpContent,因此页面不调用详情端点、不消费 helpId,也不让 JSON int64 进入页面模型。每次响应只允许显式投影 helpCategory/helpTitle/helpContent,分类从当前列表动态派生,展开键只在当前响应生命周期内使用并在搜索、分类、刷新前清空。当前受保护双导出仍返回通用 ListResult/RList,线上 RListHelpArticleVo/HelpArticleVo 又没有 required,正文格式、仅发布内容、展示顺序和认证失败承载也未形成一致合同;匿名实测列表与详情均为 HTTP 200+业务 code=401,而线上文档声明 HTTP 401 string。问题单 API-M06-001003tests/help-center-openapi-contract.ps1 已建立;门禁通过前保留明确本地 FAQ,不写 live-only adapter。

个人资料读取三人审查固定 GET /genealogy/app/auth/profile 为 M01/M02/M03 共用的唯一接口 owner。首批只要求 canonical 11 位 phone 必填;nickName/realName/email 未设置时唯一省略,出现时必须是非空规范字符串,姓名最多 30、邮箱格式有效且最多 100。adapter 立即把明文手机号变为掩码和读屏标签,只输出固定页面模型;userId/avatar/status 等字段全部丢弃,因此它们的 int64/枚举不阻塞本批。受保护双导出仍是通用 ObjectResult/RObject,线上 RAppProfileVo/AppProfileVo 则无 required 和字段边界;匿名实测仍是 HTTP 200+业务 401,与文档 401 string 冲突。问题单 API-PROFILE-READ-001003tests/profile-openapi-contract.ps1 已建立;门禁通过前不把 live-only 字段接进页面。

通知三人审查把读取与写入拆成两个原子批次。读取唯一使用 GET /genealogy/app/notificationsGET /genealogy/app/notifications/unread-count:列表必须完整返回当前账号最多 200 条活动通知并按最新优先,未读数精确统计同一集合;页面只消费完整纯文本标题/正文、带时区时间和 READ/UNREAD,所有服务端 ID、发送者与业务目标都不进入公开页面模型。N02 没有详情接口,首批只能以当前内存 generationordinalsnapshotKey 打开完整快照,重启、账号切换或成功刷新后的旧 key 均提示返回消息中心重新打开。已读写入另由两个 POST 持有,要求无损字符串 notificationId、当前账号幂等、read-all 截止点和并发新消息语义;通过前删除伪本地已读而不发请求。当前受保护双导出的列表仍是通用模型且没有未读数路径,线上模型无 required/枚举/容量,所有 ID 仍为 int64,匿名实测又是 HTTP 200+业务 401。问题单 API-NOTIFICATION-READ-001003API-NOTIFICATION-STATE-001003 以及两项失败合同已经建立,均不以猜测代码绕过。

M02 资料写入三人审查保留现有 PUT /genealogy/app/auth/profile 作为唯一 App owner,但要求后端把它正式定义为原子 dirty-only merge,而非全资源替换或依赖 DTO 惯例猜测。请求只允许脏的 nickName/realName/email:省略保持,昵称出现时必须非空,真实姓名/邮箱的精确空串表示清空,null、纯空白和边界空白非法;成功返回完整 canonical RAppProfileVo,清空后的可选字段仍省略。并发沿用 T01 的单一版本模型:AppProfileVo.profileVersion 是 opaque stringPUT 必带同形状 If-Match,旧版本返回 409 PROFILE_VERSION_CHANGEDH5 CORS 同步允许该 header。受保护双导出还是旧 ProfileUpdateBody → RObject,线上则是无 required/merge/version/security 的 AppProfileUpdateBody → RAppProfileVo;当前页面还把同一 fixture 名称同时填入昵称和真实姓名,并用 500ms 定时器伪造本地校验。问题单 API-PROFILE-UPDATE-001004tests/profile-update-openapi-contract.ps1 已建立;GET 门禁和本门禁通过前不接写入。

M10 退出三人审查固定 DELETE /genealogy/app/auth/logout 只撤销请求中 bearer 所属的当前设备凭证族;同账号其他设备保持登录,“全部设备退出”必须另立接口。活动、已撤销和已过期但仍可验证为本 client 签发的历史凭证重复 DELETE 都返回同一个 200 RVoid,且成功后旧 token 对任何受保护接口均不可用;伪造、格式非法或 client 不匹配才返回 typed 401 拒绝。客户端唯一 logoutCoordinator 在同一同步临界段捕获 A 的 token/clientid、清本地 token/家谱上下文并 bump epoch、用显式快照创建不绑定 M10 生命周期的请求,然后立即 goRoot(A01);异步回调永不再次 clear,避免误删随后登录的 B。线上 endpoint 虽存在,却无 security/clientid、required RVoid、范围/幂等/复用反例和 JSON/no-store;问题单 API-LOGOUT-001003tests/logout-openapi-contract.ps1 已建立。任何远端失败都不恢复本地 token,只区分“已从本机退出;服务器撤销已确认/未确认/未能撤销”。

M04 改密三人审查否决当前登录/注册/找回/改密共用的静态 32 个十六进制字符 MD5 wire:它是可直接重放的密码等价物,也使服务端无法执行真实新密码策略。唯一生产目标是四条入口原子迁移到 HTTPS 中的 raw writeOnly 密码;当前密码与登录兼容 1—64 Unicode code point,新密码统一 15—64 code point、NFC、允许空格与 Unicode、无组成规则,并由服务端执行常见/泄露密码 blocklist、账号限速和带独立盐的自适应慢哈希。M04 当前密码就是重新认证,TAC 不替代身份;用户明确要求的 A01/A04/A05 TAC 仍由原认证门禁持有。严格 200 前服务端必须原子落密、提升 credentialEpoch 并撤销包括调用者在内的所有 access/refresh session,客户端清本机回 A01;网络、超时、畸形响应或 5xx 也是结果未知,同样清本机且不自动重试。问题单 API-PASSWORD-001005tests/password-change-openapi-contract.ps1 已建立;门禁通过前 M04 保持诚实本地预览。

M05 换绑三人审查否决“活动 bearer+新号验证码”直接改号:这只能证明控制新号码,不能证明当前账号本人。唯一生产流程是活动 session、最终 PUT 内 raw currentPassword 重新认证、APP_PHONE_CHANGE TAC 和新号严格 6 位 OTP;不强制旧号 OTP,避免用户丢失旧号时永久锁死,但成功事务必须持久写入旧号安全通知 outbox。标准 OpenAPI 无法按公共发码 body 的 sceneCode 条件化鉴权,因此采用独立且强制 SaToken 的 POST /genealogy/app/auth/phone/sms/codescene 由路径固定;公共 /auth/sms/code 删除 APP_PHONE_CHANGE,两个 operation 仍复用同一 OTP 生成、限速和存储 owner。最终 PUT /auth/phone body 只含 currentPassword/phone/smsCode,在同一事务内消费 OTP、执行号码唯一约束、更新号码、提升 credentialEpoch、撤销包括当前在内的全部 access/refresh session并写通知 outbox,严格 200 返回 RVoid。无密码账号返回 STEP_UP_UNAVAILABLE,不能降级;最终 PUT 的超时、5xx、畸形响应或进程终止均按结果未知清本机回 A01且不自动重试。问题单 API-PHONE-001005tests/phone-change-openapi-contract.ps1 已建立;M04 raw-password 门禁、认证/TAC 门禁和本门禁通过前,M05 保持诚实本地预览。

G03 创建链路三人反向质询后否决“先建空谱、再写始祖”的 ROOT_REQUIRED 两写方案:当前产品没有跨会话保存空谱的需求,而两写会凭空增加半成品配额、可见性、恢复、取消、过期和第二次未知结果。唯一生产目标是第一步只在本页收集资料,最终按钮以 AppGenealogyBootstrapBody 一次原子创建家谱、OWNER 成员关系、带数据库权威标记的唯一一世始祖、READY 状态和幂等回执;通用人物 collection、人物 DELETE 与 parents mutation 必须阻断第二根、删除根和重挂父母,人物 PUT 对根的可编辑白名单精确只有 name/sex/birthDate/biography,其他字段全部 typed 422。首次 POST 先以短控制事务认领 PENDING/digest/fencing,再由业务事务完成全部写入,任一步失败全回滚并 CAS 终态;结构化转换只允许 ABSENT→PENDING→SUCCEEDED/FAILED_NO_COMMIT 且终态不可变,FAILED 机器保证零领域写与零 quotaPENDING 的 resolveBy<=claimedAt+2 分钟GenealogyBootstrapOperationKey 由 13 位服务端判定的 issuedAt 毫秒与至少 128 位 CSPRNG 组成,acceptUntil=issuedAt+10 分钟、最大未来偏差 5 分钟,并由 600/300 秒扩展锁定;operation-status GET 无 body、纯读且只返回显式 discriminator 的三个状态,截止前 404 保持同 key,截止后无记录按 key 计算 FAILED 而不写墓碑。请求使用受鉴权 /genealogy/app/region/search、词法 GenealogyRegionCode、服务端 selectable 和统一 GenealogyAccessPreset=MEMBER_ONLY/PUBLIC_APPLY,同版删除公共地区旧路由,并递归清除组合 schema 中的 visibility/joinMode 及旧 create/update DTOG11 在本批只取得共享字段形状,其 If-Match、版本/CAS、权限刷新与结果未知仍是独立门禁。客户端仅持久 {sessionEpoch,operationKey,startedAt}IDEMPOTENCY_KEY_REUSED 必须进入 fatal/quarantined,禁止查询或安装 status、自动换 key,只有用户明确放弃才能清理;其他分支按可证明未提交与 unknown 分离。成功固定按 receipt→/mine cache→context→G05 收口,context/导航失败只重试本地闭环。问题单 API-G03-001005、完整双源深比较、后端 tests/g03-bootstrap-openapi-contract.ps1 和实际执行状态机套件的客户端 tests/g03-bootstrap-client-release-gate.ps1 已建立;G03 两门禁转绿仍不能绕过家谱工作区读取门禁、聚焦/全量回归与 MuMu 原生验收,全部通过前保留诚实本地预览,不接 appApi.createGenealogy

当前 JSON 的 SHA-256 为 87db1dc148c5e6e877815aff7b3a7fc7c7eca95a2cec50a88b42f3908961f31aYAML 的 SHA-256 为 8964cd583ce172425b63bbfd802f7eb587eb3641eadfd6f9d3b264faa8090c6c。两份文件均已被 Git 跟踪,当前相对 HEAD 无差异;本轮没有改写、格式化或覆盖接口导出。

必须保护的用户文件

  • APP.openapi.yamlAPP.openapi.json:后端接口离线源快照,只接受同一后端版本的双导出替换,不得手工修改。
  • static/tac/:当前共 5 个文件,其中 4 个是后端提供且不可改写的供应商文件,第 5 个是项目适配器 static/tac/js/jiapu-tac-adapter.jsA01/A04/A05 已形成真实运行时消费者,文件集合与供应商哈希由 tests/auth-tac-integration-contract.ps1 唯一保护。
  • 当前五份中文治理文档:长期唯一入口,随已验证进度同步更新,不另建平行计划。

任何清理批次都不得覆盖、恢复或删除以上文件。

清理前基线

  • 五个核心验证:全部通过。
  • PowerShell 合同:129 个,128 个通过,1 个旧 A01 固定画布合同失败。
  • Vue 覆盖:实际 66、清单 66、缺失 0、陈旧 0
  • Vue 中 100% 100% no-repeat0
  • Vue 中直接声明 border-image-slice0
  • 文档:261 个;PowerShell 测试:129 个;Node 测试:29 个。
  • static/128 个正式文件,约 95.45 MiB

以上数字只记录清理起点,不是必须保持的目标。

阶段 0 最终结果

  • 旧 A01 固定画布、PSD、Photoshop、v2 按钮和旧卷轴入口已经三人一致退役;没有通过重建旧预览制造假绿。
  • schema v3 注册表已经完整覆盖当前 static/assets:认证直接资产、其余应用直接资产、共享卷轴、六张长页面背景和 G01 空态边框各有唯一 owner;旧 G01 候选与模块背景清单及注册例外已经删除。
  • design-pipeline/manifests/shared-scroll-skins-v3.json 只拥有母版、处理、物理输出和质量规则,不再拥有页面槽位或 uni-app mode
  • 阶段 0 验收时,tests/runtime-assets-contract.ps1 精确闭合 79 个正式输出、物理文件和源码消费者;导航任务 3 又删除了退役通用页面唯一虚构消费的两张 notification frame,当前正式输出为 77 个,并由 tests/retired-module-page-contract.ps1 防止旧入口与孤立资产回归。
  • 设计管线当前为 Node 25/25 PASS、Python 19/19 PASS;四张共享卷轴、六张长背景和 G01 空态边框均可真实重建并通过质量审计。
  • 质量报告只含工作区相对路径;确定性测试证明相同输入连续两次得到相同字节哈希与报告。
  • 六张长背景与 G01 空态边框迁移后的可见像素哈希逐张等于迁移前正式图;连续两次构建的文件 SHA-256 也完全一致。旧 Sharp 单用途依赖和专用构建器已删除。
  • 已删除 28 个无运行时消费者的 static/assets3 个旧 static/icons4 个未接入业务的 TAC 文件和 8 个候选或伪母版;两张用户批准的 A01 选型图作为 reference-only / non-runtime 视觉锚点保留。
  • 阶段 0 验收时的 MuMu 证据:emulator-5554 当时在线,ADB 设备字段为 model:SDY_AN00,系统型号为 SDY-AN00,物理尺寸 720×1280density 320 dpi。本轮原生截图逐张打开复核了 A01、G01、T01 和 F01,未见缺图、透明错误、异常裁切或样式回退;复核结束后已回到 A01 页面,未启动、关闭或调整模拟器。
  • docs/接口与页面映射总表.md 已按 pages.json 建立 52/52 活动页面映射;A04、G 系列第一轮、T01 和新线上 OpenAPI 差异已有专项结论,其余具体接口仍标记为“待对应业务阶段 OpenAPI 审查”。
  • 第一轮六项产品优化已经完成:G01/G06 统一读取受控查询参数,G03 在本轮进一步删除了无业务参数的 onLoad;AppDialog 统一安全区与高度预算;AppTabbar/GenealogyCard 补齐可访问点击语义;G10 拒绝原因建立错误关联与失败聚焦;A04/A05/M04 统一消费唯一密码策略;T01 可在视图漂移后精确回到当前成员。
  • 后续产品阶段按顺序为导航栈语义统一、T01 大规模世系树、短信验证码完整状态机、跨页面领域数据持久化、全局文字层级和无障碍第二轮;不得混合实施。
  • 文档权威迁移已删除 198 个旧 Markdown、35 张旧 H5/静态设计图、4 个只保护旧资料的测试和 .superpowers/sdd12 个过程文件;阶段 0 临时清单随后也已删除,当前 docs/ 只保留 5 个长期中文 Markdown 入口。
  • 浏览器截图链已把 G03、G06、G08—G12、T06、F02、N01 的有效状态断言迁回各自现有运行时合同;G01、T03—T08、T07 三个有价值的浏览器测试只剥离截图写盘,继续验证状态、滚动、溢出与交互。
  • 已删除固定 Chrome 截图助手、联系表、8 个只保护截图助手的合同,以及迁移后重复的 N01/A02 合同;tests/mumu-visual-acceptance-boundary-contract.ps1 现在唯一约束“仓库不维护自动截图证据链、最终视觉通过只来自 MuMu”。

当前物理库存为 140 个 PowerShell 合同、47 个 Node 文件和 4 个 JSON 合同数据文件。最新 fresh 结果为 PowerShell 126/140 通过;其余 14 项不是可删除的普通回归,而是保留真实外部或发布阻塞的 tests/lineage-openapi-contract.ps1tests/auth-tac-openapi-contract.ps1tests/genealogy-workspace-openapi-contract.ps1tests/g03-bootstrap-openapi-contract.ps1tests/g03-bootstrap-client-release-gate.ps1tests/help-center-openapi-contract.ps1tests/profile-openapi-contract.ps1tests/profile-update-openapi-contract.ps1tests/notification-read-openapi-contract.ps1tests/notification-read-state-openapi-contract.ps1tests/logout-openapi-contract.ps1tests/password-change-openapi-contract.ps1tests/phone-change-openapi-contract.ps1 和缺少 MuMu 人工证据时必须失败的 tests/auth-android-accessibility-release-gate.ps1。十四个输出分别为 LINEAGE-OPENAPI-CONTRACT BLOCKEDAUTH-TAC-OPENAPI-CONTRACT BLOCKEDGENEALOGY-WORKSPACE-OPENAPI-CONTRACT BLOCKEDG03-BOOTSTRAP-OPENAPI-CONTRACT BLOCKEDG03-BOOTSTRAP-CLIENT-RELEASE BLOCKEDHELP-CENTER-OPENAPI-CONTRACT BLOCKEDPROFILE-OPENAPI-CONTRACT BLOCKEDPROFILE-UPDATE-OPENAPI-CONTRACT BLOCKEDNOTIFICATION-READ-OPENAPI-CONTRACT BLOCKEDNOTIFICATION-READ-STATE-OPENAPI-CONTRACT BLOCKEDLOGOUT-OPENAPI-CONTRACT BLOCKEDPASSWORD-CHANGE-OPENAPI-CONTRACT BLOCKEDPHONE-CHANGE-OPENAPI-CONTRACT BLOCKEDANDROID-AUTH-ACCESSIBILITY-RELEASE BLOCKED。Node 语法 47/47 通过,纯 Node 冒烟 19/19 通过,活动 Vue 脚本模块语法 64/64 通过;导航源码扫描保持 MIGRATION-DEBT=0。依赖 127.0.0.1:9222 调试页的浏览器运行时文件本轮只做语法检查,没有执行;这不能冒充浏览器行为或 MuMu 原生视觉通过。

阶段 0 清理结束时,static/ 的正式基线为 79 个文件、共 70,414,397 字节。任务 3 退役两张孤立通知 frame 后,正式 static/assets77 个文件、共 69,093,742 字节;static/tac/ 当前 5 个文件、共 68,190 字节,因而当前 static/ 物理库存为 82 个文件、共 69,161,932 字节。4 个供应商文件保持原字节并由哈希合同保护,新增适配器是唯一项目映射层;TAC 已进入 A01/A04/A05 业务运行时,但不属于可重建视觉资产注册表。tmp/unpackage/design-pipeline/generated/ 均不存在;正式生成资产仍由清单和构建器恢复,质量报告不作为长期资料保留。

当前规划结论

导航栈

  • 迁移前 52 个活动页面只读统计为 navigateTo 59navigateBack 11redirectTo 14reLaunch 7,活动页面合计 91 次;活动组件另有 4 次,封存 A06 另有 2 次。任务 3—9 已依次迁移共享组件、认证、G、T、F、R、N/M,任务 10 删除最后一个无消费者旧表单组件并关闭门禁。当前 pages/components 中 navigateTonavigateBackredirectToreLaunchgetCurrentPages 和业务页面路径字面量均为 0switchTab 全项目为零;五种 Uni 导航调用和页面栈读取只允许由 utils/navigation.js 持有,业务路径只允许由 utils/navigation-routes.js 持有。
  • MuMu 已复现 F01→F03 返回后残留两个 F01、A01→A04→登录后残留两个 A01、T03 同路由连续叠页,以及栈深为 1 时 F03 错回 G01。
  • 三人终选并已实现两个唯一所有者:utils/navigation-routes.js 持有 52 条路由、父页参数映射和结果操作枚举,utils/navigation.js 持有五种 Uni 导航 API、五个公开导航语义方法、一次性结果与统一返回优先级;没有真实替换边,因此不公开替换方法。
  • G01、F01、M01 保持自定义 Tab 根页;A01 是认证根页。T03 只保留一个原生页面实例,初始路由 personId 是不可变宿主页身份,亲属浏览使用页内成员轨迹和可变活动成员;T05 本地预览离开使用 goBack(),不会把活动成员误写成宿主页路由身份。
  • 任务 1—10 已完成测试先行和静态实现;一次性结果绑定真实目标路由与业务参数上下文,只能由当前真实栈顶目标页消费。52 个活动路由、共享组件、四个根语义以及认证、G、T、F、R、N/M 系列均已迁移;通知目标只能由本地类型白名单映射,未知或越权目标失败关闭。未接真实写接口的页面只能形成明确的本地预览或硬关闭,不再展示伪保存、伪邀请码、伪订单或伪安全结论。任务 4—10 的 MuMu 原生流程复核仍因本轮禁止触碰模拟器而待执行,静态零债务不能替代该验收。

T01 大规模世系树

  • 此前默认 6 人数据中的 103→106 断线已通过唯一成员 owner 与字符串 parentId 修复;普通节点实际半高与全局常量仍相差约 4rpx,10×12 压力数据约 45/54 个父分组仍会断线,而旧测试只检查线段数量。
  • 当前布局最坏为 O(G×N),单人一代时接近 O(N²);页面与 mock 已统一当前阶段的 id/parentId 夹具,但 OpenAPI 仍使用递归 children/spouses,无法直接对接未来规范图窗口。
  • 产品终选“焦点成员渐进窗口+独立全谱概览”,初始上二代/下二代;主世系为骨架,配偶并排,每段家庭关系有独立联合点,子女从对应联合点向下。
  • 技术终选视口大小的单 Canvas 同画节点和边;纯 JavaScript 按“规范化→严格校验→可见投影→确定性布局→Scene/空间索引→相机”处理,DOM 只保留页头、工具条、两档抽屉、搜索、概览和无障碍线性列表。
  • 本地旧导出和 2026-07-22 线上 OpenAPI 都只有 v1 /lineage/tree,仍是递归模型,并缺少 overview、locator、稳定关系寻址和树版本并发合同。最新线上文档的 722 条路径中没有任何 /genealogy/app/v2/507 个模型中也没有新图辨识字段,四个稳定业务码同样缺失。后端问题单 API-T01-001 已固定四条 v2 路径、FOCUS/BOUNDARY 查询、schemaVersion/treeVersion、EMPTY/POPULATED 空谱判别、窗口入口与全谱根分离、严格匿名节点、以 relationshipKind 判别的可寻址伴侣/父子关系、空 PATCH 错误码和 Scene 原子版本;tests/lineage-openapi-contract.ps1 已建立严格红灯,在同版本线上文档与双导出通过前,T01 客户端不得开始任务 12。
  • 当前实施轮没有改写 OpenAPI 文件,也没有启动、关闭或调整 MuMu;已完成导航共享所有者、共享组件/根页头部语义、退役死入口、认证、G 系列、T 系列和 F 系列导航合同,以及树成员与家族内容夹具统一。认证请求代码已对准真实端点,但运行模式仍失败关闭;G/T/F 系列真实写接口与 T01 新图尚未接入。

TAC 认证与无障碍安全边界

  • utils/auth-verification.js 是当前认证场景、4 位短信码和服务端票据形状的唯一客户端 owner;生产目标由后端 SmsCodeSecrettests/phone-change-openapi-contract.ps1 锁定为严格 6 位,门禁通过时必须一次替换所有活动消费者并删除旧 owner 的四位规则。components/TacVerification.vue 是验证浮层与 renderjs 生命周期 ownerstatic/tac/js/jiapu-tac-adapter.js 是 TianAi challenge/proof/verify 映射 ownerutils/api.js 是严格 HTTP 200 envelope、15 秒超时、离页中止、认证会话写入和反馈 wire payload 的唯一 owner。旧认证专用请求控制器入口、占位验证、伪验证码、宽松令牌兼容和 M07 假提交均已删除。
  • A01 默认短信登录;密码登录因 API-AUTH-TAC-001 保持可见但不可用。A04/A05 都只在发送短信前验证一次,并在手机号改变后使旧验证码上下文失效;成功、失败、取消、重复回调、空响应、非 JSON、超时、离页和返回键均有静态或纯运行时合同。短信发送与重设密码的 RVoid 没有声明 data 必填,客户端因此只要求合法 HTTP 200 与整数成功 code,并把“省略 data”或 data:null 都精确归一为 null;登录、注册和 challenge 等有实体响应仍强制 data
  • 当前客户端浮层已补齐对话框命名、说明关联、初始聚焦、Tab 圈定、Escape/Android 返回、焦点恢复、原生刷新与关闭按钮、48px 目标及小视口内部滚动;这只是客户端壳层预检,不代表第三方滑块本身可由 TalkBack 或键盘完成。tests/auth-android-accessibility-release-gate.ps1 要求 MuMu 原生证据与非拖动等价验证方式,证据缺失时固定输出 ANDROID-AUTH-ACCESSIBILITY-RELEASE BLOCKED
  • 三人交叉质询后的唯一方向是“同一验证中心、同一短时单次 validToken、供应商无关的服务端决策”,永久禁止 accessibility=true、跳过 TAC 或无票据发短信。中国大陆非交互风控供应商只进入限时 POC,必须在真实 UniApp Android WebView 中证明 TalkBack、外接键盘和 Switch Access 无焦点陷阱且误杀、防刷、弱网与故障指标达标,不能预先写成无障碍完成。已安全绑定设备只能作为加权信号;供应商不确定或不可用时进入支持文字/中继的可审计人工兜底或稍后重试,绝不 fail-open;音频验证码仅为后续独立 POC 候选,不能作为 P0 或唯一替代。

领域上下文与 M07 反馈

  • utils/genealogy-context.js 只接受无边界空白的非空词法字符串 ID,并持有独立失效标记;utils/session.js 在损坏令牌、退出和账号令牌变化时同步清理 ID 与标记。首次且没有历史选择或标记时可确定选择首个可用家谱;针对调用方提供的新列表,历史选择消失或显式目标不可用时写入标记并由 G01 要求用户明确重选,跨重载也禁止静默串谱。真实后台撤权能否被及时发现仍取决于后续 workspace 的 onShow/事件刷新。
  • appApi.submitFeedback 是反馈提交唯一 owner:只接受 feedbackContent 必填、feedbackType/contactInfo 可选的三个字符串字段,trim 后删除空选填值;调用方不能关闭认证头。remote 精确 POST /genealogy/app/feedback,只认 HTTP 200 且 code 为整数成功码的 envelope;反馈响应没有声明 data 必填,页面也不消费返回实体。mock 固定失败关闭且不调用网络。
  • M07 提交中禁用输入并使用提交前快照;成功后保留回执内容并禁止原样重复提交,请求期若仍有迟到输入则明确区分“上一份已提交”和“当前修改未提交”。超时、断网、意外 2xx/3xx、HTTP 408/5xx 或响应无效进入 uncertain,同一快照禁止重提;unknown 回流也会重新比较当前表单,迟到输入保持可提交而不冒充旧快照。只有确定拒绝才允许重试。tests/m07-feedback-state-runtime-smoke.js 已直接执行这些页面状态;真实服务联调仍受认证远端门禁约束。

家谱工作区远端门禁

  • 三人反向质询后没有要求后端把 AppGenealogyVo 全部字段设为必填,也不把缺少 security 注解或文档媒体类型 */* 单独宣称为数据泄漏。首批只消费 genealogyId/genealogyName/canView/canManage/canEditContent/roleType;前五项需明确类型并必填,roleType 还需非空正式枚举。地点、堂号、人数和简介可选并由页面诚实降级,未知额外响应字段允许忽略。
  • JSON 响应身份必须使用非空词法字符串。仅在客户端拒绝 unsafe number 虽可避免串谱,却会让 OpenAPI 合法的 int64 用户永久不可用,不能作为普遍上线方案;URL path 在 wire 上本就是文本,不机械要求为了同一问题改类型。
  • /mine 必须以必填 canView 或等价、可自动验证的投影保证只把当前账号仍可查看的家谱送入 context;G01 只有成功取得新列表才 reconcile。网络、超时和 5xx 保留旧现场并显示错误,明确撤权/无权/不存在才写 tombstone。G05 使用 /overview,取消迟到请求并在新身份加载前清掉旧数据,远端失败绝不回退 fixture 角色。
  • OpenAPI 注解修复后仍须用有效账号执行无凭证、跨账号、撤权、删除、5xx、畸形 JSON 和取消反例;当前无令牌 HTTP 200+业务 code=401 的承载方式可以保留,也可改规范 HTTP 状态,但文档、运行时 validator 与部署行为必须一致。

M06 帮助内容远端门禁

  • 首批只使用 /genealogy/app/help-articles 一次取得完整正文;详情接口、文章深链、封面、浏览量和业务 ID 均不属于 M06。adapter 只准输出 {category,title,content} 与当前响应生命周期的展示键,必须显式丢弃 helpId/status/sortOrder/viewCount/coverOssId/remark
  • 响应 envelope 的 code/data 和每行 helpCategory/helpTitle/helpContent 必须 required;三项均为非空字符串,分类是可直接展示标签,正文首版固定为纯文本。用户侧列表只返回已发布内容,数组顺序就是展示顺序;客户端不猜分类码、不解释 HTML/Markdown。
  • 搜索与筛选只作用于已投影数组;筛选后不得重新编号。搜索、分类和刷新先收起正文,新请求以 controllergeneration 拒绝迟到响应,离页取消请求;空列表、搜索无结果、加载失败和认证失效必须分别表达。
  • M06 现有分类和问题标题使用 <view role="button"> 且触控高度不足;真正接线时改为原生按钮语义,补 aria-pressed/aria-expanded/aria-controls、状态播报、重试和至少 44dp 目标。源码审查不能替代 MuMu 的系统字号、TalkBack、焦点与视觉验收。

个人资料读取远端门禁

  • 唯一 profile adapter 在 mock/remote 两种模式都产出同一窄模型;运行模式必须经 resolveRuntimeMode() 校验,错误配置不得静默回 fixture。remote 使用严格 envelope、15 秒超时、请求取消和 generation 防迟到,不建立跨账号缓存或经路由传递个人资料。
  • 原始手机号只在 adapter 局部验证 canonical 格式,输出仅含 maskedPhone 与“绑定手机号,尾号 xxxx”读屏标签;页面、日志、错误、缓存和路由都不得接触明文。可选昵称、实名、邮箱只有真正省略时规范为内部空串;出现 null、空白、超长或非法邮箱时整份失败关闭。
  • M01 的加载/失败只替换身份卡,服务菜单与底栏保持可用,并删除查询参数制造的假错误和“重试即成功”;通知 fixture 不得与真实身份混装为线上数量。M02 完成异步填表后才建立 dirty baselineGET 不冒充 PUT 保存;M03 只让手机号行局部加载/失败,密码入口不受普通读取失败影响,并删除不属于账号资料的“创建者”角色。
  • 真正实施时原子替换禁止页面调用 API 的旧静态断言,使用 AppLoading 和原生按钮,补 M02 的 aria-invalid/aria-describedby、失败聚焦、状态播报、44dp 目标、长昵称换行和装饰图隐藏;MuMu 仍须验证系统字号、TalkBack、焦点与真实纹理对比。

通知读取与已读状态远端门禁

  • 读取批次以无筛选列表作为当前账号完整活动集合 owner,RListNotificationVo.data 允许空但最多 200 条并按 publishTime 最新优先;RNotificationUnreadCount.data 为 0—200,精确等于同一活动集合中 readStatus=UNREAD 的数量。两个请求之间发生并发新消息时允许瞬时差异,客户端不得据此判错。
  • NotificationVo 的首批 required 字段为 noticeTitle/noticeContent/publishTime/readStatus:标题 1—50、完整正文 1—1000 且为纯文本,时间必须是带时区 RFC3339,状态只允许 READ/UNREAD。N01 摘要最多显示 160 个字素,N02 展示同一快照的完整正文;长文本必须换行,不解释 HTML、Markdown、URL 或服务端跳转字段。
  • 读取 adapter 只公开 {snapshotKey,title,content,publishedAt,unread}key 由成功响应 generation 与映射前 ordinal 组成;不持久化、不使用裸序号,也不把 notificationId/genealogyId/bizId/bizType/senderPhone 暴露给页面。成功刷新原子替换 generation,退出和账号切换立即清空;N02 不能解析 key 时只提示“请返回消息中心重新打开”。
  • 首批删除通用“前往入谱审核”、详情目标按钮和从消息字段猜路由;后端将来只有提供闭合的 bizType → route key+必填词法参数+权限/失效语义 字典后才可独立恢复 CTA。M01/G01 共同消费未读数 owner,文案统一为“未读消息”,可见角标封顶 99+,读屏仍播报真实数量。
  • 写批次通过前,打开 N01/N02、点击“标记已读”或“全部已读”都不得只改本地 clone。写合同通过后,唯一通知 controller 才能私有保留 1—128 位 URL-safe opaque notificationId;页面仍只持有 snapshotKey。单条和全部已读必须对当前账号幂等;read-all 只覆盖服务端接收时已存在的活动通知,并发新消息保持未读;超时或结果未知时重新读取列表和计数收敛。
  • 两个失败门禁分别是 tests/notification-read-openapi-contract.ps1tests/notification-read-state-openapi-contract.ps1。当前分别输出 NOTIFICATION-READ-OPENAPI-CONTRACT BLOCKEDNOTIFICATION-READ-STATE-OPENAPI-CONTRACT BLOCKED;后端同版本双导出、有效账号反例和 MuMu 状态矩阵完成前不能宣称通知闭环上线。

M02 个人资料写入远端门禁

  • PUT 请求体唯一 owner 固定为关闭额外字段的 AppProfileMergeUpdateBody,只能包含 1—3 个真正脏的 nickName/realName/email。昵称出现时为去边界空白的 1—30 字符;真实姓名和邮箱的精确 "" 是唯一清空命令,非空真实姓名 1—30、邮箱 1—100 且格式有效。省略表示保持,null、纯空白、边界空白、空 body、头像/性别/生日或任意额外字段全部早失败。
  • AppProfileVo 新增 required profileVersion,形状为 1—128 位 URL-safe opaque string;写请求只在 required If-Match header 携带,不在 body 建第二版本字段。服务端按当前账号和租户原子 CAS,成功返回含新版本的完整 canonical profile,旧版本固定 409 PROFILE_VERSION_CHANGED;相同字段集重复执行不产生通知、审计之外的额外业务副作用。
  • M02 首次 GET 完成后才建立 baseline;保存时冻结三个输入和提交快照,成功用响应回填并重置 baseline。确定失败保留草稿;超时、断网、408/5xx 或畸形成功响应属于结果未知,先 GET 逐项核对本次脏字段,匹配则确认成功、仍为旧值才允许重试、第三值进入冲突,不盲目重复 PUT。
  • session generation 是账号隔离边界:账号切换、退出和页面卸载中止等待、清空未持久草稿并拒绝旧账号迟到响应;取消 RequestTask 不等于服务端未写。真实姓名、邮箱、提交 payload 和版本不得进入日志、路由、持久缓存或遥测。
  • 当前假定昵称必填,所以旧账号昵称省略时可以只改其他字段,但不能把已有昵称清空。头像选择、相册权限、OSS ID、性别和生日全部留到独立批次;当前 <view role="button"> 假头像动作在写入实施时删除。邮箱没有验证与送达合同,页面不得继续承诺“用于接收通知”。
  • tests/profile-update-openapi-contract.ps1 当前输出 PROFILE-UPDATE-OPENAPI-CONTRACT BLOCKED。后端关闭 API-PROFILE-UPDATE-001004、同版本双导出通过、读取 owner 可用、有效账号/CORS 反例和 MuMu 表单矩阵完成前,M02 保持诚实本地校验而不发写请求。

M10 当前设备退出远端门禁

  • 后端 DELETE 只撤销当前请求 bearer 及同一可续签凭证族;其他设备 token 保持有效。合法签发给同一 client 的 active/revoked/expired token 重复调用统一返回 200 RVoid,操作幂等且无额外副作用;成功后用旧 token 调 profile 等受保护接口必须失败。非法或 client 不匹配返回 RLogoutRejected,业务码只允许 TOKEN_INVALID/TOKEN_CLIENT_MISMATCH,不能冒充远端已撤销。
  • operation 必须 required SaToken 与非空 clientid、禁止 request body、200/401 使用 application/json 并带 Cache-Control: private, no-storeRVoid 的整数 code required,另声明 400/429/500。线上仅有文字“需要登录”和 */*,本地虽有 security/clientid 但 RVoid 无 required、只列 200,均未达到发布合同。
  • logoutCoordinator 是唯一跨页 owner:同步捕获 token/clientid 与 logoutEpoch,立即调用 session owner 清 token、家谱上下文和账号缓存并 bump epoch,再以显式 A 快照创建 RequestTask;整个同步段不 awaitM10 页面拿不到 token。创建失败也不恢复;请求不绑定页面 controllerreLaunch/A01/M10 卸载不 abort。
  • coordinator 的公开内存态只含 {attemptId,logoutEpoch,status},状态为 pending/confirmed/unconfirmed/not-revoked,不保存 token、请求头或错误 payload。A01 仅在 session 仍为空且 epoch 未变化时原子消费一次提示;B 登录后 A 的迟到结果直接丢弃。进程被杀允许丢提示,但旧 token 不落盘、不排队、不跨重启重试。
  • 唯一用户承诺始终是“已从本机退出”。200 显示服务器撤销已确认;network/timeout/408/429/5xx/畸形响应与 generic 401 显示未确认;typed 401/400/403 显示未能撤销。所有分支都留在 A01,不恢复 token、不返回 M10、不重新开放登录后页面;异步 callback/finally 绝不能再次 session.clear()
  • tests/logout-openapi-contract.ps1 当前输出 LOGOUT-OPENAPI-CONTRACT BLOCKED。同版本双导出、两设备 token 隔离/复用反例、真实网络异常和 MuMu 退出提示完成前,只能称现有行为为本机退出,不能宣称服务端注销完成。

M04 登录态修改密码远端门禁

  • 密码 wire 是跨 A01 登录、A04 注册、A05 找回和 M04 登录态改密的单一合同。PasswordLoginBody.passwordPasswordChangeBody.oldPassword 只引用 CurrentPasswordSecret;注册、找回和改密的新密码只引用 NewPasswordSecret。生产入口不再接受 MD5、十六进制摘要或两套兼容分支;确认密码只留客户端。
  • CurrentPasswordSecret 是原样、不 trim 的 1—64 Unicode code pointNewPasswordSecret 是 NFC 后 15—64 code point,允许空格、Unicode 和密码管理器粘贴,不强制字母/数字组成。服务端才是策略权威,必须执行常见/泄露密码 blocklist、当前密码验证、新旧不同、账号级限速和带盐慢哈希;页面校验只是即时提示。
  • PUT required SaToken、非空 clientid 与关闭额外字段的 JSON body200/400/401/409/422/429/500 均为 typed JSON、private, no-store429 带 Retry-After。409/422 用 RPasswordChangeRejected 区分 CREDENTIAL_VERSION_CONFLICT/CURRENT_PASSWORD_INCORRECT/NEW_PASSWORD_SAME_AS_CURRENT/PASSWORD_POLICY_VIOLATION,不解析 msg
  • 唯一会话方案是 ALL:严格 200 前原子写入新 verifier、提升 credential epoch,并让所有设备/所有 client 的旧 access/refresh session 跨节点失效;不返回新 token,也不让当前 bearer 继续存活。200、401、409 和传输结果未知都清秘密与对应本机会话并回 A01;只有明确未写的 400/422/429 可清 credentialChangeInFlight 后留页。
  • 为关闭 PUT 已发出后进程被杀的窗口,session owner 在发送前只持久化 {sessionEpoch,startedAt} marker,禁止保存 token、密码、摘要或 body。冷启动发现同 epoch marker 时必须在任何账号缓存渲染前清会话并进 A01;新登录 bump epoch,使旧 marker 和迟到响应失效。客户端不自动重试、不建 operation-status;重新登录就是最小对账路径。
  • tests/password-change-openapi-contract.ps1 当前输出 PASSWORD-CHANGE-OPENAPI-CONTRACT BLOCKED。后端关闭 API-PASSWORD-001005、原子重导双文件、密码登录 TAC 可用、两设备/并发/故障注入与 MuMu 无障碍矩阵完成前,M04 继续显示“不提交服务器”。

三人规则

  • 总共三人:主代理与两位固定评审者。
  • 三个人都完整检查文档、测试和资产,不割裂分工。
  • 审查阶段只读,实际文件变更只由主代理执行。
  • 删除候选必须三人一致确认;任意一人提出有效疑点时继续调查。
  • 用户已授权三人一致后直接删除,无需逐文件再次确认。

当前禁止事项

  • 不执行 Git add、commit、push、restore、checkout 或 reset。
  • 不启动、关闭或调整 MuMu。
  • 不删除活动业务源码、接口导出、当前权威设计或用户改动;只有三人以消费者、合同和资产清单共同证明已经退役的旧入口才可同轮删除。
  • 不因测试失败而删除测试。
  • 不因静态搜索无匹配而直接删除资产。
  • 不归档确认失效的旧内容,不保留兼容入口。

下一步

  1. T01 后端接口门禁已经建立并运行出预期红灯;等待后端按 API-T01-001 发布四条 v2 操作并提供同一版本重新导出的 JSON/YAML,不手改当前快照,也不提前实施任务 12。
  2. TAC 客户端批次已经完成。认证后端仍须关闭 API-AUTH-TAC-001004、提供同版本双导出并修复 challenge 500;随后才允许把 runtimeConfig.modemock 切为 remote,执行正式 H5 CORS、真实票据重放/限流和 MuMu Android 流程。
  3. 并行推进非交互风控的限时 POC 与文字/中继人工兜底合同;只有 POC、服务端原子消费和 ANDROID-AUTH-ACCESSIBILITY-RELEASE 全部通过,才可宣称认证达到上线门槛。
  4. 新图合同通过后,按规范化与校验、布局、Scene 与空间索引、单 Canvas、页面交互、接口回流的顺序实施 T01。
  5. 家谱工作区三人审查和失败合同已经完成;等待后端关闭 API-GENEALOGY-WORKSPACE-001003 并提供同版本双导出。门禁通过后再测试先行实现唯一 adapter、G01 onShow 列表现场和 G05 /overview 读取,不提前固化字段或枚举。
  6. G03 原子创建三人审查和失败合同已经完成;等待后端关闭 API-G03-001005、以同版本双导出交付 bootstrap POST、状态查询、地区选择与统一 accessPreset。通过前不接当前宽松 createGenealogy;通过后先实现严格 coordinator、无 PII 恢复 marker、地区选择器、context/G05/G01 闭环,再独立完成 MuMu 表单与无障碍矩阵。
  7. M06 三人审查和失败合同已经完成;等待后端关闭 API-M06-001003 并提供同版本双导出。通过后测试先行实现 list-only adapter、加载/空/失败/重试、动态分类、纯文本手风琴和无障碍语义,不接详情或文章 ID。
  8. 个人资料读取三人审查和失败合同已经完成;等待后端关闭 API-PROFILE-READ-001003 并提供同版本双导出。通过后测试先行实现唯一掩码 adapter 与 M01/M02/M03 局部状态,M05 当前手机号展示随同一只读 owner 原子迁移但不接换绑写接口。
  9. 通知读取与已读写入已分别完成三人审查和失败合同;等待后端关闭 API-NOTIFICATION-READ-001003API-NOTIFICATION-STATE-001003。读取通过后先实现无 ID 的内存快照和 M01/G01 未读数;写入另批迁移私有 ID、删除伪本地写并验证并发收敛,不恢复不可信目标 CTA。
  10. M02 个人资料 PUT 已完成三人审查和失败合同;等待后端关闭 API-PROFILE-UPDATE-001004。读取与写入门禁都通过后,按 normalizer、严格 API、M02 状态机和 MuMu 表单矩阵独立实施,不混头像或账号安全。
  11. M10 服务端退出已完成三人审查和失败合同;等待后端关闭 API-LOGOUT-001003 后,再测试先行实现 session epoch、唯一 logoutCoordinator、A01 一次性提示和两设备撤销矩阵。
  12. M04 登录态改密与四条密码 wire 已完成三人审查和失败合同;等待后端关闭 API-PASSWORD-001005 后,才原子迁移共享密码策略、MD5 调用、session marker、M04 状态机和全设备撤销矩阵。
  13. M05 手机号换绑三人审查和失败合同已经完成;等待后端关闭 API-PHONE-001005,且 M04 raw-password 与认证/TAC 前置门禁同时通过后,再原子迁移全活动 OTP、实现专用受保护发码、共享 credential marker 与 M05 状态机。
  14. 继续审查下一个不依赖现有红灯的业务域;按 G/F/R 逐域推进。随后逐批完成文字层级与无障碍,不混合验证码、账号写入、领域数据或支付。