diff --git a/design-qa.md b/design-qa.md
deleted file mode 100644
index a41a095..0000000
--- a/design-qa.md
+++ /dev/null
@@ -1,175 +0,0 @@
-# M09 VIP 与订单:设计核验
-
-## 对比对象
-
-- Source visual truth: `C:\Users\Administrator\.codex\generated_images\019fa647-03b4-7901-9b6a-175d07d56512\exec-f3e0331f-59c3-4f01-a48f-d069bdab2d58.png`
-- 同状态真机截图:`tmp/vip-redesign-audit/20-uniform-footer-cards.png`
-- 下单面板真机截图:`tmp/vip-redesign-audit/21-uniform-footer-sheet.png`
-- 并排对比:`tmp/vip-redesign-audit/22-uniform-main-reference-and-implementation.png`
-- 设备:MuMu Android 基座,720 × 1280(360 × 640 CSS px,device scale factor 2)。参考图裁去底部已露出的面板后,按同一高度归一化进行并排检查。
-
-## 视觉验收
-
-- 顶部:水墨山景、竹影、留白与居中的标题层级已落地;新增背景资产为 `static/assets/modules/profile/opaque/m09-vip-hero-landscape.png`。
-- 套餐:基础版、宗族版、永久纪念版使用同一主推卡片规格,均有同样的朱砂描边、庭院水墨资产、底部价格/期限栏与圆角“立即开通”按钮。
-- 卡片资产:使用 `static/assets/modules/profile/opaque/m09-featured-courtyard.png`,在三张卡上保持统一的透明度和裁切方式,文字与按钮在真实窄屏上保持可读。
-- 下单:原居中装饰弹窗替换为底部确认单;套餐、有效期、应付金额、微信支付方式和取消入口均清晰可见。
-
-## 交互验收
-
-- MuMu 真机已点击“立即开通”,成功打开“确认下单”底部面板。
-- 已点击“暂不购买”安全关闭面板;关闭后确认页面仍保留 3 个“立即开通”入口,未由这次视觉验收新增订单。
-- 套餐和订单数据仍由现有接口读取;本次只改页面结构、样式与图片资产,不改接口字段或订单创建逻辑。
-
-## 已知合同边界
-
-- 当前 OpenAPI 未提供第三方支付调起参数或支付结果回调,因此主操作保持“创建订单”,不虚假宣称已完成微信支付。
-
-## 结果
-
-final result: passed
-
----
-
-# T01 世系谱:设计核验
-
-## 对比对象
-
-- Source visual truth:用户在本次会话提供的 `Jiapu-App` 世系谱截图(408 × 936 px),并已核对参考源码 `C:\Users\Administrator\Desktop\job\Jiapu-App\pages\index\tree\index.vue`。
-- Implementation screenshot:`tmp/t01-pedigree-paged-order-final2.png`(720 × 1280 px,MuMu Android;360 × 640 CSS px,density 2)。
-- 当前真实数据状态:已授权的“真机联调10159371”仅有 1 位成员;页面已显示一列始祖资料与右侧世代切换,不能据此核验多人横向滚动。
-
-## Findings
-
-- [P1] 当前授权家谱只有一位成员,无法以真实数据复核参考图的“多位同世成员横向展开”状态。
- - 影响:实际单列、世代切换和纵向文字已验证,但多人列宽、横向滚动和同代排序仍缺少真机证据。
- - 修复:使用至少 5 位同世成员的测试家谱再次打开 T01;不应以本地伪造数据替代真实家谱数据。
-
-## 已完成的源码核验
-
-- T01 使用现有 `appApi.getTree` 单一数据 owner,按 `generation` 分组后每 5 人补齐空列并使用 `swiper` 横向分页;不引入参考项目的旧 `getGenealogyUserByParentsId` 接口。
-- 列结构为关系、姓名、资料三段纵向阅读;同世人员位于横向滚动容器,右侧切换上一世/下一世。
-- 静态合同、关系布局合同、人物操作合同和树接口运行时 smoke 均已通过。
-
-final result: blocked
-
----
-
-# T01 relationship-compass redesign: MuMu comparison rerun
-
-## Evidence
-
-- Source visual truth: `C:\Users\Rain\.codex\generated_images\019fad7d-b30e-7e42-b40a-586bade6fec2\exec-dce4de58-d938-4ab5-ad7f-dfdacb399de0.png` (853 × 1844 px).
-- Accepted implementation capture: `tmp/t01-relationship-compass-round6.png` (MuMu Android, 900 × 1600 physical px; Chrome DevTools viewport 451 × 800 CSS px at 2× density).
-- Full-view comparison: `tmp/t01-relationship-compass-round6-comparison.png`; the source and implementation were width-normalized to 853 px and placed side by side.
-- State: T01 tree overview, selected member `真机联调始祖`, relationship-action sheet open. The capture was taken after native image assets had loaded; the earlier immediate capture was rejected because the images had not painted yet.
-
-## Comparison history
-
-1. Earlier comparison (`tmp/t01-relationship-compass-audit-compare.png`) found P1 gaps: no visible relationship connectors, a mismatched central graphic, generic rectangular relationship buttons, and inconsistent sheet hierarchy.
- - Fix: generated and wired the paper panel, six-way relationship map, medallion, close, marker, and arrow assets; restored the independent sheet and removed the mismatched section labels.
-2. First recovered MuMu capture (`tmp/t01-relationship-compass-round2-recovered.png`) confirmed the actual authorized T01 state was reachable, but showed P1 spacing and button-shape drift.
- - Fix: generated the relation-button frame and a smaller, clean four-point compass asset; added the genuine divider asset; tightened the 9:16 layout so all four management actions stay in the viewport.
-3. Final MuMu capture (`tmp/t01-relationship-compass-round6.png`) was compared in the same composite input. No actionable P0/P1/P2 mismatch remains.
-
-## Fidelity review
-
-- Typography and copy: the live member name and generation remain readable; relationship and management labels do not wrap. The selected member's live copy intentionally differs from the concept's sample name.
-- Spacing and layout rhythm: on the actual 9:16 MuMu viewport, header, divider, six relationship actions, and four management actions form one complete, unobscured sheet. The source canvas is taller (853 × 1844), so its exact vertical crop is not reproduced; this is a P3 reference-canvas difference rather than an app overflow.
-- Colors and tokens: warm ivory paper, antique gold, and cinnabar are consistent between the panel, graph, relationship actions, and management cards.
-- Image quality and assets: visible non-standard artwork is PNG-backed (panel, compass, relationship frame, portrait medallion, markers, close, arrows, divider). No emoji, inline SVG, CSS-drawn icon, or placeholder was used in place of those assets.
-- Residual P3 polish: the reference uses a sample portrait and individually drawn function icons; the running app keeps its neutral medallion and existing generated marker assets so the sheet does not imply an incorrect person identity or operation type.
-
-## Verification
-
-- Opened the selected T01 member in MuMu and accepted the delayed native capture.
-- Passed: `tests/t01-person-action-panel-contract.ps1`, `tests/t01-relation-layout-contract.ps1`, `tests/t01-all-states-visual-contract.ps1`, and `tests/t01-tree-state-contract.ps1`.
-- Passed: `git diff --check` (only existing CRLF conversion warnings).
-
-final result: passed
-
----
-
-# T01 人物操作面板:关系罗盘重设计核验
-
-## 对比对象
-
-- Source visual truth:本次会话选择的第 2 张「关系罗盘」设计图,`C:\Users\Rain\.codex\generated_images\019fad7d-b30e-7e42-b40a-586bade6fec2\exec-dce4de58-d938-4ab5-ad7f-dfdacb399de0.png`。
-- Implementation screenshot:`tmp/jiapu-t01-panel-mumu-final.png`,MuMu Android 真机运行时的面板打开状态(900 × 1600 px)。
-- 同画布对比:`tmp/t01-relationship-compass-reference-vs-mumu-final.png`;左侧为设计稿面板裁切,右侧为 MuMu 实现面板裁切,并将二者归一至 853 × 1254 px 的同一面板画布。
-
-## 真机视觉对比
-
-- 信息层级:实机的成员头部、6 个围绕罗盘的亲属入口及下方 2 × 2 人物管理区,与设计稿的阅读顺序一致;四个管理入口在 900 × 1600 实机截图中均完整可见。
-- 资产与对比:实机使用纸张底图、人物徽章、关系标记、管理标记、关闭图标、箭头及关系罗盘等生成 PNG 资产;罗盘和边框在真机上没有空白、拉伸或替代图形。
-- 有意保留的 P3 差异:设计稿为贴边并带拖拽把手的轻量面板;实现保留当前家谱页面的左右留白、纸张边框及更细密的罗盘插画,以和已存在的朱红/宣纸视觉系统一致。这不影响层级、可读性或操作入口。
-
-## 真机交互验收
-
-- 初次实机核验发现 `scroll-view` 与头部同层,关闭按钮会被内容层遮挡。已将 `.member-action-panel__head` 提升至 `z-index: 2`;MuMu WebView 点击关闭按钮后,面板节点已消失。
-- MuMu 点击第一个关系入口“父亲”后,已进入“新增亲属 / 为真机联调始祖添加父亲”页面,见 `tmp/jiapu-t01-father-flow.png`;未填写任何字段,并已放弃草稿返回世系图。
-
-## Implementation Checklist
-
-- [x] 已落地选中设计的关系罗盘信息架构。
-- [x] 已生成并引用对应 PNG 资产,未用 emoji、内联 SVG 或 CSS 图形替代。
-- [x] 已捕获 MuMu 实现截图,并与源设计在同一画布中并排对比。
-- [x] 已验证关闭和“父亲”关系入口。
-
-## 第二轮保真收敛(待真机复核)
-
-- 根据 `tmp/t01-relationship-compass-audit-compare.png` 的 P1 差异,已更换为生成的 `t01-action-panel-paper-v3.png` 宣纸面板和 `t01-relation-map-v3.png` 六向连接罗盘;同时移除与设计稿不符的两段区块标题,收紧头部,并将关系按钮与管理卡片改为米纸/朱红配色。
-- 已通过 T01 人物操作面板、文档流、全状态视觉、关系布局、树状态合同及编译审计;生成的透明罗盘与面板资产均已检查 alpha。
-- 复核阻塞:HBuilderX 热更新后 MuMu 返回 A01 登录页,`tmp/t01-relationship-compass-round2.png` 不是人物操作面板,不能用于设计比较。为避免访问或猜测测试账号凭据,本轮没有重新登录。
-- 解除条件:在 MuMu 恢复已授权测试会话后,打开 T01 人物操作面板并重新截图;随后必须与同一张源设计同画布比较,处理任何残留 P1/P2 后才能改回通过。
-
-final result: blocked
-
----
-
-# T01 树状图与 T02 世系谱:真机回归
-
-## 对比对象
-
-- Source visual truth:本次会话中用户提供的参考项目“世系谱”截图(408 × 936 px)及 `C:\Users\Administrator\Desktop\job\Jiapu-App\pages\index\tree\index.vue` 的交互实现。
-- Implementation captures:`C:\Users\Administrator\AppData\Local\Temp\t01-entry-verify.png`、`C:\Users\Administrator\AppData\Local\Temp\t02-entry-verify.png`、`C:\Users\Administrator\AppData\Local\Temp\t02-swipe-verify.png`、`C:\Users\Administrator\AppData\Local\Temp\t02-return-after-fix.png`。
-- Device/state:Android 模拟器 720 × 1280 px;真实家谱“界面大数据回归谱0726”;T01 树状图、T02 第 1/2 世。
-
-## 真机交互验收
-
-- T01 右上角“世系谱”可进入独立 T02 表格页;T02 右上角“树状图”可返回 T01 图谱页。
-- T02 从第 1 世直接左滑可切换到第 2 世,未使用点击箭头替代横向手势。
-- 点击姓名打开“成员档案”;点击下方生平文字读取人物详情并打开“人物生平”弹窗,两个命中区域和结果不同。
-- 返回失败的路由根因已修复:可选 `selectedId` 为空时不再传入 `undefined`,以符合导航参数必须为非空字符串的校验。
-
-## 视觉核验状态
-
-- 字体与排版、列格、纵向文字、朱红页头、右侧世代标识和背景纹理已在真机截图中检查。
-- 当前会话里的参考截图没有可供本地重新打开的原始文件路径,因此无法按同一画布把参考图与实现图合成后做逐像素并排对比;不对像素级一致性作虚假通过结论。
-
-## Implementation Checklist
-
-- [x] 树状图与世系谱拆分为两个路由。
-- [x] 双向页头跳转与原生横向滑动。
-- [x] 姓名资料页与生平弹窗的分离点击行为。
-- [x] HBuilderX 页面诊断、静态路由合约和 Android 真机回归。
-
-final result: blocked
-
----
-
-# T01 树状图与 T02 世系谱:设计核验
-
-## 对比对象
-
-- Source visual truth:用户本次会话提供的参考项目“世系谱”截图,以及 `C:\Users\Administrator\Desktop\job\Jiapu-App\pages\index\tree\index.vue` 的 `swiper` 实现。
-- Implementation capture:未生成。当前 HBuilderX CLI 未识别已连接模拟器作为可部署设备,无法取得包含新 T01/T02 路由的截图。
-- 目标状态:从“世系图”进入 T01 树状图;T01 顶部进入 T02 世系谱;T02 顶部返回 T01。
-
-## 阻塞项
-
-- [P0] 无法取得新版本的真机或浏览器实现截图,因此不能与参考截图进行同视口视觉比较,也不能把直接左右滑动标为已验收。
- - 已完成代码核验:T01 恢复横向树状图;T02 使用原生 `swiper` 和页内纵向 `scroll-view`,每页五位成员。
- - 需要:让 HBuilderX 识别任一已连接模拟器,或提供可运行的 H5 预览,以捕获两页入口和横滑状态。
-
-final result: blocked
diff --git a/docs/APP-136接口功能归属与重复关系-2026-07-26.md b/docs/APP-136接口功能归属与重复关系-2026-07-26.md
deleted file mode 100644
index 5101d9f..0000000
--- a/docs/APP-136接口功能归属与重复关系-2026-07-26.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# APP 136 接口功能归属与重复关系
-
-> 历史快照(2026-07-26,136 条 operation),不再作为当前实施依据。当前根目录导出与桌面 Apifox 均为 149 条 operation,请使用 [APP-149接口页面归属与表单字段审计-2026-07-27.md](APP-149接口页面归属与表单字段审计-2026-07-27.md)。
-
-更新时间:2026-07-26
-
-## 结论
-
-Apifox 当前目录共 136 条:128 条 APP 接口、4 条 APP/PC 共用行政区划接口、4 条旧系统兼容验证接口。
-
-“136 条”不等于 136 个独立页面功能。真正功能重复的只有旧兼容验证/发码链路;列表、分页、详情、选项、管理态接口是同一资源在不同交互下的不同合同,不能擅自删掉或混用。
-
-字段、必填、枚举、请求/响应 DTO 以桌面 Apifox 为准。根目录 `家谱.openapi.json` 只用于核对目录数量和路径,不用其缺失字段推断前端 DTO。
-
-## 一、唯一入口与功能重复
-
-| 分类 | 接口 | 当前唯一使用策略 | 结论 |
-| --- | --- | --- | --- |
-| APP 人机验证 | `GET /genealogy/app/auth/verification/{operationCode}/require`、`POST .../challenge`、`POST .../verify` | A01 密码/短信登录、A04 注册、A05 找回密码,通过 `TacVerification` 与 `utils/auth-verification.js` | 当前 APP 唯一验证链路 |
-| 旧验证码兼容 | `GET /captcha/require`、`POST /captcha/challenge`、`POST /captcha/verify`、`GET /auth/code` | 当前 APP 不调用 | 与 APP 人机验证功能重叠,保留 API 目录记录但不能再接回 A01/A04/A05,避免重复验证 |
-| APP 场景发码 | `POST /genealogy/app/auth/sms/{operationCode}/code` | A01/A04/A05;`operationCode` 是 `password-login`、`sms-login`、`register`、`forgot-password` | 当前 APP 唯一发码链路 |
-| 旧短信发码兼容 | `POST /genealogy/app/auth/sms/code` | 仅 `appApi.sendLegacySmsCode` API 层 owner;没有页面入口 | 与上项发码功能重叠。保留兼容方法供后端指定旧调用方,不得在现有认证页重复发短信 |
-| 行政区划(共享) | `GET /genealogy/region/children`、`/path/{regionCode}`、`/search`、`/{regionCode}` | APP 与 PC 共用;当前 G03/G11 使用 children | 不是旧接口、不是重复接口。其余三条在对应 UI 出现“回填路径/搜索/单项校验”交互后接入 |
-
-## 二、136 条按功能模块归属
-
-| Apifox 模块 | 数量 | 应归属页面/组件 | 备注 |
-| --- | ---: | --- | --- |
-| 验证中心 | 7 | A01、A04、A05、`TacVerification` | 其中 4 条为旧兼容,见上表 |
-| 认证登录 | 12 | A01、A04、A05、M01、M02、M04、M05、M10 | 改密、换绑、注销、退出属于敏感写操作,测试不执行 |
-| 文件上传 | 6 | G03、G11、M02、F02、F06、F07、F09、R04、R07、R08、R10,通过 `resumable-image-upload.js` | 单文件、分片 init/chunk/complete、业务引用绑定/释放各自用途不同 |
-| 行政区划 | 4 | G03 创建家谱、G11 家谱设置 | APP/PC 共用基础查询 |
-| 家谱 | 13 | G01、G03、G05、G06、G08、G09、G10、G11 | 配额、options、详情、审核/撤销等要与具体页面按钮逐项接线,不因已有列表接口视为完成 |
-| 家谱成员 | 6 | 当前没有“家谱成员(账号成员)管理”页面;不要误接到世系人物 T03–T08 | `memberId` 与 `personId` 不是同一 ID。成员管理页/候选 DTO 缺失需单列 |
-| 字辈谱 | 6 | G12 | 正常列表、维护列表、批量预览、批量保存、单条新增/修改是不同操作 |
-| 世系人物 | 12 | T01、T03–T08、R01、R02 | 首位成员创建后端 `code:500` 阻塞;不能伪造 personId |
-| 家族圈 | 14 | F01、F02、F03 | 列表与分页、评论与评论分页、回复与回复分页均非重复;编辑/删除/点赞/回复 UI 需逐项确认 |
-| 内容文章 | 9 | F04、F05、F06、M06、M08 | 谱文分类、帮助详情目前没有已确认页面入口,不能靠列表代替 |
-| 相册 | 7 | F07、F08、F09 | 相册本身与相片记录是两级资源;编辑/删除动作需遵守测试禁止删除边界 |
-| 祭祀 | 8 | R05、R06、R07 | 活动、献礼分别有列表和写入合同 |
-| 族务记录 | 18 | R03、R04、R08、R10、R11 | 成长/备忘/亲友的详情、修改、删除需有明确详情或编辑入口;R09 人生事件没有独立资源合同 |
-| 消息通知 | 4 | N01、G01 未读数 | N02 没有单条详情读取接口;标已读/全部已读不能在未授权测试中触发 |
-| 意见反馈 | 2 | M07 | 列表与提交分别接线 |
-| VIP | 3 | M09 | 套餐、订单列表可读取;创建订单属于支付链路,不执行 |
-| 视频 | 1 | F10 | 仅有删除视频接口,缺少视频列表/详情/上传/播放合同,因此 F10 不能假装可用 |
-| 贺礼邀约 | 4 | R06(活动详情)及“我的活动邀请”入口待产品页面 | 受邀人需要真实 `appUserId`;当前成员/世系 DTO 没有可确认候选来源,不能拿 `memberId` 或 `personId` 猜代 |
-
-以上数量相加为 136。
-
-## 三、共享行政区划的实测合同
-
-桌面 Apifox 已核对:
-
-| 接口 | 必填 | 可选 | 当前 API owner | 页面状态 |
-| --- | --- | --- | --- | --- |
-| `GET /genealogy/region/children` | 无 | `parentCode`(不传或 `0` 为省级) | `appApi.getRegionChildren` | G03/G11 已真实读取 |
-| `GET /genealogy/region/path/{regionCode}` | path `regionCode:string` | `clientid` header | `appApi.getRegionPath` | 暂无“按已存地区回填层级路径”控件 |
-| `GET /genealogy/region/search` | query `keyword:string` | `level: 1..5`、`limit:integer`、`clientid` header | `appApi.searchRegions` | 暂无地区关键字搜索控件 |
-| `GET /genealogy/region/{regionCode}` | path `regionCode:string` | `clientid` header | `appApi.getRegion` | 暂无单项详情校验控件 |
-
-后三条返回 DTO 在桌面文档当前显示为通用对象/列表对象,API 层只校验 envelope 与最外层数组/对象,不擅自猜测内部字段。等页面要消费具体字段时,先在桌面 Apifox 展开响应模型并补严字段校验。
-
-## 四、接线判定标准
-
-一条接口只有同时满足以下三项才标记“页面完成”:
-
-1. `utils/api.js` 有唯一方法 owner,按桌面 Apifox 的必填/可选参数组装请求;
-2. 明确页面按钮、页面加载或组件行为调用该方法,且参数来源不是猜测 ID;
-3. 用浏览器在测试账号和测试数据上做真实请求验证;写入再做列表或详情回读。
-
-仅有 API 方法、或仅页面能打开、或只有导出文件字段,均不算页面完成。
-
-## 五、2026-07-26 浏览器复测结论
-
-- 从 A01 密码登录进入测试账号后,以真实 `genealogyId`、动态、谱文和相册标识运行 `tests/all-page-route-runtime-smoke.js`,52/52 页面均通过;认证态访问 A01 被守卫重定向到 G01 属于预期行为,测试已明确校验该分支。
-- G01 的“世系图、成员、字辈诗、申请审核”四个快捷入口均通过浏览器页面点击复测,分别到达 T01、G05、G12、G10,未捕获运行时异常。
-- T04 再次经页面输入首位成员姓名并提交。请求仍未获服务端确认,页面显示“保存失败 / 发生未知异常,请联系管理员”;未写入本地成员、未生成假 `personId`。该结果继续受“首位成员创建 code:500”阻塞。
-- 该路由复测只验证真实读取、页面状态和既有测试数据;未执行短信、改密、换绑、退出、删除、审核或支付。
-
-## 六、桌面 Apifox 与导出目录核对
-
-桌面 Apifox 本地接口树(2026-07-26 16:56 更新)包含根目录 `家谱.openapi.json` 的全部 136 个 `HTTP method + path`;没有只存在于导出而桌面目录不存在的 operation。导出文件可用于路径、方法和数量的完整审计。
-
-该核对不扩大为 DTO 字段已完整:页面要消费的 body/response 字段、必填、枚举和示例仍以桌面 Apifox 的接口详情为准。若桌面详情未声明条目 DTO 或枚举,前端继续把该字段标为阻塞,而不从导出占位结构猜测。
diff --git a/docs/APP-136请求参数字段核对表-2026-07-26.md b/docs/APP-136请求参数字段核对表-2026-07-26.md
deleted file mode 100644
index 6eb0a36..0000000
--- a/docs/APP-136请求参数字段核对表-2026-07-26.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# APP 136 请求参数字段核对表
-
-更新时间:2026-07-26
-
-## 使用规则
-
-- 路径和 operation 数量以桌面 Apifox 当前 APP 目录为准;本机已核对根目录 `家谱.openapi.json` 的 136 个 `method + path` 均存在于桌面目录。
-- 下表字段来自该次导出快照,用于逐项核对前端 consumer。桌面 Apifox 若显示更严格的 required、枚举、长度、oneOf 或条目 DTO,以桌面详情覆盖本表并重新导出。
-- `int64` 在 H5 JSON 中不得强制转换为 JavaScript `number`。真实雪花 ID 超过安全整数范围时,必须由后端改为十进制字符串合同,不能截断或猜测。
-- “阻塞”表示前端没有安全的参数来源、DTO、operation 或服务端成功响应;不是用本地默认值补齐的许可。
-
-## 公共路径与查询参数
-
-| operation 类别 | 必填 | 可选 | 当前页面/状态 |
-| --- | --- | --- | --- |
-| 绝大多数 `/genealogy/app/**` | Header `clientid` | 当前登录 bearer | API 请求层统一注入;实际浏览器验证 |
-| 资源路径 `/{genealogyId}` | path `genealogyId` | — | 所有家谱内页面从真实当前家谱上下文取得 |
-| 世系资源 `/{personId}` | path `personId` | — | T03–T08、R01–R02 被首位成员 `code:500` 阻塞 |
-| 动态资源 `/{feedId}` | path `feedId` | — | F01/F03 实际读取;点赞状态 DTO 阻塞 |
-| 谱文/相册/礼仪/记录资源 ID | 对应 path ID | — | 已有真实测试数据的列表/详情/创建按页面验证;编辑/删除需要产品入口或受测试边界限制 |
-| 分页 | `pageNum`、`pageSize` 在 Apifox 均为可选 | keyword、generation、status 等按各 operation | 没有页面分页交互时不以默认假分页替代 |
-| 行政区划搜索 | query `keyword` | `level` 1–5、`limit` | `children` 已在 G03/G11 实读;其余三个尚无对应交互控件 |
-
-## 写入 body 字段
-
-星号为当前导出中的 required 字段。没有写入页面、稳定候选 ID 或枚举的字段均明确列为阻塞,不能手填内部 ID。
-
-| Schema / operation | 页面 | 必填字段 | 可选字段 | 当前消费结论 |
-| --- | --- | --- | --- | --- |
-| `VerificationChallengeBody`(challenge) | A01/A04/A05 | `tenantId`、`subject` | — | 已接验证组件 |
-| `VerificationCheckBody`(verify) | A01/A04/A05 | `tenantId`、`subject`、`challengeId` | `providerCode`、`captchaType`、`payload` | provider 细节以桌面 TAC DTO 为准 |
-| `PasswordRegisterBody` | A04 | `grantType`、`tenantId`、`phone`、`password`、`smsCode` | `nickName`、`registerSource` | 短信写入未执行(测试边界) |
-| `PasswordLoginBody` | A01 | `grantType`、`tenantId`、`phone`、`password` | `validToken` | 已真实登录 |
-| `SmsLoginBody` | A01 | `grantType`、`tenantId`、`phone`、`smsCode` | — | 短信写入未执行 |
-| `SmsCodeBody` | A01/A04/A05 | `grantType`、`tenantId`、`phone` | `validToken` | 场景路径已接;未发短信 |
-| `ProfileUpdateBody` | M02 | — | `nickName`、`avatarOssId`、`sex`、`birthday`、`provinceCode`、`cityCode`、`districtCode` | 头像 `ossId` 类型冲突;字典/地区回填 DTO 需桌面详情确认 |
-| `PasswordChangeBody` | M04 | `oldPassword`、`newPassword` | — | 敏感操作,不执行 |
-| `PasswordResetBody` | A05 | `grantType`、`tenantId`、`phone`、`smsCode`、`newPassword` | — | 短信/改密不执行 |
-| `PhoneChangeBody` | M05 | `phone`、`smsCode` | — | 敏感操作,不执行 |
-| `AccountDeactivateBody` | M10 | `smsCode` | — | 敏感操作,不执行 |
-| `ResumableInitBody` | 上传组件 | 实际服务端:`uploadId`、`fileName`、`fileMd5`、`totalSize`、`chunkSize`、`totalChunks` | `contentType` | 导出快照写为 `fileSize` 且漏 `uploadId`;真实请求省略 `uploadId` 返回“上传ID不能为空”,改用 `fileSize` 返回“文件大小不能为空”。前端只按已验证的实际契约发送,等待 Apifox 统一(B17) |
-| `ResumableCompleteBody` | 上传组件 | 实际已验证链路:`uploadId`、`fileName`、`fileMd5`、`totalSize`、`totalChunks` | — | 导出快照与实际字段冲突待后端统一;回执 `ossId` 仍为不安全 19 位字符串 |
-| `FileReferenceBody` | 业务附件 | `bizType`、`bizTable`、`bizId`、`bizField` | `bizName`、`ossId`、`ossIds`、`usageScene`、`usageName` | 缺稳定业务表/字段 owner,且 `ossId` 类型冲突;不能猜绑定 |
-| `GenealogyCreateBody` | G03 | `genealogyName`、`surname`、`regionCode` | `ancestralHall`、`originPlace`、`addressDetail`、`coverOssId`、`intro`、`visibility`、`joinMode` | 已真实创建/回读;封面受 `ossId` 阻塞 |
-| `GenealogyUpdateBody` | G11 | — | 与创建同名字段 | 读取已接;写入需页面确切 dirty/权限合同 |
-| `GenealogyJoinApplyBody` | G08 | — | `applicantName`、`phone`、`relationDesc`、`applyReason`、`inviterUserId` | 已真实申请列表回读;内部邀请人 ID 无候选来源 |
-| `GenealogyJoinAuditBody` | G10 | `status` | `auditRemark` | 审核为敏感操作,不执行 |
-| `GenealogyMemberUpdateBody` | 无独立成员管理页 | — | `memberName`、`relationName`、`roleType`、`lineagePersonId` | `memberId` 非 `personId`;不得误接世系页 |
-| `GenealogyOwnerTransferBody` | 无 | `targetMemberId` | — | 缺成员候选与产品入口,不能手填 ID |
-| `GenerationPoemBody` | G12 | `generationNo`、`generationText` | `description`、`sortOrder`、`status` | 已真实维护/回读 |
-| `GenerationPoemBatchBody` | G12 | `poemText` | `disableMissing` | 已真实预览/保存回读 |
-| `LineagePersonBody` | T04/T05/T06、R02 | `name`、`bindingMode` | `appUserId`、`personNo`、`aliasName`、`sex`、`generation`、`generationName`、`fatherId`、`motherId`、`avatarOssId`、`birthDate`、`birthLunar`、`birthPlace`、`deathDate`、`deathLunar`、`deathPlace`、`burialPlace`、`personStatus`、`biography`、`sortOrder`、`remark`、`relationName` | `bindingMode` 固定为 `NONE` / `SELF` / `SPECIFIED`:前两者禁止提交 `appUserId`,后者必须提交;`SELF` 后端从 Token 获取当前用户。页面默认 `NONE`;`SPECIFIED` 仍缺可信候选接口。实测 `NONE` 无 `appUserId` 的新增子女仍返回业务 `code:500`,等待后端排查新版写接口 |
-| `FamilyFeedBody` | F02/F03 编辑入口缺失 | `feedContent` | `feedType`、`mediaOssIds`、`sortOrder`、`status` | 文本动态已真实创建/回读;媒体受 `ossId` 阻塞;编辑无产品入口 |
-| `FamilyFeedCommentBody` | F03 | `commentContent` | `parentCommentId` | 一级评论已真实创建/回读;回复 UI 未设计 |
-| `ArticleBody` | F06 | `articleTitle`、`articleContent` | `categoryId`、`articleSummary`、`coverOssId`、`authorName`、`sortOrder`、`status` | 已真实创建/回读;分类条目 DTO、封面 `ossId` 阻塞 |
-| `AlbumBody` | F07 | `albumName` | `albumDesc`、`coverOssId`、`sortOrder`、`status` | 已真实创建/回读;封面 `ossId` 阻塞 |
-| `AlbumPhotoBody` | F09 | `ossId` | `photoTitle`、`photoDesc`、`photographer`、`shootTime`、`sortOrder`、`status` | 上传回执成功,但 `ossId` JSON 类型冲突,不能创建照片记录 |
-| `CeremonyBody` | R07 | `ceremonyType`、`ceremonyTitle` | `ceremonyDesc`、`ceremonyTime`、`location`、`locationAddress`、`longitude`、`latitude`、`coverOssId`、`sortOrder`、`status` | 已真实创建/回读;封面受 `ossId` 阻塞 |
-| `CeremonyGiftBody` | R06 | `giftAmount` | `giverName`、`giftMessage` | 礼仪详情/献礼读取已接;写入需从真实礼仪 ID 进入 |
-| `GrowthRecordBody` | R08 | `recordTitle` | `lineagePersonId`、`recordType`、`recordContent`、`recordDate`、`remindTime`、`mediaOssIds`、`sortOrder`、`status` | 无真实 personId 时人物归属不能填;非人物字段已真实创建/回读 |
-| `MemoBody` | R10 | `memoTitle` | `memoContent`、`remindTime`、`completed`、`mediaOssIds`、`sortOrder`、`status` | 已真实创建/回读;附件受 `ossId` 阻塞 |
-| `RelativeRecordBody` | R04 | `relativeName` | `relationName`、`eventName`、`eventTime`、`giftAmount`、`recordContent`、`mediaOssIds`、`sortOrder`、`status` | 已真实创建/回读;附件受 `ossId` 阻塞 |
-| `MeritRecordBody` | R11 | `donorName`、`meritTitle` | `meritType`、`meritContent`、`amount`、`meritTime`、`sortOrder`、`status` | 已真实创建/回读 |
-| `FeedbackBody` | M07 | `feedbackContent` | `feedbackType`、`contactInfo` | 已真实提交/读取 |
-| `VipOrderBody` | M09 | `packageId` | `genealogyId`、`payType` | 创建订单属于支付,不执行 |
-| `CeremonyInviteesBody` | R07/R06 | `inviteeUserIds` | — | 缺 `appUserId` 候选列表;不能用 member/person ID 猜代 |
-| `CeremonyInvitationResponseBody` | 我的活动邀请页缺失 | `inviteStatus` | — | 枚举仅 `ACCEPTED`/`DECLINED`;需要产品入口和真实邀请 |
-
-## 后端需要优先确认的统一规则
-
-1. 所有 `int64` 在 APP JSON 请求/响应中是否统一为十进制字符串;至少要覆盖 `ossId`、所有资源 ID、`appUserId`、`memberId`、`personId`、`categoryId` 和 `packageId`。
-2. 所有“建议使用字典值”的字段必须在 Apifox 给出 enum 或独立 options operation,特别是 `sex`、`personStatus`、`roleType`、`status`、`visibility`、`joinMode`、`payType`。
-3. 任何需要选择内部用户/成员/人物的操作必须返回明确且同类型的候选 ID,禁止要求客户端用不同资源的 ID 猜代。
-4. 上传完成回执和所有消费 `ossId` 的 DTO 必须同版修复;否则上传成功并不等于业务图片创建成功。
-5. 分片上传 init/complete 的 Apifox 导出字段必须与实际服务端校验一致:当前实测要求 `uploadId` 与 `totalSize`,而导出写为 `fileSize` 且未声明 `uploadId`;不得要求客户端同时发送两套互斥字段。
diff --git a/docs/APP-149接口页面归属与表单字段审计-2026-07-27.md b/docs/APP-149接口页面归属与表单字段审计-2026-07-27.md
deleted file mode 100644
index 981c887..0000000
--- a/docs/APP-149接口页面归属与表单字段审计-2026-07-27.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# APP 149 接口页面归属与表单字段审计
-
-更新时间:2026-07-27
-
-## 一、唯一依据与结论
-
-- 唯一接口源:根目录 `家谱.openapi.json`;桌面 Apifox `APP` 概览同步显示 **149** 条 operation、88 个数据模型。
-- 这 149 条不是 149 个页面。页面、认证/上传底层流程、管理操作、兼容旧接口共同构成目录,不能因为没有对应按钮就假称“未对接”,也不能把内部 ID、验证码或支付参数渲染成普通表单。
-- 当前核对结果:已存在页面和 API owner 的资源继续按现有页面操作验证;本次已修复 M02、M07、G08、R07 四个确定的字段控件/适配错误。视频发布已接入 F10;视频和官网内容的读取响应仍没有可安全消费 DTO,因此不能伪造列表或详情卡片。
-- 所有真实写入验证只允许在页面中选择、输入、提交并做列表/详情回读;不使用后台请求构造数据。短信、改密、换绑、退出、删除、审核、支付、注销不做测试写操作。
-
-## 二、149 条按 Apifox 模块归属
-
-| 模块 | 条数 | 页面或唯一 owner | 当前判定 |
-| --- | ---: | --- | --- |
-| 验证中心 | 7 | A01/A04/A05,`utils/auth-verification.js` | APP 行为验证为认证流程内部参数;旧 `/captcha/*` 与 `/auth/code` 是兼容链路,无新页面入口。 |
-| 认证登录 | 12 | A01/A04/A05、M01、M02、M04/M05/M10 | 登录、注册、资料读取/更新有页面;敏感账号写操作保留但不测。 |
-| 文件上传 | 6 | `utils/resumable-image-upload.js`、各图片选择页 | 上传初始化、分片、完成、引用绑定/释放是技术流程,`ossId` 由回执拥有,不是手填字段。 |
-| 行政区划 | 8 | G03/G11,`appApi.getRegion*` | `/genealogy/region/*` 是 APP/PC 共享 4 条;`/genealogy/app/region/*` 为同能力 APP 副本,当前统一用共享 owner,不能双接线。 |
-| 家谱 | 13 | G01、G03、G05–G11 | 列表、详情、公开搜索、申请、审核、配额、options 分属不同交互,不能互相替代。 |
-| 家谱成员 | 6 | API owner 已有;暂无独立账号成员管理页 | `memberId` 不等于世系 `personId`;成员管理/转让/移除不映射到 T 系页面。 |
-| 字辈谱 | 6 | G12 | 列表、管理、单条维护、批量预览和批量保存均保留。 |
-| 世系人物 | 12 | T01、T03–T08、R01/R02 | 首位成员创建仍须以页面实测为准;未得到真实 `personId` 前不伪造成员或关系。 |
-| 家族圈 | 14 | F01–F03 | 动态、评论、回复、点赞、分页是不同资源动作。删除不测试。 |
-| 内容文章 | 9 | F04–F06、M06、M08 | 谱文已有创建/读取;分类列表条目 DTO 未声明,分类 ID 不能手输或猜字段。 |
-| 相册 | 7 | F07–F09 | 相册和照片是两级资源;上传回执后写入,删除不测试。 |
-| 祭祀 | 8 | R05–R07 | 活动及献礼分别由列表、详情、编辑页拥有。 |
-| 族务记录 | 20 | R03/R04、R08、R10、R11 | 亲友、成长、备忘、功德是四类独立资源;人生事件没有单独写资源时不伪造。 |
-| 消息通知 | 5 | N01、G01 未读数 | 读取有 owner;标读为状态写,不在本轮测试。 |
-| 意见反馈 | 2 | M07 | 已修正为接口枚举 value 提交。 |
-| VIP | 3 | M09 | 套餐/订单读取可用;下单属于支付链路,不测试。 |
-| 视频 | 5 | F10 | 已接入上传、创建及 API owner 的 CRUD 路径;列表/详情响应未声明 DTO,页面不假造卡片字段。 |
-| 贺礼邀约 | 4 | R06 及未来“我的邀请”页 | 受邀人数组必须来自业务用户候选;不能用成员/人物 ID 冒充。 |
-| 官网内容 | 2 | M10 的协议/说明未来可用 | 见“阻塞”B05:响应体未声明,不能将当前静态说明误报为已接线。 |
-
-## 三、表单字段的统一处理规则
-
-| 字段类别 | 页面处理 | 传输规则 |
-| --- | --- | --- |
-| `required` 文本/多行文本 | 显示必填标识并做空值校验 | 只传去空白后的真实输入。 |
-| 有 `enum` 的 string | 中文标签的单选/下拉 | 只提交 enum value,绝不提交中文标签。 |
-| `date` 或写例 `yyyy-MM-dd` | 日期选择器 | 提交 `yyyy-MM-dd`。 |
-| 日期时间字符串 | 日期 + 时间选择器 | 只有用户已选择日期时组装 `yyyy-MM-dd HH:mm:ss`。 |
-| 候选 ID | 由 options/list 返回项选择 | 不显示内部 ID 自由输入;没有候选 DTO/接口则隐藏该字段并记录阻塞。 |
-| `*OssId`、`mediaOssIds` | 统一上传控件 | 只使用上传回执;不允许键盘输入。 |
-| `status`、`completed` 等管理/字典字段 | 创建表单默认省略,除非当前页面有明确管理权限且文档给出枚举 | 不把“停用”“完成”猜成前台默认开关。 |
-| token、`clientid`、`tenantId`、`grantType`、验证码票据、分片 hash | 永不显示 | 由 session、运行时配置、验证或上传 owner 自动生成。 |
-
-## 四、已有页面的重点 body 字段矩阵
-
-| 页面/接口 | 必填字段 | 可填写字段 | 选择/自动/隐藏字段 | 当前实现结论 |
-| --- | --- | --- | --- | --- |
-| M02 `PUT /auth/profile` | 无 | `nickName`、`realName`、`email` | `sex`:男 `0`/女 `1`/未知 `2`;`birthday`:日期;`avatar`:上传回执 | 已修正性别选择器,适配器拒绝非 `0/1/2`。 |
-| M07 `POST /feedback` | `feedbackContent` | `contactInfo` | `feedbackType`:建议 `advice`/功能问题 `bug`/投诉 `complaint`/其他 `other` | 已修正为中文显示、枚举 value 提交。 |
-| G03/G11 家谱创建/修改 | 创建:`genealogyName`、`surname`、`regionCode` | 堂号、籍贯、地址、简介 | 地区:三级行政区划选择;封面:上传;可见性/加入方式:枚举选择 | 保留页面已有 owner。 |
-| G08 `POST .../join-applies` | 无 | 申请人姓名、手机号、关系说明、申请理由 | `inviterUserId`:只有业务用户候选时才可选;当前隐藏 | 已删除“邀请人编号”手输框;适配器保留字段以供未来真实候选使用。 |
-| T04/T05 与亲属写入 `LineagePersonBody` | `name`、`bindingMode` | 姓名、别名、编号、字辈、地点、生平、备注、排序 | 性别 `0/1/2`、农历 `0/1`、人物状态 `0/1/2`、父母为人物 options、头像上传;`SELF`/`NONE` 不传 `appUserId`,`SPECIFIED` 必须由可信业务用户候选选择 | 页面已有选择器与白名单;首位成员后端业务 `code:500` 曾阻塞,必须用页面重试和回读确认。 |
-| F02 动态 | `feedContent` | 内容、排序 | 类型固定自动 `text`;多媒体由上传回执;状态不在普通创建页展示 | 页面显示“文字动态”。 |
-| F06 谱文 | `articleTitle`、`articleContent` | 摘要、作者、正文、排序 | 封面上传;`categoryId` 必须分类候选选择 | 分类列表没有条目 DTO,不能猜 `id/label`,暂不展示分类选择。 |
-| F07/F09 相册与照片 | 相册名;照片 `ossId` | 描述、标题、摄影者、拍摄时间、排序 | OSS 均来自上传;状态默认省略 | 已有创建后回读路径。 |
-| R04 亲友往来 | `relativeName` | 关系、事件、时间、金额、正文、排序 | 多媒体上传;状态默认省略 | 可选字段不被前端强制必填。 |
-| R07 礼仪活动 | `ceremonyType`、`ceremonyTitle` | 说明、日期时间、地点、详细地址、排序 | 封面上传;经纬度仅地图组件成对回填,当前隐藏;状态默认省略 | 适配器已接收 `locationAddress`,若未来传坐标会校验经纬度成对。 |
-| R08 成长记录 | `recordTitle` | 类型、正文、日期、提醒、排序 | `lineagePersonId` 只可选真实人物;媒体上传;状态默认省略 | 无真实人物前保留为空。 |
-| R10 备忘 | `memoTitle` | 正文、提醒、排序 | `completed` 无 enum,默认省略;媒体上传 | 不伪造完成开关。 |
-| R11 功德 | `donorName`、`meritTitle` | 正文、金额、时间、排序 | 类型:`donation`/`repair`/`public`/`other`;状态默认省略 | 现有选择器使用接口 value。 |
-| F10 视频 | `videoTitle`、`videoOssId` | 视频标题、说明 | 视频文件:上传回执自动填充;封面、时长、排序、状态:创建页隐藏 | 已接入视频选择、分片上传和创建;不允许手填 OSS ID。 |
-
-## 五、不能直接补成页面的阻塞项
-
-| 编号 | 接口/字段 | 已知请求或返回事实 | 前端处理与需要后端补充 |
-| --- | --- | --- | --- |
-| B01 | 首位成员 `POST .../lineage/persons` | 页面最小合法 body 曾返回 HTTP 200、envelope `code:500`、`发生未知异常,请联系管理员`;没有成功返回 `personId` | 后端修复后,必须从 T04 页面提交并回读 T01/T03,不能后台造成员。 |
-| B02 | `LineagePersonBody.bindingMode=SPECIFIED` | `appUserId` 条件必填,但现有 APP 没有“可信业务用户候选”读取合同 | 保留 NONE/SELF;补业务用户 options DTO 后才开放指定绑定。 |
-| B03 | 谱文分类 `GET .../article-categories` | operation 有列表路径,但当前导出没有可消费的条目字段模型 | 后端给出分类项的 `id`、显示名及响应 schema;前端再做选择器。 |
-| B04 | 视频 GET/GET detail | `VideoBody` 请求要求 `videoTitle`、`videoOssId`;F10 已可选择视频、上传并创建,当前 200 读取响应仍未声明字段 | 后端补 `VideoView`/列表 rows 的完整响应 DTO,并确认播放地址与封面读取合同;前端再展示视频列表、详情和播放。 |
-| B05 | 官网内容 GET `/site/articles`、`/site/pages/{pageKey}` | 当前 200 响应 schema 未声明 | 后端补文章/页面 key、标题、正文、更新时间等 DTO;M10 才能替换静态说明。 |
-| B06 | 礼仪坐标 | `longitude`、`latitude` 可选且必须成对;没有地图选点或坐标来源 operation | 提供地图/地理编码集成合同,或明确允许何种受控坐标来源;不让用户手输。 |
-| B07 | 贺礼邀约 `inviteeUserIds` | 必填业务用户 ID 数组;成员和世系人物 options 不能证明等同业务用户 | 发布受邀业务用户候选接口与 DTO。 |
-| B08 | `completed`、`payType`、审核 status | 当前 schema 未给可安全映射的全部 value-label 语义 | 后端补 enum 或字典 options;前端保持隐藏/不测。 |
-
-## 六、验证记录
-
-- 本轮代码静态/适配器验证通过:`lineage-openapi-contract`、`feedback-openapi-contract`、`profile-pages-contract`、`m07-feedback-submit-contract`、`g08-g10-application-flow-contract`、`r-business-flow-contract`、`form-enum-api-runtime-smoke`、`oss-id-payload-api-runtime-smoke`、`compile-audit`。
-- 这些验证不替代真实写入。下一阶段在浏览器完成接口详情核对后,仅在测试账号的页面内输入、选择、提交和回读;敏感操作继续跳过。
diff --git a/docs/APP-150项目接口覆盖与功能缺口总清单-2026-07-28.md b/docs/APP-150项目接口覆盖与功能缺口总清单-2026-07-28.md
deleted file mode 100644
index c9a3966..0000000
--- a/docs/APP-150项目接口覆盖与功能缺口总清单-2026-07-28.md
+++ /dev/null
@@ -1,118 +0,0 @@
-# APP-150 项目接口覆盖与功能缺口总清单
-
-更新时间:2026-07-28
-唯一接口依据:仓库根目录 `家谱.openapi.json`(149 个 operation)。
-
-## 1. 阅读方式与结论
-
-“没有接口”“接口已接但没功能”“接口不应有单独页面”是三件不同的事。本清单将其分开记录:
-
-- **后端合同缺口**:OpenAPI 没有足够的请求/响应字段,前端不能猜测实现。
-- **前端功能缺口**:`utils/api.js` 已有请求 owner,但没有页面入口或用户动作调用它。
-- **技术/敏感操作**:由登录、上传、会话、确认弹窗等 owner 自动调用;不做独立表单。
-
-当前结论:149 个 operation 均已完成归属;视频发布已接通。项目仍有 9 项后端合同缺口、14 组 API 已有但页面功能未接通的缺口,详见第 3、4 节。
-
-## 2. 全量模块归属(149 个 operation)
-
-| 模块 | 数量 | 当前 owner | 状态 | 说明 |
-| --- | ---: | --- | --- | --- |
-| 验证中心 | 7 | A01/A04/A05、`auth-verification.js` | 已归属 | APP 验证是认证内部流程;`/captcha/*`、`/auth/code` 为兼容接口。 |
-| 认证登录 | 12 | A01/A04/A05、M01/M02/M04/M05/M10 | 部分功能缺口 | 登录、注册、资料、改密、退出有 owner;换绑/注销见第 4 节。 |
-| 文件上传 | 6 | `resumable-image-upload.js` | 已归属 | 初始化、分片、完成、引用释放均是上传 owner;OSS ID 不可手填。 |
-| 行政区划 | 8 | G03/G11、`appApi.getRegion*` | 已归属 | APP 与共享版本各 4 条,当前只消费一套,不能双接。 |
-| 家谱 | 13 | G01/G03/G05–G12 | 部分功能缺口 | 创建、读取、设置、申请流程有 owner;申请审核/撤销需补实际动作。 |
-| 家谱成员 | 6 | `appApi` | 无页面 owner | `memberId` 是账号成员,不是世系 `personId`;不能放进 T 系页面。 |
-| 字辈谱 | 6 | G12 | 部分功能缺口 | 读取、创建、批量预览/保存有 owner;单条修改/停用需补页面动作。 |
-| 世系人物 | 12 | T01、T03–T08、R01/R02 | 后端阻塞 | 页面/API 已有;首位人物创建、指定绑定候选仍受合同阻塞。 |
-| 家族圈 | 14 | F01–F03 | 部分功能缺口 | 发布、读取、点赞、评论有 owner;编辑/删除与回复发布尚未形成页面流程。 |
-| 内容文章 | 9 | F04–F06、M06/M08 | 部分功能缺口 | 读取/新增有 owner;分类 DTO、编辑/删除动作待补。 |
-| 相册 | 7 | F07–F09 | 部分功能缺口 | 创建、读取、上传照片有 owner;相册编辑/删除、照片删除待补。 |
-| 祭祀 | 8 | R05–R07 | 部分功能缺口 | 创建、读取、献礼新增有 owner;修改/删除、地图与邀请待补。 |
-| 族务记录 | 20 | R03/R04、R08、R10/R11 | 部分功能缺口 | 新增/读取有 owner;多项编辑、删除、媒体入口待补。 |
-| 消息通知 | 5 | N01/N02、G01 | 部分功能缺口 | 列表、详情、未读数有 owner;标记已读动作待补。 |
-| 意见反馈 | 2 | M07 | 部分功能缺口 | 提交有 owner;“我的反馈”列表无页面。 |
-| VIP | 3 | M09 | 部分功能缺口 | 套餐/订单读取有 owner;创建订单未形成受控支付流程。 |
-| 视频 | 5 | F10、`appApi` | 后端合同缺口 | 上传、创建和 CRUD API owner 已接;列表/详情 DTO 缺失。 |
-| 贺礼邀约 | 4 | R06、`appApi` | 后端合同缺口 | API owner 有;缺业务用户候选与“我的邀请”页面。 |
-| 官网内容 | 2 | M10 | 后端合同缺口 | 响应无 DTO,不能替换当前静态说明。 |
-
-## 3. 后端 / OpenAPI 必须补充的合同(不能由前端猜)
-
-| ID | 相关接口/字段 | 现状 | 缺少的合同 | 前端当前处理 | 优先级 |
-| --- | --- | --- | --- | --- | --- |
-| C01 | `GET /genealogies/{genealogyId}/videos`、`GET .../videos/{videoId}` | 只有通用响应,无可消费视频字段 | `VideoView`:`videoId`、标题、说明、视频播放 URL、封面 URL、时长、创建时间、状态 | F10 可上传并创建,不渲染列表/播放器 | P0 |
-| C02 | `POST /lineage/persons` 首位成员 | 页面最小合法请求曾收到业务 `code:500` | 后端修复创建逻辑,并返回可回读的 `personId` | T04 不伪造首位人物 | P0 |
-| C03 | `LineagePersonBody.bindingMode=SPECIFIED` | `appUserId` 条件必填 | 可信业务用户候选接口及 DTO,明确用户 ID 与人物关系 | 仅开放 `NONE` / `SELF` | P1 |
-| C04 | `GET .../article-categories` | 列表 response 未定义条目字段 | 分类 `id`、显示名、状态、排序 DTO | F06 隐藏分类选择,不能手输 `categoryId` | P1 |
-| C05 | `GET /site/articles`、`GET /site/pages/{pageKey}` | response 未定义 | 文章/页面 key、标题、正文、更新时间、链接 DTO | M10 保留静态内容 | P1 |
-| C06 | 礼仪 `longitude`、`latitude` | 两字段须成对,但无位置来源 | 地图选点或地理编码合同;坐标精度/坐标系说明 | R07 隐藏坐标手输 | P2 |
-| C07 | 活动 `inviteeUserIds` | 需要业务用户 ID 数组 | 可邀请业务用户候选接口、显示名、可邀请条件 DTO | R06 不提交猜测 ID | P1 |
-| C08 | `completed`、`payType`、部分审核/管理状态 | 字典含义或可用范围不足 | 完整 enum/value-label 与权限规则 | 创建页默认不显示管理开关 | P2 |
-| C09 | 家族圈评论回复 | 只有回复列表接口,没有声明创建回复的操作或父评论字段 | 回复创建 endpoint 与请求体(至少评论内容、父评论 ID) | F03 仅展示现有评论,不提供假回复提交 | P1 |
-
-## 4. API 已有,但页面功能尚未接通
-
-以下项的 `appApi` 已有对应请求 owner;静态检索未发现页面调用,或页面只展示静态/只读状态。实现前需确认权限与交互,不应直接暴露内部 ID。
-
-| ID | 操作 | 当前缺少的页面功能 | 建议页面/入口 | 前置条件 |
-| --- | --- | --- | --- | --- |
-| F01 | `PUT/DELETE .../feeds/{feedId}` | 编辑、删除本人动态 | F03 动态详情 | 必须仅显示本人有权操作的按钮。 |
-| F02 | `DELETE .../comments/{commentId}` | 删除本人评论/删除占位展示 | F03 评论区 | 有回复时按后端返回的删除占位渲染。 |
-| F03 | `PUT/DELETE .../articles/{articleId}` | 谱文编辑、删除 | F05/F06 | 分类 DTO 到位后,编辑页才开放分类选择。 |
-| F04 | `PUT/DELETE .../albums/{albumId}` | 相册编辑、删除 | F07/F08 | 删除需二次确认并遵循后端权限。 |
-| F05 | `DELETE .../albums/{albumId}/photos/{photoId}` | 删除照片 | F08 | 仅作者/管理者显示。 |
-| F06 | `PUT/DELETE .../ceremonies/{ceremonyId}` | 礼仪编辑、删除 | R06/R07 | 地图字段仍按 C06 处理。 |
-| F07 | `DELETE .../ceremonies/{ceremonyId}/gifts/{giftId}` | 删除献礼 | R06 | 需明确献礼人/管理员权限。 |
-| F08 | 成长、备忘、亲友、功德的 `PUT/DELETE` | 记录编辑、删除 | R08/R10/R04/R11 | 目前新建/读取与编辑动作未闭环。 |
-| F09 | `PUT .../generation-poems/{poemId}` | 修改、停用、恢复单条字辈 | G12 | 需按 `status` 枚举和管理权限显示。 |
-| F10 | 家谱成员 6 条 | 成员列表、成员资料、移除、退出、转让 | 新建“成员管理”页 | 严格使用 `memberId`,绝不能复用世系人物 UI。 |
-| F11 | 加入申请审核、撤销 | 审核/撤销提交动作与结果回读 | G09/G10 | 需确认当前用户角色,敏感写操作必须二次确认。 |
-| F12 | 通知标已读、全部已读 | 单条/全部已读行为 | N01/N02 | 标读应静默回写列表,不弹假成功。 |
-| F13 | `GET /feedback` | “我的反馈”列表 | M07 或新建 M11 | response DTO 足够时展示,不开放删除。 |
-| F14 | 换绑、注销、VIP 创建订单 | 安全表单/支付确认链路 | M05/M10/M09 | 短信验证、支付回调、二次确认不可省略。 |
-
-## 5. 没有可新增接口的页面功能
-
-| 页面 | 原因 | 需要的后端资源 |
-| --- | --- | --- |
-| R09 人生大事 | OpenAPI 149 条中没有人生事件资源的 CRUD | 人生事件列表、详情、新增、修改、删除;需定义归属人物、事件日期、事件类型、内容、媒体字段。 |
-| F10 视频列表/播放 | 已有路径但读取 DTO 不完整,等同不可安全实现 | 见 C01。 |
-| “我的活动邀请” | 读取接口有 owner,但没有页面和邀请候选数据 | 邀请页面、C07 候选 DTO;现有 `GET .../ceremony-invitations/mine` 可作为入口。 |
-| 家谱成员管理 | 后端路径完整但无页面信息架构 | 成员管理页面及权限/成员 DTO展示规则。 |
-
-## 6. 不是“少页面”的接口(保持自动或受控)
-
-| 接口类别 | 正确 owner | 不应暴露的字段/原因 |
-| --- | --- | --- |
-| 验证挑战、验证校验、短信发送 | `auth-verification.js`、认证页 | `validToken`、challenge、验证码票据由认证流程持有。 |
-| 文件初始化、分片、完成、引用 | 上传工具 | `uploadId`、MD5、chunkIndex、OSS ID 都是上传回执/技术参数。 |
-| `clientid`、token、tenantId | `config.js`、session | 运行时认证信息,绝不能做表单字段。 |
-| 行政区划 APP/共享重复路径 | `appApi.getRegion*` | 只选择一个 owner,避免同一功能双请求。 |
-| 删除、审核、退出、注销、支付 | 现有页面的明确二次确认流程 | 不应为“接口覆盖率”而自动触发真实写操作。 |
-
-## 7. 表单字段总规则
-
-| 字段类型 | 表单处理 |
-| --- | --- |
-| OpenAPI `required` 文本 | 显示必填标识,提交前 trim 校验。 |
-| `enum` 字符串 | 使用中文标签的选择器,仅提交 enum value。 |
-| 日期/日期时间 | 使用日期或日期+时间选择器;不能自由输入格式。 |
-| 候选 ID | 必须由 options/list 选择;缺候选 DTO 时隐藏,不允许手输。 |
-| `*OssId`、`mediaOssIds` | 只从上传回执获取;视频同样适用。 |
-| `status`、`completed`、排序、审核、支付字段 | 默认不出现在普通创建表单;只在明确管理权限和完整字典合同下出现。 |
-| 认证、分片、路径 ID | 自动生成/路由携带;不可显示或编辑。 |
-
-## 8. 推荐实施顺序
-
-1. 后端先完成 C01、C02:视频可展示播放、世系首位人物可创建,才能闭合两个主要入口。
-2. 补 C03、C04、C07:所有候选 ID 都能选择而不是手填。
-3. 实施 F11(成员管理)和 F12(申请审核/撤销),先补清晰的权限和确认流程。
-4. 实施 F01–F10 的编辑/删除闭环;每一项均先做“当前用户是否有权”的详情回读。
-5. 处理 C05、C06、C08 与 R09,完成官网内容、地图、字典和人生事件的新增合同。
-
-## 9. 验证边界
-
-- 本文是接口和代码静态审计,不代表所有写接口已经在生产环境执行。
-- 真实写入必须在测试账号、对应页面中操作,再通过列表/详情回读验证;不得用脚本绕过页面构造业务数据。
-- 当前视频测试文件为 `C:\Users\Rain\Desktop\9d063f4536624f6b1ccb4d2cb9e9786c.mp4`;已确认存在且为非空 MP4。真实上传需在登录态下从 F10 的系统文件选择器选择它。
diff --git a/docs/APP表单控件与接口字段审计-2026-07-26.md b/docs/APP表单控件与接口字段审计-2026-07-26.md
deleted file mode 100644
index 424b234..0000000
--- a/docs/APP表单控件与接口字段审计-2026-07-26.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# APP 表单控件与接口字段审计
-
-更新日期:2026-07-26
-依据:桌面 Apifox APP 合同、`家谱.openapi.json`、当前页面真实表单代码。
-
-## 判定规则
-
-| 字段性质 | 页面控件 |
-| --- | --- |
-| 自由文本、标题、说明、地点、姓名 | 文本输入或多行输入 |
-| `date`、明确日期 | 日期选择器 |
-| 明确日期时间 | 日期与时间选择器,页面组合后提交标准时间字符串 |
-| 金额、排序 | 数字输入 |
-| 地区、分类、人物、业务用户、成员等资源 ID | 从真实候选列表选择;禁止手填内部 ID |
-| `sex`、`status`、是否农历等字典值 | value-label 选择器;必须有 Apifox enum 或字典 options 来源 |
-| `ossId`、封面、头像、媒体 | 真实上传组件;禁止手填文件 ID |
-
-## 已确认需要调整的表单
-
-| 页面 | 字段 | 当前控件/状态 | 正确控件 | 依赖或阻塞 |
-| --- | --- | --- | --- | --- |
-| T04、T05 | `birthLunar`、`deathLunar` | 文本输入,且提示为“按家谱记载填写” | “是否农历”选择器 | B15:Apifox 只有字典值描述,无 value-label enum |
-| T04、T05 | `sex`、`personStatus` | 页面缺入口 | 字典选择器 | B15 |
-| T04、T05 | `fatherId`、`motherId`、`appUserId` | 页面不能从候选选择 | 人物/业务用户候选选择器 | B06、B09/B13;首位成员不能填父母 |
-| T04、T05 | `avatarOssId` | 页面未接头像上传 | 真实上传组件 | B08:19 位 `ossId` 类型冲突 |
-| M02 | `sex` | 文本输入 | 字典选择器 | B15 |
-| M02 | `provinceCode`、`cityCode`、`districtCode` | 页面缺入口 | 行政区划级联选择器 | B12 的接口 DTO 已可读;需接入页面 |
-| G08 | `inviterUserId` | 数字输入,要求用户手填内部 ID | 真实邀请人候选选择器 | B09:没有业务用户候选/映射,不能手填 |
-| F06 | `categoryId` | 页面缺入口 | 谱文分类选择器 | B11:测试谱分类为空,合同没有条目字段定义 |
-| F02 | `feedType` | 自由文本输入 | 动态类型选择器或固定默认类型 | 合同仅给默认 `text`,没有完整类型 enum;不能让用户随意输入未声明类型 |
-| F09 | `shootTime` | 手工文本时间 | 日期与时间选择器 | 合同字段是拍摄时间;可直接改页面控件 |
-| R04 | `eventTime` | 手工文本时间 | 日期与时间选择器 | 合同字段是事项时间;可直接改页面控件 |
-| R07 | `ceremonyTime` | 手工文本时间 | 日期与时间选择器 | 合同字段是活动时间;可直接改页面控件 |
-| R08 | `recordDate`、`remindTime` | 手工文本时间 | 日期选择器;提醒用日期与时间选择器 | 合同字段分别是记录日期、提醒时间 |
-| R11 | `meritTime` | 手工文本时间 | 日期与时间选择器 | 合同字段是功德时间 |
-
-## 已经正确的控件
-
-| 页面 | 字段 | 当前控件 |
-| --- | --- | --- |
-| G03、G11 | `regionCode` | 行政区划级联选择器 |
-| G03、G11 | `visibility`、`joinMode` | 已封装为访问规则选择 |
-| M02 | `birthday` | 日期选择器 |
-| R10 | `remindTime` | 日期和时间选择器组合 |
-| 所有上传表单 | `coverOssId`、`mediaOssIds`、`ossId` | 真实上传回执,不提供手填文件 ID |
-| R04、R11 | 金额 | 数字输入 |
-| 各编辑页 | `sortOrder` | 数字输入 |
-
-## 不应为了“字段齐全”强行显示的字段
-
-| 字段 | 原因 |
-| --- | --- |
-| 首位成员的 `fatherId`、`motherId`、`relationName` | 与“首位成员/世系起点”语义冲突;不能伪造已有成员 ID |
-| `personNo` | 合同明确不传时服务端生成,不应要求用户填写 |
-| `avatarOssId`、`coverOssId`、`mediaOssIds` | 必须由上传组件产生,不允许文本输入 |
-| `status`、`completed` 等服务端有默认值的可选字段 | 无业务需求和明确字典时不新增裸代码控件 |
-
-## 实施顺序
-
-1. 先把 F09、R04、R07、R08、R11 的明确时间字段改为选择器并进行浏览器真实提交回读。
-2. 再接入 M02 的地区级联选择。
-3. B15、B09、B11、B06/B08 由后端补齐枚举、候选或 ID 合同后,再补世系、性别、分类、邀请人等选择器。
-
diff --git a/docs/Apifox写接口字段—表单控件映射-2026-07-27.md b/docs/Apifox写接口字段—表单控件映射-2026-07-27.md
deleted file mode 100644
index 9e1f421..0000000
--- a/docs/Apifox写接口字段—表单控件映射-2026-07-27.md
+++ /dev/null
@@ -1,197 +0,0 @@
-# Apifox 写接口字段—表单控件映射
-
-> 当前有效的 149 operation 总表、页面 owner 与阻塞项见 [APP-149接口页面归属与表单字段审计-2026-07-27.md](APP-149接口页面归属与表单字段审计-2026-07-27.md)。本文件保留为字段控件速查表;其中以下修订以根目录最新 `家谱.openapi.json` 为准。
-
-## 口径与来源
-
-- 核对时间:2026-07-27。
-- 主源:桌面 Apifox 当前 `APP` 项目(149 条 operation)及同一时刻导出的根目录 `家谱.openapi.json`;两者的 operation 数量一致。
-- `必填` 以 Apifox `必需` 标记为准;没有 `必需` 的字段均应允许不填,提交时传空值或省略由当前 API 适配器统一处理。
-- `枚举选择` 只能提交下表列出的 value,不能把中文标签提交给后端。
-- `候选选择` 只能从对应选项接口选取,页面不得暴露裸露的内部 ID 输入框。
-- `上传` 必须先走统一上传,提交上传回执中的 `ossId`;不能让用户手输 OSS ID。
-- 所有 `sortOrder` 是整数数字框;所有 `amount/giftAmount` 是金额数字框;示例为 `yyyy-MM-dd HH:mm:ss` 的时间字段用“日期 + 时间”控件拼接后提交。
-
-## 已在 Apifox 字段详情中确认的字典
-
-| 字段/字典 | value → 中文 | 页面控件 |
-| --- | --- | --- |
-| `sys_user_sex` | `0` 男;`1` 女;`2` 未知 | 单选/下拉选择 |
-| `gen_number_yes_no` | `0` 否;`1` 是 | 单选/下拉选择 |
-| `gen_lineage_person_status` | `0` 健在;`1` 已故;`2` 未知 | 单选/下拉选择 |
-| `sys_normal_disable` | `0` 正常;`1` 停用 | 单选/开关;默认 `0` |
-| `gen_genealogy_visibility` | `0` 私密;`1` 公开;`2` 成员可见 | 单选/下拉选择 |
-| `gen_genealogy_join_mode` | `0` 关闭加入;`1` 申请审核;`2` 邀请加入 | 单选/下拉选择 |
-| `gen_merit_type` | `donation` 捐赠;`repair` 修祠;`public` 公益;`other` 其他 | 单选/下拉选择 |
-| 活动邀请响应 | `ACCEPTED` 接受;`DECLINED` 拒绝 | 二选一 |
-
-`completed` 在 Apifox 当前详情中是 `string`,只给出示例 `0`,没有挂字典/允许值;因此不能伪造“完成/未完成”的值表。当前页面应默认省略,待后端给出该字段的字典定义后再开启开关。
-
-## 已有页面:字段到控件映射
-
-### M02 修改用户资料 — `PUT /genealogy/app/auth/profile`
-
-| 字段 | 必填 | Apifox 详情 | 正确控件与提交 |
-| --- | --- | --- | --- |
-| `nickName` | 否 | string,用户昵称,最多 30 字 | 文本框,最多 30 字 |
-| `realName` | 否 | string,真实姓名,最多 30 字 | 文本框,最多 30 字 |
-| `avatar` | 否 | int64,头像文件 OSS ID | 图片上传;仅提交可安全表示的数值 OSS ID |
-| `sex` | 否 | `sys_user_sex` | 枚举选择 `0/1/2` |
-| `birthday` | 否 | date,生日,格式 `yyyy-MM-dd` | 日期选择器 |
-| `email` | 否 | email,最多 100 字 | email 文本框 |
-
-### G03/G11 创建、修改家谱 — `GenealogyCreateBody` / `GenealogyUpdateBody`
-
-| 字段 | 创建必填 | 正确控件与提交 |
-| --- | --- | --- |
-| `genealogyName` | 是 | 文本框 |
-| `surname` | 是 | 文本框 |
-| `ancestralHall` | 否 | 文本框 |
-| `originPlace` | 否 | 文本框 |
-| `regionCode` | 是 | 省市区级联候选选择,提交行政区划 code |
-| `addressDetail` | 否 | 文本框 |
-| `coverOssId` | 否 | 图片上传,提交字符串 OSS ID |
-| `intro` | 否 | 多行文本 |
-| `visibility` | 否 | 枚举选择:私密 `0` / 公开 `1` / 成员可见 `2` |
-| `joinMode` | 否 | 枚举选择:关闭加入 `0` / 申请审核 `1` / 邀请加入 `2` |
-
-### T04/T05 录入、修改世系人物 — `LineagePersonBody`
-
-同一 body 还用于“添加子女、父母、兄弟姐妹、配偶”。`name` 是唯一 body 必填字段;关系路径由 URL 决定,不能把中文关系标签当成接口字段替代。
-
-| 字段 | 必填 | Apifox 详情/限制 | 正确控件与提交 |
-| --- | --- | --- | --- |
-| `bindingMode` | 是 | 身份认领方式:`NONE` / `SELF` / `SPECIFIED` | 固定英文枚举选择:不绑定账号 / 绑定当前账号 / 绑定指定用户;不发送中文值 |
-| `appUserId` | 视 `bindingMode` 而定 | `NONE` 不绑定账号且不传;`SELF` 绑定当前登录账号且不传,后端从 Token 获取;`SPECIFIED` 绑定指定业务用户且必须传 | 仅 `SPECIFIED` 由管理员选择可信业务用户候选后提交;当前没有候选接口时禁止该选项保存,绝不手输 ID |
-| `personNo` | 否 | 人物编号;不传由服务端生成 | 可选文本框;留空时省略 |
-| `name` | 是 | 姓名 | 文本框 + 必填校验 |
-| `aliasName` | 否 | 别名或曾用名 | 文本框 |
-| `sex` | 否 | `sys_user_sex` | 枚举选择:男 `0` / 女 `1` / 未知 `2` |
-| `generation` | 否 | int64,世代序号 | 正整数数字框;首位成员固定为 `1` |
-| `generationName` | 否 | 字辈或辈分 | 文本框 |
-| `fatherId` | 否 | 父亲人物 ID,必须属于当前家谱 | 从 `/lineage/persons/options` 选择父亲,提交人物 ID |
-| `motherId` | 否 | 母亲人物 ID,必须属于当前家谱 | 从 `/lineage/persons/options` 选择母亲,提交人物 ID |
-| `avatarOssId` | 否 | string/null,头像文件 OSS ID;说明明确要求统一上传组件取得,不允许手工录入 | 图片上传,提交字符串 OSS ID |
-| `birthDate` | 否 | date-time/null(写接口示例为 `yyyy-MM-dd`) | 日期选择;未录入不传 |
-| `birthLunar` | 否 | `gen_number_yes_no` | 枚举选择:否 `0` / 是 `1` |
-| `birthPlace` | 否 | 出生地 | 文本框 |
-| `deathDate` | 否 | date-time/null(写接口示例为 `yyyy-MM-dd`) | 日期选择;未录入不传 |
-| `deathLunar` | 否 | `gen_number_yes_no` | 枚举选择:否 `0` / 是 `1` |
-| `deathPlace` | 否 | 逝世地 | 文本框 |
-| `burialPlace` | 否 | 安葬地 | 文本框 |
-| `personStatus` | 否 | `gen_lineage_person_status` | 枚举选择:健在 `0` / 已故 `1` / 未知 `2` |
-| `biography` | 否 | 人物简介 | 多行文本 |
-| `sortOrder` | 否 | int64,排序值 | 整数数字框 |
-| `remark` | 否 | 备注 | 多行文本 |
-| `relationName` | 否 | 关系名称 | 新增亲属时由关系选择派生;编辑时可作为文本修订 |
-
-#### 页面实测(2026-07-27)
-
-- 此接口字段标为 `date-time`,但四个写接口示例使用 `yyyy-MM-dd`。页面此前把日期追加为 `yyyy-MM-dd HH:mm:ss`,会在客户端 `normalizeLineagePersonDate` 校验阶段被拒绝,尚未发起请求;现已改为只传日期。
-- 后端于 2026-07-27 明确补齐身份认领合同:`NONE`、`SELF` 禁止提交 `appUserId`;`SELF` 由后端从 Token 取当前 APP 用户;仅 `SPECIFIED` 必须提交 `appUserId`。页面默认 `NONE`,不再自动读取或提交 `profile.userId`。
-- 同日页面实测 `POST .../children`:请求体为 `bindingMode: "NONE"` 且不存在 `appUserId`,后端仍返回 HTTP 200 / envelope `code:500`、`发生未知异常,请联系管理员`;三世数据未落库,需后端确认新版写接口是否已部署并排查该业务异常。
-
-### F02 家族圈动态 — `FamilyFeedBody`
-
-| 字段 | 必填 | Apifox 详情 | 正确控件与提交 |
-| --- | --- | --- | --- |
-| `feedType` | 否 | 动态类型;未传默认 `text` | 当前页面固定传 `text`,不让用户输入代码 |
-| `feedContent` | 是 | 动态内容,不允许为空 | 多行文本 + 必填校验 |
-| `mediaOssIds` | 否 | 多个文件 OSS ID 用英文逗号分隔 | 多图上传;回执 ID 以 `,` 拼接 |
-| `sortOrder` | 否 | int64;未传默认 `0` | 整数数字框 |
-| `status` | 否 | `sys_normal_disable` | 正常 `0` / 停用 `1`;创建页默认 `0`,非管理页不暴露停用操作 |
-
-### F06 谱文、F07 相册、F09 相册照片
-
-| body.字段 | 必填 | 正确控件与提交 |
-| --- | --- | --- |
-| `ArticleBody.categoryId` | 否 | 从“谱文分类”接口候选选择;不手填分类 ID |
-| `articleTitle` / `articleSummary` / `authorName` | 标题是 | 分别为文本、多行摘要、文本 |
-| `articleContent` | 是 | 富文本/多行内容编辑 |
-| `coverOssId` | 否 | 图片上传,字符串 OSS ID |
-| `ArticleBody.sortOrder` | 否 | 整数数字框 |
-| `ArticleBody.status` | 否 | `sys_normal_disable` 选择,默认 `0` |
-| `AlbumBody.albumName` | 是 | 文本框 |
-| `albumDesc` | 否 | 多行文本 |
-| `coverOssId` | 否 | 图片上传,字符串 OSS ID |
-| `AlbumBody.sortOrder` | 否 | 整数数字框 |
-| `AlbumBody.status` | 否 | `sys_normal_disable` 选择,默认 `0` |
-| `AlbumPhotoBody.ossId` | 是 | 图片上传;提交字符串 OSS ID |
-| `photoTitle` / `photoDesc` / `photographer` | 否 | 文本、多行文本、文本 |
-| `shootTime` | 否 | 拍摄时间;示例按标准时间字符串 | 日期 + 时间选择 |
-| `AlbumPhotoBody.sortOrder` | 否 | 整数数字框 |
-| `AlbumPhotoBody.status` | 否 | `sys_normal_disable` 选择,默认 `0` |
-
-### R07 祭祀活动、R04 献礼
-
-| body.字段 | 必填 | 正确控件与提交 |
-| --- | --- | --- |
-| `CeremonyBody.ceremonyType` | 是 | Apifox 当前为普通 string;文本框,不能自行伪造枚举 |
-| `ceremonyTitle` | 是 | 文本框 |
-| `ceremonyDesc` | 否 | 多行文本 |
-| `ceremonyTime` | 否 | 示例为 `yyyy-MM-dd HH:mm:ss`;日期 + 时间选择 |
-| `location` / `locationAddress` | 否 | 地点名称、详细地址文本框;两项都应保留 |
-| `longitude` / `latitude` | 否 | 仅可由地图选点组件成对回填;当前没有地图候选/选点合同,R07 不暴露手输框,也不传这两个字段。API 适配层只接受成对有限数字,供后续真实地图组件使用。 |
-| `coverOssId` | 否 | 图片上传,字符串 OSS ID |
-| `sortOrder` | 否 | 整数数字框 |
-| `status` | 否 | `sys_normal_disable` 选择,默认 `0` |
-| `CeremonyGiftBody.giverName` | 否 | 文本框 |
-| `giftAmount` | 是 | 金额数字框 |
-| `giftMessage` | 否 | 多行文本 |
-
-### R08 成长记录、R09 亲友记录、R10 备忘、R11 功德
-
-| body.字段 | 必填 | Apifox 详情/正确控件 |
-| --- | --- | --- |
-| `GrowthRecordBody.lineagePersonId` | 否 | 世系人物候选选择,提交人物 ID |
-| `recordType` | 否 | 当前详情为普通 string,文本框 |
-| `recordTitle` | 是 | 文本框 |
-| `recordContent` | 否 | 多行文本 |
-| `recordDate` / `remindTime` | 否 | 示例均为 `yyyy-MM-dd HH:mm:ss`;日期 + 时间选择 |
-| `mediaOssIds` | 否 | 多图上传,逗号分隔 OSS ID |
-| `GrowthRecordBody.sortOrder` / `status` | 否 | 整数数字框;`sys_normal_disable` 选择 |
-| `MemoBody.memoTitle` | 是 | 文本框 |
-| `memoContent` | 否 | 多行文本 |
-| `remindTime` | 否 | 示例为 `yyyy-MM-dd HH:mm:ss`;日期 + 时间选择 |
-| `completed` | 否 | 当前仅 string 示例 `0`,无字典;默认省略,不能私设枚举 |
-| `MemoBody.mediaOssIds` / `sortOrder` / `status` | 否 | 多图上传;整数数字框;`sys_normal_disable` 选择 |
-| `RelativeRecordBody.relativeName` | 是 | 文本框 |
-| `relationName` / `eventName` | 否 | 文本框 |
-| `eventTime` | 否 | 示例为 `yyyy-MM-dd HH:mm:ss`;日期 + 时间选择 |
-| `giftAmount` | 否 | 金额数字框 |
-| `recordContent` | 否 | 多行文本 |
-| `RelativeRecordBody.mediaOssIds` / `sortOrder` / `status` | 否 | 多图上传;整数数字框;`sys_normal_disable` 选择 |
-| `MeritRecordBody.donorName` / `meritTitle` | 是 | 文本框 |
-| `meritType` | 否 | 枚举选择:捐赠 `donation` / 修祠 `repair` / 公益 `public` / 其他 `other` |
-| `meritContent` | 否 | 多行文本 |
-| `amount` | 否 | 金额数字框 |
-| `meritTime` | 否 | 示例为 `yyyy-MM-dd HH:mm:ss`;日期 + 时间选择 |
-| `MeritRecordBody.sortOrder` / `status` | 否 | 整数数字框;`sys_normal_disable` 选择 |
-
-## 其余写接口:同样必须按字段类型建控件
-
-| 接口 body | 字段映射 |
-| --- | --- |
-| `GenealogyJoinApplyBody` | `applicantName`、`phone`、`relationDesc`、`applyReason` 为文本/多行文本;`inviterUserId` 必须是业务用户候选选择,当前缺候选接口时不暴露裸 ID 输入。 |
-| `GenealogyJoinAuditBody` | `status` 是审核结果,必须由 Apifox 的审核状态字典提供选项后才做选择器;`auditRemark` 多行文本。 |
-| `GenealogyMemberUpdateBody` | `memberName`、`relationName`、`roleType` 文本;`lineagePersonId` 为世系人物候选选择。 |
-| `GenealogyOwnerTransferBody` | `targetMemberId` 必填,家谱成员候选选择。 |
-| `GenerationPoemBody` | `generationNo` 必填正整数;`generationText` 必填文本;`description` 多行文本;`sortOrder` 数字;`status` 用 `sys_normal_disable`。 |
-| `GenerationPoemBatchBody` | `poemText` 必填多行文本;`disableMissing` 布尔开关。 |
-| `FamilyFeedCommentBody` | `parentCommentId` 为评论候选/回复上下文,不能输入 ID;`commentContent` 必填多行文本。 |
-| `FeedbackBody` | `feedbackType` 选填枚举选择:`advice` 建议、`bug` 功能问题、`complaint` 投诉反馈、`other` 其他;界面显示中文标签,提交 value。`feedbackContent` 必填多行文本;`contactInfo` 文本。 |
-| `VipOrderBody` | `packageId` 必填,VIP 套餐候选选择;`genealogyId` 为当前家谱上下文选择;`payType` 只能使用支付方式字典,不能手填代码。 |
-| `VideoBody` | `videoTitle` 必填文本,`videoDesc` 多行文本,`coverOssId`/`videoOssId` 为上传,`durationSeconds`/`sortOrder` 为数字,`status` 为 `sys_normal_disable`。 |
-| `CeremonyInviteesBody` | `inviteeUserIds` 必填多选业务用户候选;无候选接口不能用逗号文本代替数组。 |
-| `CeremonyInvitationResponseBody` | `inviteStatus` 必填二选一:接受 `ACCEPTED`、拒绝 `DECLINED`。 |
-
-## 非页面直接填写的底层接口
-
-认证挑战、验证码、分片上传初始化/完成、文件引用等 body 由登录/上传流程生成,不应渲染为业务表单。`grantType`、`tenantId`、`challengeId`、`validToken`、文件 hash/分片大小等由对应流程拥有,不能让用户在页面中编辑。
-
-## 当前改造判定
-
-1. 已经可以立即改为选择控件的字段:`sex`、出生/逝世农历、`personStatus`、`visibility`、`joinMode`、所有 `status`、`meritType`、邀请响应。
-2. 必须改为候选选择的字段:所有家谱/成员/世系人物/分类/套餐/受邀用户的 ID 字段。
-3. 必须改为上传的字段:所有 `*OssId`、`mediaOssIds`、头像、封面、照片、视频文件。
-4. `completed`、`payType`、审核 `status` 等尚未在当前 Apifox 字段详情给出允许值;在后端未提供字典或候选接口前,不增加猜测性选择项。`feedbackType` 已有四个枚举值,已改为选择控件。
diff --git a/docs/Apifox逐页业务接口与页面展示核对台账.md b/docs/Apifox逐页业务接口与页面展示核对台账.md
deleted file mode 100644
index 6250712..0000000
--- a/docs/Apifox逐页业务接口与页面展示核对台账.md
+++ /dev/null
@@ -1,237 +0,0 @@
-# Apifox 逐页业务接口与页面展示核对台账
-
-> 权威取证顺序:用户已打开的 Apifox 桌面端文档页 → 同一部署的脱敏只读响应(仅在获准时)→ 导出文档交叉核验。不得以导出文档缺项否定 Apifox 中已存在的 operation,也不得以 operation 存在推定页面已经完成。
->
-> 记录规则:每一页必须同时给出业务动作、请求合同、响应字段、页面展示字段和完成状态。`已发布`是 Apifox 文档状态,不是客户端完成状态;`DECLARED_UNVERIFIED` 不得写成完成。
-
-## F 家族内容
-
-### F01 家族动态列表
-
-| 核对项 | Apifox 桌面端实读 | 当前页面实情 | 结论 |
-| --- | --- | --- | --- |
-| 读取列表 | `GET /genealogy/app/genealogies/{genealogyId}/feeds`;鉴权 `Authorization`;路径 `genealogyId:int64` 必填;Header `clientid:string` 必填 | 页面已删除 `listFamilyFeedFixtures`,不再调用缺 DTO 的列表响应来填充动态卡片 | 读取 owner 存在但展示未接线,等待可消费条目 DTO |
-| 响应字段 | `200 ListResult` 仅实读到通用 `code`、`msg`、`data[]`,`data` 元素未声明动态 DTO 字段 | 页面不再展示 `id/tag/time/title/content/author` 等本地字段;只提示缺失的字段合同 | 不能建立真实字段映射;不得猜测字段名 |
-| 页面状态 | 进入发布页与跨模块入口均保留 | 有效家谱下明确显示“动态列表待后端字段合同” | **未完成 / DECLARED_UNVERIFIED**:待 Apifox 补充动态条目 DTO,或在获准的登录只读窗口取得脱敏真实响应后再恢复列表与详情入口 |
-
-### F02 发布家族动态
-
-| 核对项 | Apifox 桌面端实读 | 当前页面实情 | 结论 |
-| --- | --- | --- | --- |
-| 发布动作 | `POST /genealogy/app/genealogies/{genealogyId}/feeds`;鉴权 `Authorization`;路径 `genealogyId:int64`、Header `clientid:string` 均必填 | `appApi.createFeed` 使用严格请求和离页取消;页面不再生成本地预览 | 已接线,等待真实写入响应核验 |
-| 请求体 | `application/json`:`feedContent:string` 必填且不能为空;`feedType:string` 可选,未传默认 `text`;`mediaOssIds:string` 可选,多个 OSS ID 用英文逗号分隔;`sortOrder:int64` 可选,未传默认 `0`;`status:string` 可选,未传默认正常状态 `0` | 表单收集并提交内容、动态类型、通过上传回执取得的媒体和排序值;`status` 使用服务端已声明的默认值,不暴露“0”之类状态码输入 | 已接线;真实写入仍待人工响应核验 |
-| 响应字段 | `200 ObjectResult` 只声明通用 `code`、`msg`、`data:object`,未声明新动态 DTO | 仅在严格成功信封后显示“已提交服务端”;不会在 F01 生成本地列表项 | **未完成 / DECLARED_UNVERIFIED**:接线不等于已验证;真实写入保留人工可观察窗口 |
-
-### F03 动态详情与评论
-
-| 核对项 | Apifox 桌面端实读 | 当前页面实情 | 结论 |
-| --- | --- | --- | --- |
-| 动态详情 | `GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}`;鉴权 `Authorization`;`genealogyId:int64`、`feedId:int64`、`clientid:string` 必填 | 页面已删除 `findFamilyFeedFixture`;因详情响应仍未声明动态本体 DTO,不读取并展示猜测字段 | 正文展示仍未接线,等待可消费响应字段 |
-| 详情响应 | `200 ObjectResult` 只有通用 `code`、`msg`、`data:object`,没有动态本体 DTO | 页面不展示 `tag/time/title/content/author` 等正文 fixture 字段,只显示字段合同缺口 | 动态本体字段仍不能映射,不能猜测 |
-| 一级评论读取 | `GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments`;同样要求鉴权、两个路径 ID 和 `clientid`。接口说明:仅返回正常展示的一级评论,`replyCount` 为直属回复数 | `appApi.getFeedComments` 真实读取;无远端配置或响应不合同时显示错误,不回退 fixture | 已接线,等待真实响应核验 |
-| 评论响应字段 | `data: FamilyFeedCommentView[]`:`commentId`、`genealogyId`、`feedId`、`parentCommentId`、`appUserId`、`appUserNickName`、`appUserAvatar`、`parentAppUserId`、`parentAppUserNickName`、`commentContent`、`userDeleted`、`replyCount`、`commentLevel`、`status`、`createTime` | 展示 `id ← commentId`、`author ← appUserNickName`、`time ← createTime`、`content ← commentContent`、`replyCount ← replyCount`;归属 ID 与重复 ID 在 API 边界校验 | 已接线,等待真实响应字段核验 |
-| 发表评论 | `POST /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments`;请求体 `parentCommentId:int64|null` 可选(不传或 `null` 为一级评论)、`commentContent:string` 必填,最大 1000 字符 | 提交 `commentContent`,限制 1000 字;仅在服务端请求成功并刷新评论列表后提示提交成功 | **未完成 / DECLARED_UNVERIFIED**:接口调用已接线,但未在无人值守时发起写入,也没有真实成功响应证据;动态本体仍缺 DTO |
-
-### F04—F06 谱文列表、详情与编辑
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| F04 列表 | `GET /genealogy/app/genealogies/{genealogyId}/articles`;鉴权、`genealogyId:int64`、`clientid:string` 必填;`200 ListResult` 仅通用 `code/msg/data[]`,条目未声明 DTO | 已删除 fixture、分类和本地搜索;页面明确提示缺失文章 ID、分类、标题、摘要、作者和更新时间投影 | **未完成 / DECLARED_UNVERIFIED**:没有可审计的条目字段映射,不能接线或把本地筛选误称服务端能力 |
-| F05 详情 | `GET /genealogy/app/genealogies/{genealogyId}/articles/{articleId}`;鉴权、`genealogyId:int64`、`articleId:int64`、`clientid:string` 必填;`200 ObjectResult` 仅通用对象 DTO | 已删除 fixture 正文与编辑跳转;只显示正文 DTO 缺口 | **未完成 / DECLARED_UNVERIFIED**:正文、作者、时间投影均未由详情响应声明 |
-| F06 新建 | `POST /genealogy/app/genealogies/{genealogyId}/articles`;鉴权、`genealogyId:int64`、`clientid:string` 必填 | `appApi.createArticle` 严格提交标题、摘要、封面上传回执、正文、作者和排序;成功仅表示服务端成功信封,不生成本地文章 | 已接线,等待真实写入响应核验 |
-| F06 修改 | `PUT /genealogy/app/genealogies/{genealogyId}/articles/{articleId}`;鉴权、两个路径 ID、`clientid:string` 必填 | 已移除 fixture 编辑预填;没有可靠详情 DTO 和文章 ID 列表来源时,编辑入口关闭 | **未完成 / DECLARED_UNVERIFIED** |
-| 新建/修改请求体 | `categoryId:int64` 可选;`articleTitle:string` 必填;`articleSummary:string` 可选;`coverOssId:int64` 可选;`articleContent:string` 必填;`authorName:string`、`sortOrder:int64`、`status:string` 均可选。返回均为通用 `ObjectResult` | 新建页收集可读字段;封面只接收真实上传回执。`categoryId` 需要分类列表条目 DTO,`status` 需要状态字典,二者均不让用户填写内部 ID/码 | 可写字段已接线;分类与状态选择仍 **DECLARED_UNVERIFIED**,编辑仍需可靠 articleId/详情 owner |
-
-### F07—F09 相册、照片墙与上传
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| F07 相册列表 | `GET /genealogy/app/genealogies/{genealogyId}/albums`;鉴权、`genealogyId:int64`、`clientid:string` 必填;`200 ListResult` 仅通用数组 DTO | 已删除 fixture 相册卡片和本地预览,页面明确提示缺失相册 ID、封面、名称、照片数、描述和更新时间字段 | **未完成 / DECLARED_UNVERIFIED**:相册条目、封面 URL、照片数和更新时间没有响应字段来源 |
-| F07 新建相册 | `POST /genealogy/app/genealogies/{genealogyId}/albums`;请求体 `albumName:string` 必填,`albumDesc:string`、`coverOssId:int64`、`sortOrder:int64`、`status:string` 可选;返回通用 `ObjectResult` | 表单提交名称、说明、真实封面上传回执和排序;`status` 缺可读字典,不向用户暴露码值 | 已接线,等待真实写入响应核验 |
-| F08 照片墙读取 | `GET /genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos`;鉴权、`genealogyId:int64`、`albumId:int64`、`clientid:string` 必填;`200 ListResult` 仅通用数组 DTO | 已删除 fixture 相册和照片墙,只显示缺失照片展示字段的状态 | **未完成 / DECLARED_UNVERIFIED**:缺相册与照片展示 DTO,不能猜 OSS URL、标题或说明字段 |
-| F09 写入照片记录 | `POST /genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos`;路径两个 ID、鉴权、`clientid` 必填;`ossId:int64` 必填,`photoTitle/photoDesc/photographer/shootTime/sortOrder/status` 可选 | 已删除 mock 图片库、说明表单和本地预览 | **未完成 / BLOCKED_BY_MEDIA_OWNER**:接口接受的是既有 `ossId`,当前页面没有已核实的文件上传 owner 和真实 OSS 回执,不能把本地图片冒充上传成功 |
-
-### F10 短视频
-
-| 核对项 | Apifox 桌面端实读 | 当前页面/结论 |
-| --- | --- | --- |
-| 目录检索 | 以 `video` 检索,APP 目录仅返回“删除视频”;未返回视频列表、详情、发布、修改、播放地址、评论、点赞或分享 operation | F10 所需浏览和互动链路没有业务 owner,不能以参考项目或相册接口补造 |
-| 唯一命中动作 | `DELETE /genealogy/app/genealogies/{genealogyId}/videos/{videoId}`;接口说明为逻辑删除并释放视频文件和封面文件引用;鉴权、`genealogyId:int64`、`videoId:int64`、`clientid:string` 必填,`200 VoidResult` | 单一删除动作不能证明视频页面能读取、播放或发布;**F10 未完成 / MISSING_OPERATION**。不发起删除请求 |
-
-## G 家谱工作区
-
-### G01、G03、G05—G11
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面状态与结论 |
-| --- | --- | --- |
-| G01 我的家谱 | `GET /genealogy/app/genealogies/mine`;鉴权、`clientid:string` 必填;`200 ListResult` 仅通用 `code/msg/data[]` | 页面要展示当前家谱、可切换家谱、角色与快捷入口;当前 DTO 没有这些字段。**未完成 / DECLARED_UNVERIFIED** |
-| G03 创建家谱 | `POST /genealogy/app/genealogies`;`genealogyName`、`surname`、`regionCode` 必填;`ancestralHall/originPlace/addressDetail/coverOssId/intro/visibility/joinMode` 可选。`visibility`:`0` 私密、`1` 公开、`2` 成员可见;`joinMode`:`0` 关闭、`1` 审核、`2` 邀请码 | 表单提供全部可读资料字段;地区为三级级联选择器,封面只由真实上传回执产生,访问规则由可读选项映射为 `visibility/joinMode`。已删除本地家谱/首位人物预览。创建后必须从真实响应取得 `genealogyId` 再创建首位人物;当前没有可恢复查询 owner,不能从泛型 mine 列表按名称猜 ID | **未完成 / MISSING_OPERATION**:两阶段创建结果恢复链未闭合;写入与上传已接线,仍待人工真实响应核验 |
-| G05 家谱概览 | `GET /genealogy/app/genealogies/{genealogyId}/overview`;鉴权、`genealogyId:int64`、`clientid` 必填;`200 ObjectResult` 通用对象 | 页面需要家谱资料、成员/人物等概览显示;响应无 DTO。**未完成 / DECLARED_UNVERIFIED** |
-| G06 搜索公开家谱 | `GET /genealogy/app/genealogies/public` 已在 Apifox 目录确认;读取结果仍为通用 `ListResult` | 已删除本地搜索结果和申请跳转;名称、籍贯、简介、可加入状态、稳定 genealogyId 均未获声明。**未完成 / DECLARED_UNVERIFIED** |
-| G08 申请加入 | `POST /genealogy/app/genealogies/{genealogyId}/join-applies`;路径 `genealogyId:int64`、鉴权、`clientid` 必填;body `applicantName/phone/relationDesc/applyReason:string`、`inviterUserId:int64` 均可选 | 已删除本地填写预览;没有公开家谱详情、可申请权限或稳定 ID 投影时,不凭“可选”字段虚构申请上下文。**未完成 / DECLARED_UNVERIFIED**,不发送申请 |
-| G09 我的申请 | `GET /genealogy/app/genealogies/join-applies/mine`;鉴权、`clientid` 必填;`200 ListResult` 通用数组 DTO | 已删除 fixture 申请列表;申请名称、状态、原因、时间等展示字段无映射。**未完成 / DECLARED_UNVERIFIED** |
-| G10 审核申请 | `PUT /genealogy/app/genealogies/{genealogyId}/join-applies/{applyId}/audit`;路径两个 ID、鉴权、`clientid` 必填;`status:string` 必填,`auditRemark:string` 可选,返回 `VoidResult` | 已删除本地审核流程;待审核列表 DTO 和稳定 applyId 未声明。**未完成 / DECLARED_UNVERIFIED**,不执行审核写入 |
-| G11 家谱设置 | `PUT /genealogy/app/genealogies/{genealogyId}`;同一组字段为 `genealogyName/surname/ancestralHall/originPlace/regionCode/addressDetail/coverOssId/intro/visibility/joinMode`,文档均列可选 | 已删除 fixture 预填和本地预览;概览 DTO 不能安全预填,封面仍受上传 owner 阻塞。**未完成 / DECLARED_UNVERIFIED** |
-
-### G12 字辈谱
-
-| 核对项 | Apifox 桌面端实读 | 当前页面实情 | 结论 |
-| --- | --- | --- | --- |
-| 正常字辈读取 | `GET /genealogy/app/genealogies/{genealogyId}/generation-poems`;鉴权 `Authorization`、路径 `genealogyId:int64`、Header `clientid:string` 均必填。说明为仅返回正常状态字辈,供世系人物录入和展示使用 | 页面通过 `appApi.getGenerationPoems` 真实读取,展示 `generationNo/generationText/status`;响应归属、重复 poemId 和重复世代在 API 边界校验 | 已接线,等待真实响应核验;响应没有“当前世代”字段,页面已删除固定当前世代推断 |
-| 维护列表读取 | `GET /genealogy/app/genealogies/{genealogyId}/generation-poems/management`;同一鉴权、路径和 `clientid` 要求。说明为家谱内容编辑者访问,返回正常与停用字辈,供恢复、纠错和排序调整 | 点击维护先真实请求 `appApi.getGenerationPoemManagement`,成功才进入编辑;不再用 fixture 或角色推断权限 | 已接线,等待真实响应/权限核验;维护读取失败不伪造“无权限”或本地编辑状态 |
-| 单条新增/修改/停用恢复 | `POST /genealogy/app/genealogies/{genealogyId}/generation-poems`;`PUT /genealogy/app/genealogies/{genealogyId}/generation-poems/{poemId}`。后者路径另有 `poemId:int64` 必填;两者 body 均为:`generationNo:int64` 必填、`generationText:string` 必填且最大 50 字、`description:string` 可选且最大 500 字、`sortOrder:int64` 可选、`status:string` 可选(`0` 正常、`1` 停用) | 当前编辑器以一段本地文本拆分生成字辈行;没有单条 request mapper 或服务端返回处理 | 单条合同已明确,当前页面交互是批量维护模型;不能把本地状态切换写成停用/恢复成功,**未完成 / DECLARED_UNVERIFIED** |
-| 批量预览 | `POST /genealogy/app/genealogies/{genealogyId}/generation-poems/batch/preview`;body `poemText:string` 必填、最大 26000 字,最多 500 世,可用空格、逗号、分号、顿号、斜杠或换行分隔;`disableMissing:boolean` 可选 | `appApi.previewGenerationPoemBatch` 只提交 `poemText/disableMissing`;页面展示服务端 `createCount/updateCount/keepCount/disableCount`,草稿或策略变化即使旧预览失效 | 响应 `GenerationPoemBatchPreviewView` 的计数字段和家谱归属已校验,等待真实响应核验;不再使用本地差异作为保存依据 |
-| 批量保存 | `POST /genealogy/app/genealogies/{genealogyId}/generation-poems/batch/save`;请求体与批量预览相同;接口说明为按当前数据生成差异,停用不删除历史字辈记录;返回 `VoidResult` | 保存仅在当前草稿已有同签名服务端预览时调用,严格成功后读取维护列表;本地不再更新或宣称保存成功 | **未完成 / DECLARED_UNVERIFIED**:写入已接线,但无人值守未触发真实保存;需人工可观察结果和真实回读才能升级状态 |
-
-## T 世系树与成员
-
-### T01 世系树与人物操作面板
-
-| 核对项 | Apifox 桌面端实读 | 当前页面实情 | 结论 |
-| --- | --- | --- | --- |
-| 世系树读取 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/tree`;鉴权 `Authorization`、路径 `genealogyId:int64`、Header `clientid:string` 均必填;`200 LineagePersonTreeResult` | `pages/tree/t01-tree-overview.vue` 已调用 `appApi.getTree`,但尚未作真实响应验证 | 不是“无接口”,但不能因代码存在而宣称页面已完成 |
-| 树节点响应字段 | `data: LineagePersonTreeView[]`:`personId/genealogyId/genealogyName/genealogyNo/appUserId/appUserNickName/personNo/name/aliasName/sex/generation/generationName/fatherId/fatherName/motherId/motherName/spouseNames/avatarOssId/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/personStatus/biography/sortOrder/status/remark/relationType/relationName/spouses[]/children[]`;`spouses` 为配偶节点、`children` 为递归子女节点 | 当前 mapper 只投影树布局所需 `id/parentId/name/relation/generation/branch/years/sex/personStatus`;人物卡和操作面板头像固定使用本地占位图,未消费 `avatarOssId`;父母、配偶、子女等可用响应关系也未完整展示 | **未完成 / DECLARED_UNVERIFIED**:必须补头像文件取址与字段投影,并在真实只读响应下核验树形关系,才能满足人物卡要求 |
-| 点击人物后的动作 | 页面已有“查看资料、添加父亲/母亲/配偶/兄弟姐妹/儿子/女儿、调整排行、编辑信息”动作入口,分别路由 T03/T04/T06/T05 | 父母、子女的 HTTP 动作实际分别共享 `/parents`、`/children`,页面未发送 `sex` 或 `relationName`,因此不能区分“父亲/母亲”“儿子/女儿”;邀请绑定在页面中明确标作不可用 | **未完成**:操作面板存在不等于每个业务动作闭环;性别语义和邀请绑定仍缺合同闭环 |
-| 邀请绑定 | 在 Apifox APP 目录分别以 `invite`、`bind` 全文检索,均未命中任何邀请签发、受邀人查询、人物绑定、绑定结果查询 operation | 页面也未伪造该流程 | **MISSING_OPERATION**:不以入谱申请或普通人物修改替代“邀请绑定” |
-
-### T03 成员资料
-
-| 核对项 | Apifox 桌面端实读 | 当前页面实情 | 结论 |
-| --- | --- | --- | --- |
-| 读取详情 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}`;鉴权、`genealogyId:int64`、`personId:int64`、`clientid` 均必填;`200 LineagePersonResult` | 页面调用 `appApi.getPerson` | 读取路径存在,但不是完成依据 |
-| 详情响应字段 | `data: LineagePersonView`:`personId/genealogyId/genealogyName/genealogyNo/appUserId/appUserNickName/personNo/name/aliasName/sex/generation/generationName/fatherId/fatherName/motherId/motherName/spouseNames/avatarOssId/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/personStatus/biography/sortOrder/status/remark` | 已把别名、性别字典值、人物状态字典值、出生/逝世农历、出生/逝世地点、安葬地、配偶名、生平和备注纳入 T03 mapper 与展示;仍未展示头像(缺 `avatarOssId` 取址)、`appUserNickName`、排序/状态原值,亲属仍只可由父母 ID 跳转。 | **未完成 / DECLARED_UNVERIFIED**:T03 仍是半成品,不能计入完成;字段已接线但未用真实只读响应核验,头像、完整亲属投影和字典语义仍未闭环。 |
-
-### T04 添加亲属、T05 编辑、T06 排行
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面实情与结论 |
-| --- | --- | --- |
-| T04 首位成员/新增人物 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons`;鉴权、路径 `genealogyId`、`clientid` 必填;body 只有 `name:string` 必填。可选字段为 `appUserId/personNo/aliasName/sex/generation/generationName/fatherId/motherId/avatarOssId/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/personStatus/biography/sortOrder/remark/relationName`;其中 `personNo` 由服务端生成,`avatarOssId` 须来自文件上传组件 | 表单已提供并提交当前可安全映射的 `aliasName/generationName/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/biography/remark`;非首位成员同时提交关系选择产生的 `relationName`。性别、人物状态缺字典 owner;关联账号、父母、头像与排行需要独立对象选择、上传或原子排序 owner,不能让用户填写内部 ID 或猜码。真实写入未验证。**未完成 / DECLARED_UNVERIFIED** |
-| T04 添加父母、子女、兄弟姐妹、配偶 | 分别为 `POST .../lineage/persons/{personId}/parents`、`.../children`、`.../siblings`、`.../spouses`;路径 `genealogyId/personId`、鉴权、`clientid` 均必填,均返回 `LineagePersonResult`,body 与新增人物同合同。实读 `sex:string` 仅写“建议使用系统字典值”,示例为 `"0"`;以“字典/dict/性别”检索 APP/PC 目录均未找到该字典读取 owner 或男/女码值映射。 | 页面现会提交所选亲属的 `relationName`,不再把路由意图丢掉;父亲/母亲共用 `/parents`,儿子/女儿共用 `/children` 仍不能仅凭该显示名获得可靠性别语义。头像仍缺文件上传回执。**未完成 / DECLARED_UNVERIFIED**,不得拿参考项目的旧 `0/1` 码值猜填,也不能执行无人值守写入。 |
-| T05 修改人物 | `PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}`;两个路径 ID、鉴权、`clientid` 必填,body 与新增人物同合同,返回 `LineagePersonResult` | 已读写 `name/aliasName/generationName/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/biography/remark`;静态校验确认表单字段与请求白名单一致。头像仍缺上传回执;性别、人物状态、排行因字典或原子 owner 缺失未写入。 | **未完成 / DECLARED_UNVERIFIED**:已扩展为已声明的安全字段子集,但没有真实保存后的响应/回读,不能称完整人物编辑。 |
-| T06 调整排行 | Apifox 只有单人物 `PUT .../persons/{personId}` 中的可选 `sortOrder:int64`,没有同辈排行列表、批量重排、原子提交或冲突回显 operation | 页面已明确显示“服务暂未开放”,不逐人写入 | **未完成 / MISSING_OPERATION**:不能以单人 `sortOrder` 伪造同辈原子排行调整 |
-
-### T07 成员目录、T08 成员状态
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面实情与结论 |
-| --- | --- | --- |
-| T07 成员目录分页与搜索 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/page`;query 可选 `pageNum`(默认 1)、`pageSize`(默认 10)、`keyword`(姓名/别名/人物编号)、`generation:int64`、`personStatus:string`;响应 `LineagePersonPageResult` 为 `rows: LineagePersonView[]` 与 `total`。另有 `GET .../lineage/persons/options?keyword=` 供人物选项读取 | 已移除 `listTreeMemberPresentationFixtures`;页面使用实际 `pageNum/pageSize/keyword` 请求、消费 `rows/total`,支持服务端搜索与继续加载;本地预览明确报真实读取不可用,不伪造目录数据。 | **未完成 / DECLARED_UNVERIFIED**:读取合同已接线并经静态检查,尚未用登录态获得一次真实 `rows/total` 响应;世代/人物状态筛选尚未增加页面控件。 |
-| T08 成员状态说明 | 人物详情、列表和分页都提供 `personStatus`、`status`;停用人物为 `DELETE /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}`,接口说明为逻辑停用且在正常子女时拒绝停用,返回 `VoidResult` | 已移除 `findTreeMemberPresentationFixture` 和 `privacy/deceased/forbidden` 推断;页面读取人物详情,但在无状态字典时不展示原始 `personStatus` 值,也不提供停用写入。 | **未完成 / DECLARED_UNVERIFIED**:读取已接线并经静态检查,仍未用真实只读响应核验;没有字典映射时不得展示内部码或生成隐私/受限/纪念文案。 |
-
-## R 记录模块
-
-### R01 人物录、R02 人物档案
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| R01 人物录列表、搜索 | 正确读取 owner 是 `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/page`;query 为 `pageNum/pageSize/keyword/generation/personStatus`,响应为 `rows: LineagePersonView[]/total`。人物选项另有 `GET .../lineage/persons/options?keyword=` | 已移除 `listTreeMemberPresentationFixtures` 和本地“新增预览”;页面用 `pageNum/pageSize/keyword` 请求、消费 `rows/total`,支持服务端搜索和继续加载。新增人物保持从 T01 亲属关系入口进入。 | **未完成 / DECLARED_UNVERIFIED**:读取合同已接线并经静态检查,尚未用登录态获得一次真实响应;世代/人物状态筛选尚未增加页面控件。 |
-| R02 人物档案读取 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` 返回已在 T03 实读的 `LineagePersonView`,含 `name/generation/generationName/biography/remark`,以及头像、性别、别名、亲属名、地点、生卒、状态等 | 已移除 `findTreeMemberPresentationFixture`、本地预览/编辑;页面读取详情并展示已声明的资料字段,编辑入口改为跳转 T03 的成员档案,再由 T05 完成可写字段维护。成长日志仍跳 R08,人生事仍为待开放。 | **未完成 / DECLARED_UNVERIFIED**:读取已接线并经静态检查,尚未取得真实详情响应;头像取址、性别/状态字典和完整亲属投影仍未闭环。 |
-| R02 新建/编辑人物 | `POST /lineage/persons`、`PUT /lineage/persons/{personId}` 的完整人物请求合同已在 T04/T05 实读,`name` 必填,其余有世代、头像、亲属、状态、排序、传记、备注等字段 | 表单只收 `name/generationName/generation/biography/remark`,保存仅变成本地预览 | **未完成 / DECLARED_UNVERIFIED**:是可辨认的字段子集但没有远端读写闭环;不得把“生成本地预览”说成新建或修改成功 |
-
-### R03 贺礼簿、R04 往来详情与编辑
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| R03 列表、R04 详情 | `GET /genealogy/app/genealogies/{genealogyId}/relative-records`、`GET .../relative-records/{relativeId}`;均需鉴权、`genealogyId`、`clientid`,分别返回通用 `ListResult`、`ObjectResult`,未声明条目 DTO | 已删除 R03/R04 fixture 列表、详情和本地编辑预填;页面明确说明缺记录 ID、关系、事项、时间、金额和备注的响应映射 | **未完成 / DECLARED_UNVERIFIED**:接口并非缺失,但响应没有声明 `relativeId` 等展示字段,不能猜字段映射 |
-| R04 新增/修改 | `POST /genealogy/app/genealogies/{genealogyId}/relative-records`、`PUT .../relative-records/{relativeId}`;body 为 `relativeName:string` 必填,`relationName/eventName/eventTime/giftAmount:number/recordContent/mediaOssIds/sortOrder/status` 可选,返回通用 `ObjectResult` | 创建页提交姓名、关系、事项、时间、金额、备注、真实媒体回执和排序;`status` 无可读字典,不向用户暴露状态码。详情/修改入口因无记录 DTO/ID 来源关闭 | 创建已接线,等待真实写入响应核验;修改仍 **DECLARED_UNVERIFIED** |
-| R04 删除 | `DELETE .../relative-records/{relativeId}` 已在 Apifox 同一资源目录确认 | 页面明确显示“删除暂未开放” | **未完成 / DECLARED_UNVERIFIED**:不执行删除;存在删除 operation 也不改变其他读写未接线的事实 |
-
-### R05—R07 礼仪活动与献礼
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| R05 礼仪活动列表、R07 新建 | 在 APP 目录以 `ceremony` 实读到该资源共六个动作:详情、修改、活动献礼列表、新增献礼、删除活动、删除献礼;没有活动列表或新建活动 operation | 已删除 `listCeremonyFixtures`、新建和编辑预览;R05/R07 显示缺 operation 状态并保留返回路径 | **未完成 / MISSING_OPERATION**:不得用详情或修改接口冒充活动列表/新建;R05、R07 的主业务 owner 缺失 |
-| R06 礼仪详情 | `GET /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}`;需鉴权、路径 `genealogyId/ceremonyId`、`clientid`,返回通用 `ObjectResult`;未声明活动 DTO | 已删除 fixture、受邀人拼装和编辑入口,只提示详情字段缺口 | **未完成 / DECLARED_UNVERIFIED**:详情 operation 存在,但这些展示字段、受邀人及其关系没有响应字段依据 |
-| R07 修改礼仪 | `PUT .../ceremonies/{ceremonyId}`;body `ceremonyType:string`、`ceremonyTitle:string` 必填,`ceremonyDesc/ceremonyTime/location/coverOssId/sortOrder/status` 可选,返回通用 `ObjectResult` | 无可靠详情 DTO 和活动 ID 来源时关闭修改,且封面另缺上传 owner | 表单字段虽可对应,但没有远端读取、写入和回读;**未完成 / DECLARED_UNVERIFIED** |
-| R06 献礼 | `GET .../ceremonies/{ceremonyId}/gifts` 返回通用 `ListResult`;`POST .../gifts` 的 body 为 `giverName:string` 可选、`giftAmount:number` 必填、`giftMessage:string` 可选,返回通用对象 | 页面有受邀人展示,不是献礼条目展示或写入 | **未完成 / DECLARED_UNVERIFIED**:献礼接口不能替代受邀信息,且没有条目 DTO 可映射 |
-
-### R08 成长日志、R09 人生事
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| R08 列表与详情 | `GET /genealogy/app/genealogies/{genealogyId}/growth-records`、`GET .../growth-records/{recordId}`;同一 APP 资源另有新增、修改、删除,共五个动作。列表为通用 `ListResult`、详情为通用 `ObjectResult`,均未声明记录 DTO | 已删除 `listGrowthRecordFixtures` 和本地列表预览;页面只保留创建表单 | **未完成 / DECLARED_UNVERIFIED**:`recordId`、标题、日期、内容没有响应字段声明,不能恢复列表或详情 |
-| R08 新增/修改 | `POST .../growth-records`、`PUT .../growth-records/{recordId}`;新增 body 已实读:`lineagePersonId/recordType/recordContent/recordDate/remindTime/mediaOssIds/sortOrder/status` 可选,`recordTitle:string` 必填 | 从人物档案进入时自动绑定当前人物,表单提交类型、标题、内容、日期、提醒、真实媒体回执和排序;`status` 无可读字典,不向用户暴露状态码。修改没有记录 ID 来源而关闭 | 创建已接线,等待真实写入响应核验;修改 **DECLARED_UNVERIFIED** |
-| R09 人生事 | 分别以 `life` 与“人生”在 APP 接口目录检索,均未命中独立人生事件资源;当前文档中不能用成长、备忘或人物资料替代 | 页面已明确提示接口未开放且不展示/提交数据 | **未完成 / MISSING_OPERATION**:保持关闭是正确的,不虚构读写链路 |
-
-### R10 家族备忘、R11 功德记录
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| R10 备忘列表与详情 | `GET /genealogy/app/genealogies/{genealogyId}/memos`、`GET .../memos/{memoId}`;同一资源另有新增、修改、删除,共五个动作。列表 `ListResult`、详情 `ObjectResult` 都只声明通用包装字段 | 已删除 fixture 列表和本地预览,只保留创建表单 | **未完成 / DECLARED_UNVERIFIED**:不能从泛型响应推导 `memoId` 或 `completedLabel`,状态文案也没有字典依据 |
-| R10 新增/修改 | `POST .../memos`、`PUT .../memos/{memoId}`;body `memoTitle:string` 必填,`memoContent/remindTime/completed/mediaOssIds/sortOrder/status` 可选 | 表单提交标题、日期与时间选择器生成的提醒时间、内容、真实媒体上传回执和排序。`completed/status` 未声明可读值或字典,均不向用户暴露 `0/1` 码。修改缺 ID 来源关闭 | 创建已接线,等待真实写入响应核验;修改 **DECLARED_UNVERIFIED** |
-| R11 功德列表 | `GET /genealogy/app/genealogies/{genealogyId}/merit-records`;同资源仅另有新增、删除,共三个动作;列表返回通用 `ListResult`,未声明条目 DTO | 已删除 fixture 列表和本地预览,只保留创建表单 | **未完成 / DECLARED_UNVERIFIED**:列表字段没有合同映射,页面不猜条目字段 |
-| R11 新增/修改 | `POST .../merit-records`;body `donorName:string`、`meritTitle:string` 必填,`meritType/meritContent/amount:number/meritTime/sortOrder/status` 可选;当前 APP 目录未见修改 operation | 表单提交捐赠人、标题、类型、金额、时间、内容和排序;`status` 缺可读字典,不向用户暴露状态码 | 新增已接线,等待真实写入响应核验;编辑 **MISSING_OPERATION** |
-
-### 2026-07-24 实际服务端回读补充(覆盖上述 R03—R11 的旧“未验证”结论)
-
-已用当前测试账号在家谱 2080557121112465409 完成真实创建和列表回读;未执行删除、退出、短信或改密操作。
-
-| 资源 | 实际返回字段(已回读) | 页面闭环 |
-| --- | --- | --- |
-| 亲友往来 | relativeId、relativeName、relationName、eventName、eventTime、giftAmount、recordContent、mediaOssIds、sortOrder | R04 创建后由 R03 列表回读 |
-| 礼仪活动 | ceremonyId、ceremonyType、ceremonyTitle、ceremonyDesc、ceremonyTime、location、giftCount | R07 创建后由 R05 列表回读 |
-| 成长记录 | recordId、lineagePersonId、lineagePersonName、recordType、recordTitle、recordContent、recordDate、remindTime、mediaOssIds、sortOrder | R08 先读列表,创建后重新读取 |
-| 家族备忘 | memoId、memoTitle、memoContent、remindTime、completed、mediaOssIds、sortOrder | R10 先读列表,创建后重新读取;completed 未展示为业务状态 |
-| 功德记录 | meritId、donorName、meritType、meritTitle、meritContent、amount、meritTime、sortOrder | R11 先读列表,创建后重新读取并计算金额合计 |
-
-以上五组的列表与创建状态均为 VERIFIED。单条详情、修改和删除仍按页面当前入口及测试范围分别保留,不把未测试能力标记为通过。
-
-世系首位成员创建于同一测试家谱进行了页面提交和合同最小请求复核:POST lineage/persons 的合法最小 body(name、generation=1)均返回 HTTP 200、业务 code 500、消息“发生未知异常,请联系管理员”;随后 GET 世系树仍为空。该项为服务端业务异常,前端未猜测额外字段或伪造创建成功;T04 首位成员失败文案已明确为“首位成员尚未保存”。
-
-## N 消息通知
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| N01 消息中心列表 | `GET /genealogy/app/notifications`;鉴权 `Authorization`、Header `clientid:string` 必填;`200 ListResult` 只声明通用 `code/msg/data[]`,条目仍为泛型对象 | 已删除 `listNotificationFixtures`、未读计数和本地业务跳转,只显示缺失通知字段合同 | **未完成 / DECLARED_UNVERIFIED**:没有消息 ID、已读、标题、时间、正文、目标类型和目标参数的响应字段合同;不能把 fixture 的跳转当作通知接口返回能力 |
-| N02 消息详情 | 在 APP 消息通知目录实读到的仅有列表、单条标已读、全部标已读三个 operation;没有详情读取 operation | 已删除详情 fixture,只显示缺详情 owner 状态 | **未完成 / MISSING_OPERATION**:不能以列表泛型或本地 fixture 冒充单条详情;详情所需正文、来源和跳转字段均无接口 owner |
-| N01/N02 单条标已读 | `POST /genealogy/app/notifications/{notificationId}/read`;鉴权、`notificationId:int64`、`clientid` 必填,返回 `VoidResult` | 无可消费通知 ID 时页面不显示单条标已读,已删除本地 `unread` 修改 | 正确写入 owner 存在但没有可回读 item/ID,**未完成 / DECLARED_UNVERIFIED** |
-| N01 全部标已读 | `POST /genealogy/app/notifications/read-all`;鉴权、`clientid` 必填,返回 `VoidResult` | 已删除“全部已读”本地 fixture 修改 | **未完成 / DECLARED_UNVERIFIED**:无列表回读时不把本地状态改动当服务端写入成功 |
-
-## M 个人中心与账号
-
-### M01 个人中心、M02 个人资料
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| M01 当前用户资料 | `GET /genealogy/app/auth/profile`;鉴权、`clientid` 必填,返回通用 `ObjectResult`,`data` 未声明用户 DTO | 已删除 `currentUser.name/role/phone` 和 fixture 未读数展示,保留各模块入口 | **未完成 / DECLARED_UNVERIFIED**:用户名、角色、手机号及其脱敏规则没有响应字段合同;不可把 mock 当前用户当作已登录资料 |
-| M02 读取与修改资料 | 读取为同一 `GET /auth/profile`;修改为 `PUT /genealogy/app/auth/profile`。修改 body 已实读:`nickName/avatarOssId/sex/birthday/provinceCode/cityCode/districtCode/addressDetail` 均可选,返回通用 `ObjectResult` | 已删除 mock 预填和本地保存;当前 UI 的真实姓名/邮箱与更新合同不相交,页面明确关闭编辑 | `nickName` 可对应,但 `realName/email` 不在修改合同;后端的头像、性别、生日、地区、地址未有页面输入或 mapper。**未完成 / DECLARED_UNVERIFIED**;头像另受上传 owner 阻塞 |
-
-### M03—M05 安全设置、改密、换绑手机
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| M03 账号与安全概览 | 资料读取、改密、换绑均有各自 APP operation,未见独立“安全概览/设备/登录记录”读取 operation | 已删除本地账号摘要,保留改密与换绑入口 | **未完成 / DECLARED_UNVERIFIED**:入口可以保留,但安全状态、设备、会话等没有 owner,不能凭本地提示宣称已核验 |
-| M04 修改密码 | `PUT /genealogy/app/auth/password`;鉴权、`clientid` 必填;body `oldPassword:string`、`newPassword:string` 均必填且均为 32 位 MD5;返回 `VoidResult` | 页面将当前/新密码 MD5 后以 `oldPasswordHash/newPasswordHash` 传给 api 层,最终字段名映射为 `oldPassword/newPassword` | 请求字段、摘要格式和页面动作可对齐;但尚未在真实账号下接受响应验证,且不得无人值守改密。**未完成 / DECLARED_UNVERIFIED** |
-| M05 换绑手机号 | `PUT /genealogy/app/auth/phone`;鉴权、`clientid` 必填;body `clientId:string`、`phone:string`、`smsCode:string` 均必填,验证码模式为 4 位;响应为 `ObjectResult`(含 400/200) | 已删除 mock 当前手机号、输入和本地校验,页面明确提示需人工 TAC/短信与资料 DTO | 号码和四位码输入可对应,但缺实际滑动验证、短信发送、`clientId` 来源、写入与回读。**未完成 / DECLARED_UNVERIFIED**;不代用户发验证码或换绑 |
-
-### M06 帮助、M07 反馈、M08 推广、M09 VIP、M10 关于
-
-| 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 |
-| --- | --- | --- | --- |
-| M06 帮助中心 | `GET /genealogy/app/help-articles`、`GET /genealogy/app/help-articles/{articleId}`;列表为通用 `ListResult`、详情为通用对象,未声明文章 DTO | 页面本地内置分类、问题、答案和搜索 | **未完成 / DECLARED_UNVERIFIED**:帮助读取 owner 存在,但不能从泛型响应推导问题、答案、分类或文章 ID;当前本地说明不是服务端帮助 |
-| M07 提交反馈 | `POST /genealogy/app/feedback`;鉴权、`clientid` 必填;body `feedbackType:string` 可选、`feedbackContent:string` 必填、`contactInfo:string` 可选,返回通用 `ObjectResult` | 表单与 api 层正好提交这三字段,页面包含成功、失败、结果不确定的提示 | 请求合同已对应;未经真实接受响应验证,不能把 UI 成功态视为后端成功。**未完成 / DECLARED_UNVERIFIED**,不代用户提交反馈 |
-| M08 应用推广/邀请 | `GET /genealogy/app/promotions` 已存在,但仅为“应用推广列表”,返回通用 `ListResult`;全文检索未发现邀请码签发、归因、奖励、受邀绑定或分享回执 operation | M08 正确保持“推广能力未开放”,没有伪造邀请 | **未完成 / MISSING_OPERATION**:普通推广内容列表不能替代邀请推广业务闭环 |
-| M09 VIP 与订单 | APP 目录有 `GET /genealogy/app/vip/packages`、`GET /genealogy/app/vip/orders`、`POST /genealogy/app/vip/orders`;前两者列表响应为泛型。创建订单 body 为 `packageId:int64` 必填,`genealogyId:int64`、`payType:string` 可选,返回通用对象 | 页面当前不读取、不会创建订单或扣费 | **未完成 / DECLARED_UNVERIFIED**:套餐与订单 owner 存在但 DTO 未声明、页面未接线;支付调起、支付结果、取消/退款等动作在当前 APP 目录未形成可审计合同,故继续禁用付费流程 |
-| M10 关于与退出 | 协议、版本为本地静态内容;退出为 `DELETE /genealogy/app/auth/logout`,鉴权、`clientid` 必填,返回 `VoidResult` | M10 调用 api 层退出并且无论远端结果如何都会清本机会话 | 登出路径与合同一致,但未在真实请求下验证;协议/版本没有远端 owner 的需求。退出动作仍标 **DECLARED_UNVERIFIED**,不在无人值守状态触发 |
-
-## A 认证
-
-| 页面/动作 | Apifox 桌面端实读:业务接口、请求/响应字段 | 当前页面展示或输入字段 | 完成状态 |
-| --- | --- | --- | --- |
-| A01 登录:验证前置与发送短信 | `GET /captcha/require`:查询 `tenantId/clientId/sceneCode/subject`,其中 `sceneCode` 必填;响应 `VerificationRequireResult` 已声明 `required/providerCode/captchaType/sceneCode/ttlSeconds`。`POST /genealogy/app/auth/sms/code`:Header `clientid` 必填;Body `clientId/grantType/tenantId/sceneCode/phone/validToken` 均必填,`sceneCode` 含 `APP_SMS_LOGIN`;响应 `VoidResult`。 | `a01-entry.vue` 以手机号、密码或四位短信码登录;取码先查验证要求,再由内嵌验证组件提交 `validToken`。滑动验证采用服务商组件本身,不增加页面自定义样式。 | **未完成 / DECLARED_UNVERIFIED**:前置响应字段与发送短信字段已逐项对上,但未发送短信;`required=false` 时如何签发可消费票据也未由 Apifox 合同说明,不能把页面本地倒计时当发送成功。 |
-| A01 账号密码登录 | `POST /genealogy/app/auth/login`:Header `clientid` 必填;Body `clientId/grantType/tenantId/phone/password` 均必填,`grantType=password`,`password` 为 32 位 MD5;响应组件为 `LoginResult`。 | 页面将手机号和 MD5 密码传至 API 层;当前 API 层读取响应 `access_token` 保存会话。登录接口请求体没有 `validToken` 字段,页面仅把滑动验证作为前端完成条件。 | **未完成 / DECLARED_UNVERIFIED**:请求字段对齐;Apifox 当前只标出 `LoginResult` 组件,未在该 operation 展开可核的会话字段,且尚未以测试账号获得一次被接受的响应,不能声明登录已完成。 |
-| A01 短信登录 | `POST /genealogy/app/auth/login/sms`:Header `clientid` 必填;Body `clientId/grantType/tenantId/phone/smsCode` 均必填,`grantType=sms`,`smsCode` 为四位短信码;响应组件为 `LoginResult`。 | 页面字段为手机号、四位验证码;API 层同样依赖返回的 `access_token` 建立会话。 | **未完成 / DECLARED_UNVERIFIED**:请求合同对齐,但该动作依赖真人收到短信;未发送、未登录,不把页面登录成功提示当成远端成功。 |
-| A04 注册 | 短信链路同上但 `sceneCode=APP_REGISTER`。`POST /genealogy/app/auth/register`:Header `clientid` 必填;Body 已实读 `clientId/grantType/tenantId/phone/password/smsCode`,`grantType=password`、密码为 32 位 MD5、验证码为四位;响应 `LoginResult`。 | 页面输入手机号、验证码、密码、确认密码和协议勾选;提交时传手机号、MD5 密码、验证码。 | **未完成 / DECLARED_UNVERIFIED**:字段链路可对照,但注册会创建真实账号,按约定不在无人值守时触发;`LoginResult` 的完整展示字段仍待接受响应核实。 |
-| A05 找回密码 | 短信链路同上但 `sceneCode=APP_FORGOT_PASSWORD`。`PUT /genealogy/app/auth/password/reset`:Header `clientid` 必填;Body `clientId/grantType/tenantId/phone/newPassword/smsCode` 均必填,`grantType=password`、`newPassword` 为 32 位 MD5、验证码为四位;响应 `VoidResult`。 | 页面输入手机号、验证码、新密码、确认密码;提交参数为手机号、MD5 新密码、验证码。 | **未完成 / DECLARED_UNVERIFIED**:请求字段对齐;找回会真实改密,未触发,不能以本地“修改成功”状态当接口完成。 |
-| A06 账号状态/恢复 | 在 APP 认证目录按 `status`、`frozen`、`disabled`、`risk`、`appeal`、`recovery` 检索,未找到账号状态读取、限制原因、申诉或恢复的独立 operation。 | 页面只读路由参数 `status`,并用本地 `frozen/disabled/risk` 文案展示限制原因和恢复说明;“查看恢复方式”仅打开本地弹层;该文件也未注册进 `pages.json` 的 52 条路由。 | **未完成 / MISSING_OPERATION**:没有后端 owner 提供状态、原因、可恢复路径或申诉结果,不能把静态文案当真实账号状态;未注册时也不能由正常路由到达。 |
-
-## 本轮累计
-
-| 范围 | 已逐页实读 | 可实施映射 | 未完成原因 |
-| --- | ---: | --- | --- |
-| F01—F10 | 10/10 | F02 发布、F03 评论读取/提交、F06 谱文创建、F07 相册创建已按声明字段接线;F01/F04/F05/F08/F09 已关闭无 DTO 或上传 owner 的 fixture 展示 | F02/F03/F06/F07 等待真实响应核验;动态、谱文和相册展示仍缺 DTO;F09 缺文件上传 owner,F10 缺读取/发布 owner;写入不得在无人值守时触发 |
-| G01、G03、G05—G12 | 9/9 | G12 正常列表、维护列表、批量预览/保存已按声明字段接线;G03/G06/G08—G11 已删除 fixture 或本地预览 | G12 待真实读取/写入响应核验,当前世代字段仍未声明;G03 两阶段结果恢复链、G06/G08—G11 的 DTO/ID/权限缺口仍未闭环 |
-| T01、T03—T08 | 7/7 | 树、详情、人物分页/选项、人物与亲属写入合同均已逐项实读;T03、T05、T07、T08 的已声明读取/字段子集已接线 | T03 明确为未完成;T01 头像与邀请绑定未闭环;T04 关系性别语义不完整;T06 缺原子排行 operation;T07/T08 均待真实读取响应核验 |
-| R01—R11 | 11/11 | R03/R04、R08、R10、R11 创建已按声明字段接线;R05—R07/R09 已删除本地流程 | 所有 R 列表/详情仍缺 DTO;创建待真实响应核验;R05/R07、R09 另有明确 `MISSING_OPERATION` |
-| N01—N02 | 2/2 | 消息列表、单条标已读、全部标已读 owner 已实读;页面已删除 fixture 消息和本地已读 | 列表条目 DTO 未声明、消息详情 operation 明确缺失,无稳定 ID 时不发送已读 mutation |
-| M01—M10 | 10/10 | M01—M03/M05 已删除 mock 资料和本地资料流程;改密、反馈、退出已有独立接线 | M02 字段与合同不一致;读取 DTO 多为泛型;M08 缺邀请业务 owner;VIP 还缺可审计支付闭环;敏感写入均未实测 |
-| A01、A04—A06 | 4/4 | 验证要求、短信发送、密码/短信登录、注册、找回密码的请求合同已逐项实读 | 无人值守不发送短信、不注册、不找回、不真实登录;`LoginResult` 仅见响应组件名,完整会话字段待接受响应;A06 明确缺状态/恢复 owner |
diff --git a/docs/MuMu全页样式复核-2026-07-26.md b/docs/MuMu全页样式复核-2026-07-26.md
deleted file mode 100644
index 56d5273..0000000
--- a/docs/MuMu全页样式复核-2026-07-26.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# MuMu 全页样式复核(2026-07-26)
-
-## 范围与方法
-
-- 设备:MuMu Android(SM-A5560),实际运行中的 APP WebView,900 × 1600 截图。
-- 范围:`pages.json` 的 52 个页面路由,以及测试账号可进入的列表、空态、错误态、新建表单和原生选择器状态。
-- 评审:三份独立结论——MuMu 实机逐页评审 1 份、核心表单代码/交互评审 1 份、家族与记录模块代码/交互评审 1 份。只采纳能由真实页面或已声明接口契约证实的结论。
-- 不使用 mock、fixture 或本地伪造成功。全部截图在 `tmp/mumu-visual-audit-20260726/`。
-
-## 逐页复核结果
-
-已逐页打开并复核以下 52 条路由:
-
-- 认证:A01、A04、A05。
-- 家谱:G01、G03、G05、G06、G08、G09、G10、G11、G12。
-- 世系:T01、T03、T04、T05、T06、T07、T08。
-- 家族:F01、F02、F03、F04、F05、F06、F07、F08、F09、F10。
-- 记录:R01、R02、R03、R04、R05、R06、R07、R08、R09、R10、R11。
-- 消息:N01、N02。
-- 我的:M01、M02、M03、M04、M05、M06、M07、M08、M09、M10。
-
-结论:已进入的页面均保持朱红、金线、宣纸背景和卷轴按钮这套既有视觉系统;未发现横向页面滚动、标题遮挡、内容与底部导航重叠。长内容、空态、接口错误态和可进入的新建表单均已按实际数据复核。
-
-## 已落地且在 MuMu 复验的改动
-
-1. G01 当前家谱的超长名称改为单行省略,避免末尾数字孤立换行。
-2. G05 长简介限制为两行,恢复被遮挡的世系树、字辈谱、审核、设置四张功能卡;家谱统计信息收回深色头图区域。
-3. F02 动态类型固定显示为“文字动态”,不再把接口枚举值暴露成可编辑输入框;上传按钮增至可触控尺寸。
-4. F03 未返回点赞状态时使用中性说明,不再把未知状态渲染成失败样式。
-5. F10、R09、N02、M03、M05、G12、M08 移除面向用户的接口、operation、Mock 等内部术语,改为可理解的功能状态说明。
-6. M01 默认头像使用项目真实 `auth-login-outline` 图;性别代码不再直接展示。M02 在没有服务端选项字典时显示“待确认 / 选项待提供”,不伪造选择项。
-7. R02 的“人生大事”改为明确的“暂未开放”状态,不再提供无效可点击入口。
-8. F02、F06、F07、F09、R07、R08、R10 的图片上传入口最小高度统一到 88rpx。
-9. R08 成长日志的记录、提醒时间,R11 功德记录的记录时间,全部改为系统日期/时间选择器;提交时仍使用接口既有 `YYYY-MM-DD HH:mm:ss` 文本字段。
-10. R08、R10、R11 的表单底部“取消 / 提交”按钮改为容器内的可收缩网格。修复了 MuMu 窄屏上右侧提交按钮被裁切的问题;三页都已实机复验。
-
-## 选择器与输入原则
-
-- 日期、时间:使用实际 Android 原生选择器,未改变后端字段名或格式。
-- 有确定自由文本语义的字段仍使用输入框,例如姓名、标题、地点、人物简介、备注。
-- 性别、人物状态、农历等需要枚举/字典的字段,当前接口未提供可用选项来源;未猜测中文标签或构造假选项。
-
-## 不能通过前端补齐的状态
-
-| 范围 | 真实结果 | 前端处理 |
-| --- | --- | --- |
-| 首位成员创建 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons` 使用最小合法 body 仍返回业务 `code:500` | 不伪造成员;T03–T08、R01–R02 的真实成员读取/写入闭环仍需后端修复或提供可读测试成员。 |
-| 性别、人物状态、农历等选择项 | 接口契约未提供枚举/字典来源 | 保留真实已返回值;未知值显示“待确认”,不将代码当中文含义解释。 |
-| 消息详情 | 当前测试数据没有可读的消息详情标识 | N02 复核了无详情状态和返回路径,未伪造详情内容。 |
-
-## 本轮验证
-
-- `powershell -NoProfile -ExecutionPolicy Bypass -File tests/compile-audit.ps1`:通过。
-- `powershell -NoProfile -ExecutionPolicy Bypass -File tests/r-business-flow-contract.ps1`:通过。
-- `powershell -NoProfile -ExecutionPolicy Bypass -File tests/active-page-business-ownership-contract.ps1`:通过。
-- MuMu 实机复验:R08、R10、R11 新建表单及其底部按钮;R08 日期选择器;G01、G05、F02、F03、F10、G12、N02、M01、M02、M03、M05、M08 的改动后状态。
-- 最后一轮 MuMu 路由复测:52/52 条路由均已重新截图完成,结果位于 `tmp/mumu-visual-audit-20260726/final-routes/`。
diff --git a/docs/design/assets/a01-vnext/A01-shared-scroll-skins-with-dialog-approved.png b/docs/design/assets/a01-vnext/A01-shared-scroll-skins-with-dialog-approved.png
deleted file mode 100644
index a94268f..0000000
Binary files a/docs/design/assets/a01-vnext/A01-shared-scroll-skins-with-dialog-approved.png and /dev/null differ
diff --git a/docs/design/assets/a01-vnext/A01-shared-skin-family-option-2-selected.png b/docs/design/assets/a01-vnext/A01-shared-skin-family-option-2-selected.png
deleted file mode 100644
index ac52be4..0000000
Binary files a/docs/design/assets/a01-vnext/A01-shared-skin-family-option-2-selected.png and /dev/null differ
diff --git a/docs/design/assets/a01-vnext/masters/a01-scroll-dialog-master-v3-r2.png b/docs/design/assets/a01-vnext/masters/a01-scroll-dialog-master-v3-r2.png
deleted file mode 100644
index 482b071..0000000
Binary files a/docs/design/assets/a01-vnext/masters/a01-scroll-dialog-master-v3-r2.png and /dev/null differ
diff --git a/docs/design/assets/a01-vnext/masters/a01-scroll-primary-master-v3.png b/docs/design/assets/a01-vnext/masters/a01-scroll-primary-master-v3.png
deleted file mode 100644
index c82ad48..0000000
Binary files a/docs/design/assets/a01-vnext/masters/a01-scroll-primary-master-v3.png and /dev/null differ
diff --git a/docs/design/assets/a01-vnext/masters/a01-scroll-secondary-master-v3.png b/docs/design/assets/a01-vnext/masters/a01-scroll-secondary-master-v3.png
deleted file mode 100644
index fb9d105..0000000
Binary files a/docs/design/assets/a01-vnext/masters/a01-scroll-secondary-master-v3.png and /dev/null differ
diff --git a/docs/design/assets/a01-vnext/masters/a01-scroll-toast-master-v3.png b/docs/design/assets/a01-vnext/masters/a01-scroll-toast-master-v3.png
deleted file mode 100644
index 85ce476..0000000
Binary files a/docs/design/assets/a01-vnext/masters/a01-scroll-toast-master-v3.png and /dev/null differ
diff --git a/docs/design/assets/g01-background/masters/genealogy-page-background-long-flagship-master.png b/docs/design/assets/g01-background/masters/genealogy-page-background-long-flagship-master.png
deleted file mode 100644
index fcfd8e7..0000000
Binary files a/docs/design/assets/g01-background/masters/genealogy-page-background-long-flagship-master.png and /dev/null differ
diff --git a/docs/design/assets/g01-state/masters/g01-empty-panel-master.png b/docs/design/assets/g01-state/masters/g01-empty-panel-master.png
deleted file mode 100644
index 5ed3f2f..0000000
Binary files a/docs/design/assets/g01-state/masters/g01-empty-panel-master.png and /dev/null differ
diff --git a/docs/design/assets/module-backgrounds/masters/family-page-background-imagegen-source.png b/docs/design/assets/module-backgrounds/masters/family-page-background-imagegen-source.png
deleted file mode 100644
index 6f30482..0000000
Binary files a/docs/design/assets/module-backgrounds/masters/family-page-background-imagegen-source.png and /dev/null differ
diff --git a/docs/design/assets/module-backgrounds/masters/notification-page-background-imagegen-source.png b/docs/design/assets/module-backgrounds/masters/notification-page-background-imagegen-source.png
deleted file mode 100644
index cb8abe9..0000000
Binary files a/docs/design/assets/module-backgrounds/masters/notification-page-background-imagegen-source.png and /dev/null differ
diff --git a/docs/design/assets/module-backgrounds/masters/profile-page-background-imagegen-source.png b/docs/design/assets/module-backgrounds/masters/profile-page-background-imagegen-source.png
deleted file mode 100644
index 0152ee2..0000000
Binary files a/docs/design/assets/module-backgrounds/masters/profile-page-background-imagegen-source.png and /dev/null differ
diff --git a/docs/design/assets/module-backgrounds/masters/records-page-background-imagegen-source.png b/docs/design/assets/module-backgrounds/masters/records-page-background-imagegen-source.png
deleted file mode 100644
index d104835..0000000
Binary files a/docs/design/assets/module-backgrounds/masters/records-page-background-imagegen-source.png and /dev/null differ
diff --git a/docs/design/assets/module-backgrounds/masters/tree-page-background-imagegen-source.png b/docs/design/assets/module-backgrounds/masters/tree-page-background-imagegen-source.png
deleted file mode 100644
index 25bed73..0000000
Binary files a/docs/design/assets/module-backgrounds/masters/tree-page-background-imagegen-source.png and /dev/null differ
diff --git a/docs/design/mockups/2026-07-19/g01-add-dialog-paper-sheet-target.png b/docs/design/mockups/2026-07-19/g01-add-dialog-paper-sheet-target.png
deleted file mode 100644
index 08fba46..0000000
Binary files a/docs/design/mockups/2026-07-19/g01-add-dialog-paper-sheet-target.png and /dev/null differ
diff --git a/docs/design/references/G01-我的家谱-美术锚点.png b/docs/design/references/G01-我的家谱-美术锚点.png
deleted file mode 100644
index eeb72df..0000000
Binary files a/docs/design/references/G01-我的家谱-美术锚点.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/4、族谱网APP端-思维导图.pdf b/docs/design/references/产品参考原稿/4、族谱网APP端-思维导图.pdf
deleted file mode 100644
index e3d58d1..0000000
Binary files a/docs/design/references/产品参考原稿/4、族谱网APP端-思维导图.pdf and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/创建家谱 .png b/docs/design/references/产品参考原稿/创建家谱 .png
deleted file mode 100644
index db633d8..0000000
Binary files a/docs/design/references/产品参考原稿/创建家谱 .png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/功德录(1).png b/docs/design/references/产品参考原稿/功德录(1).png
deleted file mode 100644
index 3f6e9dd..0000000
Binary files a/docs/design/references/产品参考原稿/功德录(1).png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/功德录.png b/docs/design/references/产品参考原稿/功德录.png
deleted file mode 100644
index 948c0c4..0000000
Binary files a/docs/design/references/产品参考原稿/功德录.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/加入家谱.png b/docs/design/references/产品参考原稿/加入家谱.png
deleted file mode 100644
index a1961d5..0000000
Binary files a/docs/design/references/产品参考原稿/加入家谱.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/发布视频.png b/docs/design/references/产品参考原稿/发布视频.png
deleted file mode 100644
index 69a0a38..0000000
Binary files a/docs/design/references/产品参考原稿/发布视频.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/字辈谱.png b/docs/design/references/产品参考原稿/字辈谱.png
deleted file mode 100644
index 91b4659..0000000
Binary files a/docs/design/references/产品参考原稿/字辈谱.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家族相册.png b/docs/design/references/产品参考原稿/家族相册.png
deleted file mode 100644
index 95a2ce8..0000000
Binary files a/docs/design/references/产品参考原稿/家族相册.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家族视频.png b/docs/design/references/产品参考原稿/家族视频.png
deleted file mode 100644
index bec2a05..0000000
Binary files a/docs/design/references/产品参考原稿/家族视频.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 1.png b/docs/design/references/产品参考原稿/家谱主页 – 1.png
deleted file mode 100644
index 24dd5df..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 1.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 22.png b/docs/design/references/产品参考原稿/家谱主页 – 22.png
deleted file mode 100644
index 7ca459c..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 22.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 23.png b/docs/design/references/产品参考原稿/家谱主页 – 23.png
deleted file mode 100644
index bf9134b..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 23.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 24.png b/docs/design/references/产品参考原稿/家谱主页 – 24.png
deleted file mode 100644
index dc8643e..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 24.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 25.png b/docs/design/references/产品参考原稿/家谱主页 – 25.png
deleted file mode 100644
index a909c7b..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 25.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 26.png b/docs/design/references/产品参考原稿/家谱主页 – 26.png
deleted file mode 100644
index a24e208..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 26.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 27.png b/docs/design/references/产品参考原稿/家谱主页 – 27.png
deleted file mode 100644
index b2cdbf7..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 27.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 28.png b/docs/design/references/产品参考原稿/家谱主页 – 28.png
deleted file mode 100644
index fdcb460..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 28.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 29.png b/docs/design/references/产品参考原稿/家谱主页 – 29.png
deleted file mode 100644
index 1a102b7..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 29.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 30.png b/docs/design/references/产品参考原稿/家谱主页 – 30.png
deleted file mode 100644
index addb70a..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 30.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 31.png b/docs/design/references/产品参考原稿/家谱主页 – 31.png
deleted file mode 100644
index 31c8a7e..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 31.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 32.png b/docs/design/references/产品参考原稿/家谱主页 – 32.png
deleted file mode 100644
index e043077..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 32.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 33.png b/docs/design/references/产品参考原稿/家谱主页 – 33.png
deleted file mode 100644
index ddb4da3..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 33.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 34.png b/docs/design/references/产品参考原稿/家谱主页 – 34.png
deleted file mode 100644
index ab84cc2..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 34.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 35.png b/docs/design/references/产品参考原稿/家谱主页 – 35.png
deleted file mode 100644
index 6be416c..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 35.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 36.png b/docs/design/references/产品参考原稿/家谱主页 – 36.png
deleted file mode 100644
index 88d86ae..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 36.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 37.png b/docs/design/references/产品参考原稿/家谱主页 – 37.png
deleted file mode 100644
index 0c7aa97..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 37.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 38.png b/docs/design/references/产品参考原稿/家谱主页 – 38.png
deleted file mode 100644
index 4e62b87..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 38.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 39.png b/docs/design/references/产品参考原稿/家谱主页 – 39.png
deleted file mode 100644
index 7d2658b..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 39.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 40.png b/docs/design/references/产品参考原稿/家谱主页 – 40.png
deleted file mode 100644
index 8db4101..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 40.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 41.png b/docs/design/references/产品参考原稿/家谱主页 – 41.png
deleted file mode 100644
index 959951a..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 41.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 42.png b/docs/design/references/产品参考原稿/家谱主页 – 42.png
deleted file mode 100644
index 0ffd4e8..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 42.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 43.png b/docs/design/references/产品参考原稿/家谱主页 – 43.png
deleted file mode 100644
index 75d218d..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 43.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 44.png b/docs/design/references/产品参考原稿/家谱主页 – 44.png
deleted file mode 100644
index 79f9eb5..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 44.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 45.png b/docs/design/references/产品参考原稿/家谱主页 – 45.png
deleted file mode 100644
index 25d7d0f..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 45.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 46.png b/docs/design/references/产品参考原稿/家谱主页 – 46.png
deleted file mode 100644
index dc8643e..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 46.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 47.png b/docs/design/references/产品参考原稿/家谱主页 – 47.png
deleted file mode 100644
index f1b6d90..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 47.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 48.png b/docs/design/references/产品参考原稿/家谱主页 – 48.png
deleted file mode 100644
index 589d746..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 48.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 49.png b/docs/design/references/产品参考原稿/家谱主页 – 49.png
deleted file mode 100644
index 676c765..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 49.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 50.png b/docs/design/references/产品参考原稿/家谱主页 – 50.png
deleted file mode 100644
index 109489f..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 50.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页 – 51.png b/docs/design/references/产品参考原稿/家谱主页 – 51.png
deleted file mode 100644
index 8e6b6bc..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页 – 51.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/家谱主页.png b/docs/design/references/产品参考原稿/家谱主页.png
deleted file mode 100644
index 17c7eec..0000000
Binary files a/docs/design/references/产品参考原稿/家谱主页.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/新建相册.png b/docs/design/references/产品参考原稿/新建相册.png
deleted file mode 100644
index e0de6f3..0000000
Binary files a/docs/design/references/产品参考原稿/新建相册.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/添加功德人.png b/docs/design/references/产品参考原稿/添加功德人.png
deleted file mode 100644
index 2d4fc6f..0000000
Binary files a/docs/design/references/产品参考原稿/添加功德人.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/添加谱文.png b/docs/design/references/产品参考原稿/添加谱文.png
deleted file mode 100644
index 71ce53d..0000000
Binary files a/docs/design/references/产品参考原稿/添加谱文.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/登陆.png b/docs/design/references/产品参考原稿/登陆.png
deleted file mode 100644
index 8cd9c7c..0000000
Binary files a/docs/design/references/产品参考原稿/登陆.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/相册.png b/docs/design/references/产品参考原稿/相册.png
deleted file mode 100644
index d0e151d..0000000
Binary files a/docs/design/references/产品参考原稿/相册.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/管理世代.png b/docs/design/references/产品参考原稿/管理世代.png
deleted file mode 100644
index 38e65d8..0000000
Binary files a/docs/design/references/产品参考原稿/管理世代.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/编辑家族视频.png b/docs/design/references/产品参考原稿/编辑家族视频.png
deleted file mode 100644
index e84c52b..0000000
Binary files a/docs/design/references/产品参考原稿/编辑家族视频.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/编辑相册.png b/docs/design/references/产品参考原稿/编辑相册.png
deleted file mode 100644
index a5377b5..0000000
Binary files a/docs/design/references/产品参考原稿/编辑相册.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/设置世代.png b/docs/design/references/产品参考原稿/设置世代.png
deleted file mode 100644
index 5adf773..0000000
Binary files a/docs/design/references/产品参考原稿/设置世代.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/调整世代.png b/docs/design/references/产品参考原稿/调整世代.png
deleted file mode 100644
index 3433aa9..0000000
Binary files a/docs/design/references/产品参考原稿/调整世代.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/谱文(1).png b/docs/design/references/产品参考原稿/谱文(1).png
deleted file mode 100644
index 7e6777e..0000000
Binary files a/docs/design/references/产品参考原稿/谱文(1).png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/谱文.png b/docs/design/references/产品参考原稿/谱文.png
deleted file mode 100644
index 0f72aee..0000000
Binary files a/docs/design/references/产品参考原稿/谱文.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/谱文详情.png b/docs/design/references/产品参考原稿/谱文详情.png
deleted file mode 100644
index 50e1707..0000000
Binary files a/docs/design/references/产品参考原稿/谱文详情.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/首页 .png b/docs/design/references/产品参考原稿/首页 .png
deleted file mode 100644
index fa0e7da..0000000
Binary files a/docs/design/references/产品参考原稿/首页 .png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/首页 – 14.png b/docs/design/references/产品参考原稿/首页 – 14.png
deleted file mode 100644
index fe23cb6..0000000
Binary files a/docs/design/references/产品参考原稿/首页 – 14.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/首页 – 16.png b/docs/design/references/产品参考原稿/首页 – 16.png
deleted file mode 100644
index 1107be9..0000000
Binary files a/docs/design/references/产品参考原稿/首页 – 16.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/首页 – 18.png b/docs/design/references/产品参考原稿/首页 – 18.png
deleted file mode 100644
index 3e9144c..0000000
Binary files a/docs/design/references/产品参考原稿/首页 – 18.png and /dev/null differ
diff --git a/docs/design/references/产品参考原稿/首页 – 19.png b/docs/design/references/产品参考原稿/首页 – 19.png
deleted file mode 100644
index 60b0efa..0000000
Binary files a/docs/design/references/产品参考原稿/首页 – 19.png and /dev/null differ
diff --git a/docs/design/references/公共操作图标-风格锚点.png b/docs/design/references/公共操作图标-风格锚点.png
deleted file mode 100644
index 9983776..0000000
Binary files a/docs/design/references/公共操作图标-风格锚点.png and /dev/null differ
diff --git a/docs/产品参考页面功能映射表.md b/docs/产品参考页面功能映射表.md
deleted file mode 100644
index c6ee476..0000000
--- a/docs/产品参考页面功能映射表.md
+++ /dev/null
@@ -1,751 +0,0 @@
-# 产品参考页面功能映射表
-
-> 规划日期:2026-07-23(北京时间)
-> 状态:需求已收口,作为《今晚全量联调与明早测试执行计划》的权威附件,三人交叉评审与用户确认均已完成;用户已明确开始执行,`T_due=2026-07-24 08:00`,55 个候选 PA 本轮维持 `approvedCandidateActions=0`。
-> 冻结规则:用户确认本附件仍不代表开始实现;只有用户明确说“开始执行”后才允许修改业务代码、接口接线、样式和测试,或运行测试、构建与 MuMu。
-
-## 一、范围、优先级与计数
-
-本附件只做产品甄别,不复制参考代码。优先级固定为:
-
-1. 用户对当前 `jiapuapp` 的明确需求;
-2. 当前真实后端合同、线上文档和可复现响应;
-3. 当前项目的路由、架构、安全、国风视觉和无障碍基线;
-4. `C:\Users\Rain\Desktop\job\app设计`;
-5. `C:\Users\Rain\Desktop\job\Jiapu-App`。
-
-基线计数:
-
-| 对象 | 分母 | 本附件覆盖 |
-| --- | ---: | ---: |
-| 当前 `jiapuapp` 活动路由 | 52 | 52,沿用 `docs/接口与页面映射总表.md` 的 A/G/T/F/R/N/M 稳定编号 |
-| 设计参考文件 | 60=59 PNG+1 单页 PDF | 60,`D001`—`D060` |
-| 完成项目活动路由 | 78 | 78,`J001`—`J078` |
-| 完成项目注释路由声明 | 1 | 1,`JX001` |
-| 完成项目未注册页面文件 | 7 | 7,`JU01`—`JU07` |
-| 完成项目媒体资产 | 531 | 531 个进入资产候选池;实际采用前另建逐文件 `RAxxx` |
-| 本轮规划确认前批准的新增当前路由 | 0 | 0;候选先复用现有 owner 或保持关闭/待确认 |
-
-完成项目 `pages.json` 共有 79 个 `path` 文本,其中 `pages/index/vertical-swiper/vertical-swiper` 整段被注释,因此活动路由分母是 78,不是 79;`pages/render/render` 已计入 78。
-
-## 二、稳定 ID 与逐动作规则
-
-- 设计证据的完整格式是 `Dxxx-Pxx-Sxx-Axx`:文件、页面/PDF 页、页面状态、来源证据基记录。当前每张单页 PNG 都作为独立 `S01` 状态证据,表内 `Dxxx-P01-Axx` 是省略 `S01` 的短写,不表示不同文件可以合并。
-- 完成项目的完整格式是 `Jxxx-Sxx-Axx`。同一路由上的正常、空、管理、编辑、权限等状态先区分,再对查看、创建、删除、邀请、支付等来源证据基记录编号;表内省略默认 `S01`。注释路由用 `JX001`,未注册文件用 `JUxx`。
-- 通常一个 `Axx` 对应一个独立动作。若旧截图或旧代码分支把多个控件不可分地记在同一物理证据中,基记录后必须追加稳定语义后缀,例如 `J073-A02@comment`、`@reaction`、`@share`;每个后缀分别绑定合同键、六类结论和 PA。341 只统计物理基记录,语义后缀不重复增加来源文件/代码记录,但不能用同一基号合并不同产品动作。
-- 当前产品 owner:沿用 A01、G01、T01、F01、R01、N01、M01 等编号。共享 owner 使用 `S-ID`、`S-PERM`、`S-FILE`、`S-REGION`、`S-SESSION`。
-- 一行可列同一页面的多个动作,但每个动作都必须有动作 ID、合同键和结论;不同结论不得合并。
-- 文件名、画面、路由或源码相似不能单独证明“重复”。它们可能是普通态、管理态、编辑态、空态、错误态、不同角色态或主题态;只有入口、对象、动作、数据、接口、权限和返回行为全部等价后才能共用当前 owner,源状态 ID 始终保留。
-
-六类甄别结论固定为:`直接采用`、`改造后采用`、`仅参考交互`、`后端缺失,暂时关闭`、`与当前产品冲突,明确舍弃`、`待用户确认`。
-
-所有动作继承以下门禁:
-
-1. 正常、加载、空、失败、无权限、提交中、明确失败、结果未知、返回与重进状态按动作性质覆盖。
-2. 当前 OpenAPI 没有稳定 capability 投影;写入口在权限 owner 确认前只能显示禁用原因,403 不能反推权限。
-3. 所有 `int64` ID 必须先通过十进制字符串 wire 门禁;不安全 number 解析后禁止继续使用。
-4. 参考稿的亮红导航、旧 uView 控件、旧图标、固定尺寸和旧数据层不进入视觉目标;只借鉴信息结构,视觉统一回当前国风系统。
-5. `DECLARED_UNVERIFIED` 只表示受保护 OpenAPI 有声明;收到“开始执行”并取得本轮真实证据前,没有任何动作可预先标 `LIVE_VERIFIED`。
-
-## 三、当前合同键
-
-本节是源页面逐动作映射使用的唯一合同索引。每个键只能有一个 `contractState`,每个当前 operation 必须写成 `METHOD + 完整 path`。快照中有 operation 但已知 schema、权限、唯一 owner、结果确认或静态门禁冲突时,状态取更严重的 `CONTRACT_CONFLICT`;门禁脚本期望、但受保护快照没有的路径只能记为“门禁目标”,不能冒充当前 operation。当前没有任何键可预先标 `LIVE_VERIFIED`。
-
-### 3.1 共享合同
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-S-ID` | OpenAPI 中所有 `genealogyId`、`personId`、`memberId`、`appUserId`、内容 ID、文件 ID、`avatarOssId` 及关系引用;无独立 operation | `CONTRACT_CONFLICT` | 当前 `int64` JSON number 不能满足 JavaScript 安全整数门禁;严格门禁包括 `genealogy-workspace-openapi-contract.ps1`、`g03-bootstrap-openapi-contract.ps1`、`lineage-openapi-contract.ps1`。所有 ID 动作继承本键。 |
-| `C-S-CAPABILITY` | 家谱、成员、世系等读取 DTO 中的服务端 capability/角色字段;无独立 operation | `CONTRACT_CONFLICT` | 快照没有闭合 `canView/canEdit/canInvite/canAudit/canDelete` owner,不能由前端角色名或一次 403 推测。 |
-| `C-S-CONTENT-LOCK` | 无跨谱文、成长记录和重要证件的统一访问密码/内容锁 operation | `MISSING_OPERATION` | 不得复用登录密码、A05 重置密码或参考项目三套旧 wrapper;若以后批准,必须先定义独立资源、可见性、校验、重置和限流 owner。 |
-| `C-S-PLATFORM-SHARE` | 当前 UniApp/Android 系统分享 adapter;无后端 operation | `NOT_APPLICABLE` | 唯一 owner 只负责调起平台分享、取消/失败和返回状态;分享内容必须由对应业务读取 owner 提供,例如 M08 当前活动家谱票据用 `C-G-INVITE-LIST`、APP 推广用 `C-M-PROMO`、宣传视频用 `C-M-PROMO-VIDEO`、F10 家族视频用 `C-F-VIDEO-READ`。未在冻结候选真机验证前产品动作最多为 `PARTIAL`。 |
-| `C-S-PLATFORM-CLIPBOARD` | 当前 UniApp/Android 系统剪贴板 adapter;无后端 operation | `NOT_APPLICABLE` | 唯一 owner 只负责复制动作、拒绝/失败和返回状态,不拥有被复制的票据或推荐码;业务内容分别来自 `C-G-INVITE-LIST`、`C-M-REFERRAL`。未在冻结候选真机验证前不得宣称复制成功。 |
-| `C-S-SAFE-EXTERNAL-OPEN` | 当前 UniApp/Android 外部链接打开 adapter 与目标 allowlist;无后端 operation | `NOT_APPLICABLE` | 唯一 owner 只负责 HTTPS、官方域名 allowlist、取消/失败和返回状态,不拥有下载地址内容;任意参考 URL、HTTP 地址或应用市场 scheme 均不得直接迁入。 |
-| `C-S-NAV` | 当前 `pages.json`、route key、参数 validator、返回与根切换的本地导航 owner;无后端 operation | `NOT_APPLICABLE` | 只拥有导航结构,不拥有目标页数据或权限;所有跨页 PA 自动继承,参考项目菜单不能绕过当前注册路由。 |
-| `C-LOCAL` | 协议、关于、版本号等经批准的正式本地静态 owner | `NOT_APPLICABLE` | 只适用于无需远端事实的内容,不能用于邀请码、通知详情、支付结果或人物资料。 |
-
-### 3.2 A 认证与账号
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-A-TAC-API` | `GET /captcha/require`
`POST /captcha/challenge`
`POST /captcha/verify` | `CONTRACT_CONFLICT` | `auth-tac-openapi-contract.ps1` 是已知红灯;其中“密码登录必须消费 `validToken`”与已确认的“密码登录不接收 `validToken`、TAC 为客户端强制前置”冲突,执行时必须先修订门禁口径。 |
-| `C-A-TAC-A11Y` | 复用 `GET /captcha/require`、`POST /captcha/challenge`、`POST /captcha/verify`;`VerificationPayload` 声明多种验证码载荷 | `CONTRACT_CONFLICT` | 快照并非完全缺 operation;当前冲突是无拖动替代的服务端可用性、选择/降级语义和真机证据未闭合,`auth-android-accessibility-release-gate.ps1` 仍为红灯。 |
-| `C-A-LOGIN` | `POST /genealogy/app/auth/login` | `CONTRACT_CONFLICT` | 密码 wire、TAC 口径和会话结果未闭合;关联 `auth-tac-openapi-contract.ps1`、`password-change-openapi-contract.ps1`。 |
-| `C-A-SMS-SEND` | `POST /genealogy/app/auth/sms/code` | `CONTRACT_CONFLICT` | 公共发码场景、`validToken`、四位/六位 OTP 及换绑场景归属冲突;本键是该 path 的唯一 owner,注册和重置不得重复拥有。 |
-| `C-A-SMS-LOGIN` | `POST /genealogy/app/auth/login/sms` | `CONTRACT_CONFLICT` | OTP schema 与 TAC 发码闭环未通过 `auth-tac-openapi-contract.ps1`。 |
-| `C-A-REGISTER` | `POST /genealogy/app/auth/register` | `CONTRACT_CONFLICT` | OTP 和密码唯一 wire owner 未闭合;另依赖 `C-A-SMS-SEND`。 |
-| `C-A-RESET` | `PUT /genealogy/app/auth/password/reset` | `CONTRACT_CONFLICT` | OTP、密码策略及旧 MD5 路径冲突;另依赖 `C-A-SMS-SEND`。 |
-| `C-A-WECHAT` | 无 APP 微信登录 operation | `MISSING_OPERATION` | `GET /auth/code` 是遗留接口,不是可确认的当前 APP 微信登录 owner。 |
-| `C-A-PROFILE-READ` | `GET /genealogy/app/auth/profile` | `CONTRACT_CONFLICT` | 当前响应不能满足严格资料 DTO;关联 `profile-openapi-contract.ps1`。 |
-| `C-A-PROFILE-WRITE` | `PUT /genealogy/app/auth/profile` | `CONTRACT_CONFLICT` | dirty-only merge、版本/CAS、清空语义和结果未知恢复未闭合;关联 `profile-update-openapi-contract.ps1`。 |
-| `C-A-PASSWORD-CHANGE` | `PUT /genealogy/app/auth/password` | `CONTRACT_CONFLICT` | 密码 wire、全部会话撤销和稳定错误码未闭合;关联 `password-change-openapi-contract.ps1`。 |
-| `C-A-PHONE-SEND` | 无当前受保护的换绑专用发码 operation | `MISSING_OPERATION` | 门禁目标 `POST /genealogy/app/auth/phone/sms/code` 未出现在受保护快照;公共发码不得擅自替代。 |
-| `C-A-PHONE-CHANGE` | `PUT /genealogy/app/auth/phone` | `CONTRACT_CONFLICT` | 当前密码、新号 OTP、会话撤销和结果语义未闭合;关联 `phone-change-openapi-contract.ps1`。 |
-| `C-A-DEACTIVATE` | `POST /genealogy/app/auth/account/deactivate` | `CONTRACT_CONFLICT` | `AccountDeactivateBody.smsCode` 的四位内联 schema 与 `phone-change-openapi-contract.ps1` 要求的统一短信 Secret/六位口径冲突;另依赖 `C-A-SMS-SEND`。敏感操作仅限人工窗口。 |
-| `C-A-LOGOUT` | `DELETE /genealogy/app/auth/logout` | `CONTRACT_CONFLICT` | token/client 归属、幂等和终态错误未闭合;关联 `logout-openapi-contract.ps1`。 |
-
-### 3.3 G 家谱、行政区划、申请与成员
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-S-REGION-CHILDREN` | `GET /genealogy/region/children` | `DECLARED_UNVERIFIED` | 共享行政区划 owner;待线上字段和层级语义验真。 |
-| `C-S-REGION-PATH` | `GET /genealogy/region/path/{regionCode}` | `DECLARED_UNVERIFIED` | 待祖先路径顺序和缺失码语义验真。 |
-| `C-S-REGION-SEARCH` | `GET /genealogy/region/search` | `CONTRACT_CONFLICT` | `g03-bootstrap-openapi-contract.ps1` 错把目标写成未声明的 `GET /genealogy/app/region/search`,门禁必须按快照真实路径重订。 |
-| `C-S-REGION-DETAIL` | `GET /genealogy/region/{regionCode}` | `DECLARED_UNVERIFIED` | 待详情字段验真。 |
-| `C-G-MINE` | `GET /genealogy/app/genealogies/mine` | `CONTRACT_CONFLICT` | 通用列表响应不能提供稳定 ID、角色和 capability;关联 `genealogy-workspace-openapi-contract.ps1`、`g03-bootstrap-openapi-contract.ps1`。 |
-| `C-G-PUBLIC` | `GET /genealogy/app/genealogies/public` | `CONTRACT_CONFLICT` | 搜索游标、结果 DTO 和错误语义未满足 `join-application-openapi-contract.ps1`。 |
-| `C-G-OPTIONS` | `GET /genealogy/app/genealogies/options` | `DECLARED_UNVERIFIED` | 不能在未验真前与 public/mine 列表混用。 |
-| `C-G-DETAIL-READ` | `GET /genealogy/app/genealogies/{genealogyId}` | `CONTRACT_CONFLICT` | 通用对象响应且与 overview 形成两个单谱读取候选;关联 `genealogy-workspace-openapi-contract.ps1`。 |
-| `C-G-OVERVIEW` | `GET /genealogy/app/genealogies/{genealogyId}/overview` | `CONTRACT_CONFLICT` | 稳定 DTO、访问状态和 capability 未闭合;关联 workspace、G03、G11 门禁。 |
-| `C-G-SETTINGS` | `PUT /genealogy/app/genealogies/{genealogyId}` | `CONTRACT_CONFLICT` | dirty-only merge、版本/CAS、权限和 pending 申请保护未闭合;关联 `g11-settings-openapi-contract.ps1`。 |
-| `C-G-CREATE-GENEALOGY` | `POST /genealogy/app/genealogies` | `CONTRACT_CONFLICT` | G03 第一次写只有通用结果,不能确认稳定 `genealogyId`、幂等和结果未知状态。 |
-| `C-T-PERSON-CREATE` | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons` | `CONTRACT_CONFLICT` | G03 第二次写兼通用人物创建 owner;根人物保护、稳定 `personId`、ID wire 和权限未闭合。 |
-| `C-G-CREATE-RECOVERY` | 无可确认的幂等结果查询或创建续办 operation | `MISSING_OPERATION` | mine/overview 的存在不能证明可安全恢复第一次写;门禁目标 `GET /genealogy/app/genealogy-bootstrap-operations/{operationKey}` 未声明。现有 G03 两个门禁仍按原子 bootstrap 设计,与已确认两阶段方案冲突,执行时须先重订。 |
-| `C-G-JOIN-CREATE` | `POST /genealogy/app/genealogies/{genealogyId}/join-applies` | `CONTRACT_CONFLICT` | 幂等 receipt、稳定申请 ID 和结果语义未闭合;关联 `join-application-openapi-contract.ps1`。 |
-| `C-G-JOIN-RECOVERY` | 无当前申请提交结果查询 operation | `MISSING_OPERATION` | 门禁目标 `GET /genealogy/app/genealogies/join-apply-requests/{requestKey}` 未声明。 |
-| `C-G-JOIN-MINE` | `GET /genealogy/app/genealogies/join-applies/mine` | `CONTRACT_CONFLICT` | 游标和 typed item 未闭合。 |
-| `C-G-JOIN-WITHDRAW` | `DELETE /genealogy/app/genealogies/join-applies/{applyId}` | `CONTRACT_CONFLICT` | 权限、幂等和稳定结果未闭合。 |
-| `C-G-JOIN-PENDING` | `GET /genealogy/app/genealogies/{genealogyId}/join-applies/pending` | `CONTRACT_CONFLICT` | capability、游标和 typed item 未闭合。 |
-| `C-G-JOIN-AUDIT` | `PUT /genealogy/app/genealogies/{genealogyId}/join-applies/{applyId}/audit` | `CONTRACT_CONFLICT` | 审核权限、并发、重复审核和结果 receipt 未闭合。 |
-| `C-G-INVITE-LIST` | 无当前可邀请家谱/活动票据列表或单票据读取 operation | `MISSING_OPERATION` | M08 不得从本地列表推断邀请权限,也不得用静态票据恢复签发/撤销结果。 |
-| `C-G-INVITE-ISSUE` | 无当前家谱邀请票据签发 operation | `MISSING_OPERATION` | 门禁目标幂等签发 path 未出现在受保护快照;响应未知时只能经权威列表恢复,不得再次盲签。 |
-| `C-G-INVITE-REVOKE` | 无当前家谱邀请票据撤销 operation | `MISSING_OPERATION` | 门禁目标撤销 path 未出现在受保护快照;撤销竞态与未知结果必须经权威列表收敛。 |
-| `C-G-INVITE-RESOLVE` | 无当前邀请码解析 operation | `MISSING_OPERATION` | 不得以本地解码、旧 wrapper 或普通搜索代替。 |
-| `C-G-INVITE-REDEEM` | 无当前邀请码兑换/直接入谱 operation | `MISSING_OPERATION` | 不得借普通加入申请绕过独立邀请语义。 |
-| `C-G-INVITE-RESULT` | 无当前邀请码兑换结果查询 operation | `MISSING_OPERATION` | 结果未知时不得重复提交。 |
-| `C-G-POEM` | `GET /genealogy/app/genealogies/{genealogyId}/generation-poems`
`POST /genealogy/app/genealogies/{genealogyId}/generation-poems`
`POST /genealogy/app/genealogies/{genealogyId}/generation-poems/batch/preview`
`POST /genealogy/app/genealogies/{genealogyId}/generation-poems/batch/save`
`GET /genealogy/app/genealogies/{genealogyId}/generation-poems/management`
`PUT /genealogy/app/genealogies/{genealogyId}/generation-poems/{poemId}` | `CONTRACT_CONFLICT` | `g12-generation-poem-openapi-contract.ps1` 要求另一套唯一 GET/PUT、版本/CAS 和旧入口移除,门禁目标与当前六个 operation 不一致。 |
-| `C-G-MEMBER-READ` | `GET /genealogy/app/genealogies/{genealogyId}/members`
`GET /genealogy/app/genealogies/{genealogyId}/members/options` | `CONTRACT_CONFLICT` | 成员与世系人物身份、typed item 和 capability 未闭合。 |
-| `C-G-MEMBER-UPDATE` | `PUT /genealogy/app/genealogies/{genealogyId}/members/{memberId}` | `CONTRACT_CONFLICT` | body 中 `lineagePersonId` 同时成为邀请绑定候选,尚无唯一 mutation owner。 |
-| `C-G-MEMBER-REMOVE` | `DELETE /genealogy/app/genealogies/{genealogyId}/members/{memberId}` | `CONTRACT_CONFLICT` | 移除权限、所有者保护和结果未知处理未闭合。 |
-| `C-G-MEMBER-LEAVE` | `DELETE /genealogy/app/genealogies/{genealogyId}/members/me` | `CONTRACT_CONFLICT` | 本人退出约束、最后管理员/所有者保护及终态未闭合。 |
-| `C-G-MEMBER-TRANSFER` | `PUT /genealogy/app/genealogies/{genealogyId}/members/owner-transfer` | `CONTRACT_CONFLICT` | 高风险权限迁移、并发和结果确认未闭合。 |
-| `C-G-SORT` | 无家谱批量排序或始祖世代安全 operation | `MISSING_OPERATION` | 不能复用人物 `sortOrder` 或字辈接口。 |
-| `C-G-ADMIN` | 无管理员列表、授权和细粒度 capability operation | `MISSING_OPERATION` | members operation 不能在无明确角色/capability 合同时替代。 |
-| `C-G-DELETE` | 无当前删除家谱 operation | `MISSING_OPERATION` | 参考项目 `delGenealogy` 不是当前合同;不得借设置 PUT、成员退出或本地移除列表伪装删除。 |
-
-`invite-ticket-openapi-contract.ps1` 中以下目标路径均未出现在受保护快照,只是门禁目标:`GET /genealogy/app/genealogies/{genealogyId}/invite-tickets/mine`、`POST /genealogy/app/genealogies/{genealogyId}/invite-tickets`、`DELETE /genealogy/app/genealogies/{genealogyId}/invite-tickets/{inviteTicketId}`、`POST /genealogy/app/genealogy-invite-tickets/resolve`、`POST /genealogy/app/genealogy-invite-redemptions`、`GET /genealogy/app/genealogy-invite-redemption-requests/{requestKey}`。
-
-### 3.4 T 世系与邀请绑定
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-T-TREE` | `GET /genealogy/app/genealogies/{genealogyId}/lineage/tree` | `CONTRACT_CONFLICT` | 当前通用树不能满足头像卡、稳定图关系、窗口化、遮蔽和权限合同;`lineage-openapi-contract.ps1` 的 v2 路径只是未声明目标。 |
-| `C-T-DETAIL` | `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` | `CONTRACT_CONFLICT` | 通用对象、ID/capability 未闭合,T03 仍是 fixture 半成品;关联 `t03-member-remote-contract.ps1`。 |
-| `C-T-LIST` | `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons`
`GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/page`
`GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/options` | `CONTRACT_CONFLICT` | 三个读取 owner 的边界、typed item、ID 和 capability 未闭合。 |
-| `C-T-PARENT` | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/parents` | `CONTRACT_CONFLICT` | 父/母意图、`sex` enum、重复关系、图版本和权限未闭合。 |
-| `C-T-SPOUSE` | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/spouses` | `CONTRACT_CONFLICT` | 关系方向、重复/冲突、图版本和权限未闭合。 |
-| `C-T-SIBLING` | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/siblings` | `CONTRACT_CONFLICT` | 性别、共同父母、排行和关系原子性未闭合。 |
-| `C-T-CHILD` | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/children` | `CONTRACT_CONFLICT` | 儿/女 `sex` enum、另一父母、排行和关系原子性未闭合。 |
-| `C-T-EDIT` | `PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` | `CONTRACT_CONFLICT` | 宽 body、字段白名单、并发、头像链及 `appUserId` 绑定混入同一 PUT。 |
-| `C-T-RANK` | 候选但非独立 owner:`PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` | `CONTRACT_CONFLICT` | 只有单人物 `sortOrder`,没有同辈原子重排、冲突版本或完整结果;正式 PUT owner 仍是 `C-T-EDIT`。 |
-| `C-T-BIND-INVITE` | 无当前人物邀请签发、送达和接受 operation | `MISSING_OPERATION` | 家谱票据目标也未声明,且不能证明等于“绑定某一人物”。 |
-| `C-T-BIND-IDENTITY` | 无受邀账号身份查找或安全匹配 operation | `MISSING_OPERATION` | 不得按手机号、昵称或参考本地数据猜 `appUserId/memberId`。 |
-| `C-T-BIND-MUTATION` | 冲突候选:`PUT /genealogy/app/genealogies/{genealogyId}/members/{memberId}`
冲突候选:`PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` | `CONTRACT_CONFLICT` | 一个写 `lineagePersonId`,一个写 `appUserId`;快照没有指定唯一 owner、原子性或禁止双写规则。 |
-| `C-T-BIND-RESULT` | 无当前人物绑定结果查询 operation | `MISSING_OPERATION` | 结果未知时不得重试或双写。 |
-| `C-T-DELETE` | `DELETE /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` | `CONTRACT_CONFLICT` | 当前语义更接近停用;根人物、被引用人物、权限及图版本未闭合。 |
-
-### 3.5 文件链
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-S-FILE-BINARY-WRITE` | `POST /genealogy/app/files/upload`
`POST /genealogy/app/files/resumable/init`
`POST /genealogy/app/files/resumable/chunk`
`POST /genealogy/app/files/resumable/complete` | `CONTRACT_CONFLICT` | 上传成功结果、`ossId` 安全 wire、断点续传幂等及完成后可访问事实未闭合。 |
-| `C-S-FILE-REFERENCE-WRITE` | `POST /genealogy/app/files/reference`
`DELETE /genealogy/app/files/reference` | `CONTRACT_CONFLICT` | 引用对象身份、重复引用、删除引用与删除二进制边界未闭合。 |
-| `C-S-FILE-READ` | 无按 `ossId`/文件 ID 恢复可访问 URL 或授权读取的 GET operation | `MISSING_OPERATION` | 上传返回值或历史 URL 不能替代冷启动读取 owner。 |
-
-### 3.6 F 家族内容
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-F-FEED-READ` | `GET /genealogy/app/genealogies/{genealogyId}/feeds`
`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}` | `CONTRACT_CONFLICT` | 读 DTO、游标、作者投影和媒体策略未闭合;关联 `family-feed-read-openapi-contract.ps1`。 |
-| `C-F-FEED-PAGE-LEGACY` | `GET /genealogy/app/genealogies/{genealogyId}/feeds/page` | `CONTRACT_CONFLICT` | 门禁识别为应移除的重复读取 owner。 |
-| `C-F-FEED-WRITE` | `POST /genealogy/app/genealogies/{genealogyId}/feeds`
`PUT /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}`
`DELETE /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}`
`POST /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/likes`
`DELETE /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/likes` | `DECLARED_UNVERIFIED` | 媒体另依赖文件链,所有 ID 另依赖 `C-S-ID`。 |
-| `C-F-FEED-MODERATION` | 无动态置顶或加精 operation | `MISSING_OPERATION` | 不能用 `sortOrder/status` 猜测管理语义,也不能只改本地列表。 |
-| `C-F-COMMENT-READ` | `GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments`
`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments/{commentId}/replies` | `CONTRACT_CONFLICT` | 根评论/回复投影、删除占位和游标语义未闭合。 |
-| `C-F-COMMENT-PAGE` | `GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments/page`
`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments/{commentId}/replies/page` | `CONTRACT_CONFLICT` | `/comments/page` 是重复 owner 候选,回复分页也须与 canonical 读取统一。 |
-| `C-F-COMMENT-WRITE` | `POST /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments`
`DELETE /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments/{commentId}` | `DECLARED_UNVERIFIED` | 回复创建只在 `parentCommentId` 真实语义确认后复用 POST。 |
-| `C-F-ARTICLE` | `GET /genealogy/app/genealogies/{genealogyId}/article-categories`
`GET /genealogy/app/genealogies/{genealogyId}/articles`
`POST /genealogy/app/genealogies/{genealogyId}/articles`
`GET /genealogy/app/genealogies/{genealogyId}/articles/{articleId}`
`PUT /genealogy/app/genealogies/{genealogyId}/articles/{articleId}`
`DELETE /genealogy/app/genealogies/{genealogyId}/articles/{articleId}` | `DECLARED_UNVERIFIED` | 分类只有读取;文章字段、富文本和媒体白名单待验真。 |
-| `C-F-ARTICLE-CATEGORY-WRITE` | 无谱文分类新增、编辑或删除 operation | `MISSING_OPERATION` | 分类读取不能反推分类管理能力,不得借文章 POST/PUT 代替。 |
-| `C-F-ALBUM` | `GET /genealogy/app/genealogies/{genealogyId}/albums`
`POST /genealogy/app/genealogies/{genealogyId}/albums`
`PUT /genealogy/app/genealogies/{genealogyId}/albums/{albumId}`
`DELETE /genealogy/app/genealogies/{genealogyId}/albums/{albumId}` | `DECLARED_UNVERIFIED` | 封面媒体和删除语义另受文件与权限门禁约束。 |
-| `C-F-PHOTO-READ` | `GET /genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos` | `DECLARED_UNVERIFIED` | 照片访问 URL 仍依赖 `C-S-FILE-READ`。 |
-| `C-F-PHOTO-WRITE` | `POST /genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos`
`DELETE /genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos/{photoId}` | `DECLARED_UNVERIFIED` | 新增照片是“文件写+照片记录写”两段动作。 |
-| `C-F-PHOTO-EDIT` | 无照片元数据编辑 operation | `MISSING_OPERATION` | 不得借相册 PUT 或本地数组修改。 |
-| `C-F-VIDEO-DELETE` | `DELETE /genealogy/app/genealogies/{genealogyId}/videos/{videoId}` | `DECLARED_UNVERIFIED` | 孤立删除没有读取对象来源时不得启用。 |
-| `C-F-VIDEO-READ` | 无视频列表、详情或播放资源读取 operation | `MISSING_OPERATION` | 不使用参考项目 URL 或全局 store 代替。 |
-| `C-F-VIDEO-WRITE` | 无视频发布或编辑 operation | `MISSING_OPERATION` | 文件上传不等于视频实体发布。 |
-| `C-F-VIDEO-COMMENT` | 无家族视频评论读取、发表、回复或删除 operation | `MISSING_OPERATION` | 动态评论 `C-F-COMMENT-*` 只拥有 feed 资源,不能跨资源复用为视频评论。 |
-| `C-F-VIDEO-REACTION` | 无家族视频点赞/取消点赞 operation | `MISSING_OPERATION` | 不得用本地计数、动画或参考项目裸请求冒充服务端反应状态。 |
-
-### 3.7 R 族务记录
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-R-RELATIVE` | `GET /genealogy/app/genealogies/{genealogyId}/relative-records`
`POST /genealogy/app/genealogies/{genealogyId}/relative-records`
`GET /genealogy/app/genealogies/{genealogyId}/relative-records/{relativeId}`
`PUT /genealogy/app/genealogies/{genealogyId}/relative-records/{relativeId}`
`DELETE /genealogy/app/genealogies/{genealogyId}/relative-records/{relativeId}` | `DECLARED_UNVERIFIED` | 收/送方向、金额精度、人物关联和权限待验真。 |
-| `C-R-CEREMONY` | `GET /genealogy/app/genealogies/{genealogyId}/ceremonies`
`POST /genealogy/app/genealogies/{genealogyId}/ceremonies`
`GET /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}`
`PUT /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}`
`DELETE /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}`
`GET /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/gifts`
`POST /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/gifts`
`DELETE /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/gifts/{giftId}` | `DECLARED_UNVERIFIED` | 祭祀献礼不能直接等同参考“贺礼邀请”。 |
-| `C-R-GROWTH` | `GET /genealogy/app/genealogies/{genealogyId}/growth-records`
`POST /genealogy/app/genealogies/{genealogyId}/growth-records`
`GET /genealogy/app/genealogies/{genealogyId}/growth-records/{recordId}`
`PUT /genealogy/app/genealogies/{genealogyId}/growth-records/{recordId}`
`DELETE /genealogy/app/genealogies/{genealogyId}/growth-records/{recordId}` | `DECLARED_UNVERIFIED` | 人物 ID、分类 enum 和媒体字段待验真。 |
-| `C-R-MEMO` | `GET /genealogy/app/genealogies/{genealogyId}/memos`
`POST /genealogy/app/genealogies/{genealogyId}/memos`
`GET /genealogy/app/genealogies/{genealogyId}/memos/{memoId}`
`PUT /genealogy/app/genealogies/{genealogyId}/memos/{memoId}`
`DELETE /genealogy/app/genealogies/{genealogyId}/memos/{memoId}` | `DECLARED_UNVERIFIED` | 日期、提醒和权限字段待验真。 |
-| `C-R-MERIT-BASE` | `GET /genealogy/app/genealogies/{genealogyId}/merit-records`
`POST /genealogy/app/genealogies/{genealogyId}/merit-records`
`DELETE /genealogy/app/genealogies/{genealogyId}/merit-records/{meritId}` | `DECLARED_UNVERIFIED` | 只支持列表、新增和单删;图片另依赖文件链。 |
-| `C-R-MERIT-DETAIL` | 无功德详情 operation | `MISSING_OPERATION` | 列表项投影不能伪装远端详情。 |
-| `C-R-MERIT-EDIT` | 无功德编辑 operation | `MISSING_OPERATION` | 不得用再次 POST 猜测新增/编辑复用语义。 |
-| `C-R-LIFE` | 无人生事件 operation | `MISSING_OPERATION` | 保持关闭。 |
-| `C-R-DOCUMENT` | 无重要证件 operation | `MISSING_OPERATION` | 隐私敏感,不能迁移参考旧接口或示例数据。 |
-| `C-R-GREETING` | 无独立“贺礼邀请”列表、详情、增改删 operation | `MISSING_OPERATION` | `relative-records` 是人情往来,`ceremonies/gifts` 是祭祀/献礼;二者都不能因名称接近而冒充本业务。 |
-
-### 3.8 N 通知
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-N-LIST` | `GET /genealogy/app/notifications` | `CONTRACT_CONFLICT` | 当前是无稳定 item/type/target schema 的通用列表;关联 `notification-read-openapi-contract.ps1`。 |
-| `C-N-UNREAD-COUNT` | 无当前未读数 operation | `MISSING_OPERATION` | 门禁目标 `GET /genealogy/app/notifications/unread-count` 未声明。 |
-| `C-N-READ-ONE` | `POST /genealogy/app/notifications/{notificationId}/read` | `CONTRACT_CONFLICT` | 幂等、当前账号归属及稳定结果未闭合。 |
-| `C-N-READ-ALL` | `POST /genealogy/app/notifications/read-all` | `CONTRACT_CONFLICT` | 当前账号范围、幂等和结果未闭合。 |
-| `C-N-DETAIL-SAME-SESSION` | 本地 owner:N01 当前会话不可变列表项快照;来源仍是 `GET /genealogy/app/notifications` | `CONTRACT_CONFLICT` | 同会话投影可保留,但列表 item/type/target schema 不稳定;不得猜业务深链。 |
-| `C-N-DETAIL-COLD-START` | 无通知详情或按通知 ID 重取 operation | `MISSING_OPERATION` | 冷启动、进程重启、深链或快照丢失时诚实关闭。 |
-| `C-N-TYPED-REMINDER` | 候选复用 `GET /genealogy/app/notifications` | `CONTRACT_CONFLICT` | 现有列表缺稳定生日/疫苗/备忘等 type、目标 route key、参数和权限失效 schema,不能从文案猜类型。 |
-
-### 3.9 M 我的
-
-| 合同键 | 当前 operation 或唯一 owner | `contractState` | 当前阻塞和门禁 |
-| --- | --- | --- | --- |
-| `C-M-HELP-LIST` | `GET /genealogy/app/help-articles` | `CONTRACT_CONFLICT` | 完整列表 DTO 未满足 `help-center-openapi-contract.ps1`。当前 M06 的文章阅读必须由列表项投影承接。 |
-| `C-M-HELP-DETAIL` | `GET /genealogy/app/help-articles/{helpId}` | `CONTRACT_CONFLICT` | operation 已声明,但当前门禁指定完整列表为唯一远端 owner;规划不新增独立详情路由,先统一 owner 后才可启用本键。 |
-| `C-M-FEEDBACK` | `GET /genealogy/app/feedback`
`POST /genealogy/app/feedback` | `DECLARED_UNVERIFIED` | 列表范围、提交幂等和结果未知处理待验真。 |
-| `C-M-PROMO` | `GET /genealogy/app/promotions` | `DECLARED_UNVERIFIED` | 只证明推广内容读取,不代表邀请码、积分、奖励或分享变现。 |
-| `C-M-PROMO-VIDEO` | 无独立广告/宣传视频列表、详情或播放资源 operation | `MISSING_OPERATION` | `GET /genealogy/app/promotions` 未证明返回稳定可播放媒体;家族视频 `C-F-VIDEO-READ` 不能跨域替代。 |
-| `C-M-PROMO-VIDEO-COMMENT` | 无广告/宣传视频评论读取、发表、回复或删除 operation | `MISSING_OPERATION` | 不得借动态评论或家族视频评论 owner 冒充。 |
-| `C-M-PROMO-VIDEO-REACTION` | 无广告/宣传视频点赞/取消点赞 operation | `MISSING_OPERATION` | 不得用本地计数或参考控件冒充服务端状态。 |
-| `C-M-REFERRAL` | 无 APP 推广推荐码/二维码签发或读取 operation | `MISSING_OPERATION` | 推广推荐码不是家谱邀请票据,不能解析、兑换或直接入谱,也不能借 `C-G-INVITE-ISSUE` 冒充。 |
-| `C-M-REWARD` | 无邀请奖励、积分余额或奖励明细 operation | `MISSING_OPERATION` | 不得从推广文案、邀请码或本地计数推断奖励。 |
-| `C-M-VIP-READ` | `GET /genealogy/app/vip/packages`
`GET /genealogy/app/vip/orders` | `DECLARED_UNVERIFIED` | 待 typed item、金额单位和订单状态验真。 |
-| `C-M-VIP-ORDER` | `POST /genealogy/app/vip/orders` | `CONTRACT_CONFLICT` | 通用对象结果没有稳定订单 ID、幂等键、订单详情或结果未知恢复链。 |
-| `C-M-VIP-PAY` | 无支付、支付结果查询、取消或退款 operation | `MISSING_OPERATION` | 不得由创建订单 HTTP 200 进入成功页。 |
-| `C-M-MONEY` | 无余额、资金流水、提现提交或提现状态 operation | `MISSING_OPERATION` | 文件上传不能单独启用收款码/提现流程。 |
-
-未直接出现在某一 PA 合同列的键也有明确用途,不能被误当成漏接动作:`C-S-ID/C-S-CAPABILITY/C-S-NAV` 是全部相关 PA 自动继承的共享门禁;`C-G-DETAIL-READ` 是与 overview 竞争、待退役的诊断键;`C-G-MEMBER-UPDATE` 是 `C-T-BIND-MUTATION` 的冲突候选 operation 证据;`C-F-FEED-PAGE-LEGACY/C-F-COMMENT-PAGE` 是待移除的重复读取 owner;`C-F-PHOTO-EDIT` 记录未获批准产品动作的合同缺口;`C-M-HELP-DETAIL` 记录被 list-only 决策压住的声明 operation。它们不增加 PA 分母,也不能绕过对应 canonical owner。
-
-## 四、第一参考源:60 个设计文件
-
-### 4.1 D001—D030
-
-| 文件 ID / 文件 | 页面与逐动作 ID | 当前合同键与 owner | 甄别结论与改造边界 |
-| --- | --- | --- | --- |
-| `D001` `4、族谱网APP端-思维导图.pdf` | `D001-P01-A01` APP 功能树;`A02` 后台/网站/PC 分支 | A/G/T/F/R/N/M;其他端无当前路由 | `A01 仅参考交互`,作为反向覆盖目录;`A02 与当前产品冲突,明确舍弃`,不扩张本仓库 |
-| `D002` `编辑家族视频.png` | `D002-P01-A01` 选择并删除视频 | `C-F-VIDEO-READ/C-F-VIDEO-DELETE` → F10 | `后端缺失,暂时关闭`;不能因有孤立 DELETE 就启用管理页 |
-| `D003` `编辑相册.png` | `D003-P01-A01` 改名/描述/封面;`A02` 删除相册 | `C-F-ALBUM`、`C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → F07/F08 | 两项均 `改造后采用`;权限、结果未知、封面文件链和删除确认必须重做 |
-| `D004` `创建家谱 .png` | `D004-P01-A01` 填姓氏/谱名/堂号/地望/祠堂/访问权限并创建 | `C-S-REGION-CHILDREN/C-S-REGION-PATH/C-S-REGION-SEARCH/C-S-REGION-DETAIL`、`C-G-CREATE-GENEALOGY`、`C-T-PERSON-CREATE`、`C-G-CREATE-RECOVERY` → G03 | `改造后采用`;自由文本地望不能代替必填 `regionCode`;固定两阶段顺序,但首写无稳定词法 ID 或结果未知时必须停止,不能从 mine 列表猜回 |
-| `D005` `登陆.png` | `D005-P01-A01` 密码登录;`A02` 忘记;`A03` 注册;`A04` 微信登录 | `C-A-TAC-API/C-A-TAC-A11Y/C-A-LOGIN/C-A-SMS-SEND/C-A-RESET/C-A-REGISTER/C-A-WECHAT` → A01/A04/A05 | A01—A03 `改造后采用`,补 TAC/协议/错误;A04 `后端缺失,暂时关闭` |
-| `D006` `调整世代.png` | `D006-P01-A01` 调整始祖世代并联动其他成员 | `C-G-SORT` → G 候选 | `后端缺失,暂时关闭`;不能借 T06 排行或 G12 字辈 |
-| `D007` `发布视频.png` | `D007-P01-A01` 标题/描述/上传并发布视频 | `C-F-VIDEO-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → F10 | `后端缺失,暂时关闭`;上传存在也不等于视频实体发布存在 |
-| `D008` `功德录(1).png` | `D008-P01-A01` 浏览功德记录;`A02` 进入管理 | `C-R-MERIT-BASE/C-R-MERIT-DETAIL` → R11 | A01 `改造后采用`;A02 `仅参考交互`,详情/编辑合同不足 |
-| `D009` `功德录.png` | `D009-P01-A01` 多选记录;`A02` 删除 | `C-R-MERIT-BASE` → R11 | A01 `仅参考交互`;A02 `改造后采用`,服务端仅单删且需权限/二次确认 |
-| `D010` `管理世代.png` | `D010-P01-A01` 浏览字辈代次;`A02` 编辑;`A03` 新增 | `C-G-POEM` → G12 | 三项 `改造后采用`;统一到 G12 单一 owner,不建立“世代”第二合同 |
-| `D011` `加入家谱.png` | `D011-P01-A01` 粘贴邀请码并直接加入 | `C-G-INVITE-RESOLVE/C-G-INVITE-REDEEM/C-G-INVITE-RESULT` → G06 | `后端缺失,暂时关闭`;不可借普通 `C-G-JOIN-CREATE` |
-| `D012` `家谱主页 – 1.png` | `D012-P01-A01` 家谱总览;`A02` 模块导航 | `C-G-OVERVIEW` → G05 | A01/A02 均为 `仅参考交互`;作为独立总览状态证据保留,不能因与 D043 相似就判重复;红色整页视觉不直接采纳 |
-| `D013` `家谱主页 – 22.png` | `D013-P01-A01` 贺礼邀请列表;`A02` 分类筛选;`A03` 新建 | `C-R-GREETING` → R 候选 | 三项 `待用户确认`;“贺礼邀请”既非人情簿也未证明等于祭祀献礼 |
-| `D014` `家谱主页 – 23.png` | `D014-P01-A01` 多选贺礼;`A02` 删除 | 同 D013 | A01 `仅参考交互`;A02 `待用户确认`,语义与权限未定 |
-| `D015` `家谱主页 – 24.png` | `D015-P01-A01` 贺礼详情 | 同 D013 | `待用户确认`;不能用 ceremony gift 详情猜产品语义 |
-| `D016` `家谱主页 – 25.png` | `D016-P01-A01` 创建/编辑贺礼 | 同 D013 | `待用户确认`;标题、类型、金额、受邀人和状态合同均需定义 |
-| `D017` `家谱主页 – 26.png` | `D017-P01-A01` 成长日志列表;`A02` 分类/筛选;`A03` 新建 | `C-R-GROWTH` → R08 | 三项 `改造后采用`;人物 ID 与 recordType enum 先验真 |
-| `D018` `家谱主页 – 27.png` | `D018-P01-A01` 成长日志详情 | `C-R-GROWTH` → R08 | `改造后采用` |
-| `D019` `家谱主页 – 28.png` | `D019-P01-A01` 多选成长记录;`A02` 删除 | `C-R-GROWTH` → R08 | A01 `仅参考交互`;A02 `改造后采用`,只删测试数据并二次确认 |
-| `D020` `家谱主页 – 29.png` | `D020-P01-A01` 新建成长日志 | `C-R-GROWTH` → R08 | `改造后采用`;绑定真实人物,禁止本地假插入 |
-| `D021` `家谱主页 – 30.png` | `D021-P01-A01` 人情簿列表;`A02` 新建 | `C-R-RELATIVE` → R03/R04 | 两项 `改造后采用`;收/送方向、金额精度先验真 |
-| `D022` `家谱主页 – 31.png` | `D022-P01-A01` 多选人情记录;`A02` 删除 | `C-R-RELATIVE` → R03/R04 | A01 `仅参考交互`;A02 `改造后采用` |
-| `D023` `家谱主页 – 32.png` | `D023-P01-A01` 新建/编辑人情记录 | `C-R-RELATIVE` → R04 | `改造后采用` |
-| `D024` `家谱主页 – 33.png` | `D024-P01-A01` 备忘列表;`A02` 新建 | `C-R-MEMO` → R10 | 两项 `改造后采用` |
-| `D025` `家谱主页 – 34.png` | `D025-P01-A01` 管理员列表;`A02` 添加 | `C-G-ADMIN/C-G-MEMBER-READ` → G 候选 | 两项 `待用户确认`;无 capability owner,不新增假页面 |
-| `D026` `家谱主页 – 35.png` | `D026-P01-A01` 多选管理员;`A02` 删除;`A03` 权限配置 | `C-G-ADMIN/C-G-MEMBER-READ/C-G-MEMBER-REMOVE` | A01 `仅参考交互`;A02/A03 `待用户确认`,破坏性/授权能力未闭合 |
-| `D027` `家谱主页 – 36.png` | `D027-P01-A01` 选择成员并添加管理员 | `C-G-ADMIN/C-G-MEMBER-READ` | `待用户确认` |
-| `D028` `家谱主页 – 37.png` | `D028-P01-A01` 配置管理员权限 | `C-G-ADMIN` | `待用户确认`;不能把前端勾选框当服务端 capability |
-| `D029` `家谱主页 – 38.png` | `D029-P01-A01` 发布文字/图片动态;`A02` 置顶;`A03` 加精 | `C-F-FEED-WRITE/C-F-FEED-MODERATION/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → F02 | A01 `改造后采用`;A02/A03 `后端缺失,暂时关闭` |
-| `D030` `家谱主页 – 39.png` | `D030-P01-A01` 表格式世系浏览 | `C-T-TREE` → T01 | `仅参考交互`;可作为辅助模式候选,但头像卡树是当前必需主模式 |
-
-### 4.2 D031—D060
-
-| 文件 ID / 文件 | 页面与逐动作 ID | 当前合同键与 owner | 甄别结论与改造边界 |
-| --- | --- | --- | --- |
-| `D031` `家谱主页 – 40.png` | `D031-P01-A01` 搜索世系人物;`A02` 选择定位 | `C-T-LIST/C-T-TREE` → T01/T07 | 两项 `改造后采用`;搜索与树定位共享人物 ID owner |
-| `D032` `家谱主页 – 41.png` | `D032-P01-A01` 头像人物卡树;`A02` 横纵浏览 | `C-T-TREE/C-S-FILE-READ` → T01 | 两项 `改造后采用`,且是用户明确的 T01 必需能力;视觉重做为当前国风 |
-| `D033` `家谱主页 – 42.png` | `D033-P01-A01` 查看资料;`A02` 父亲;`A03` 母亲;`A04` 配偶;`A05` 兄弟姐妹;`A06` 排行;`A07` 儿子;`A08` 女儿;`A09` 邀请绑定;`A10` 编辑 | `C-T-DETAIL/C-T-PARENT/C-T-SPOUSE/C-T-SIBLING/C-T-RANK/C-T-CHILD/C-T-BIND-INVITE/C-T-BIND-IDENTITY/C-T-BIND-MUTATION/C-T-BIND-RESULT/C-T-EDIT` → T01/T03—T06/独立邀请流程 | 十项均为用户明确需求,产品取舍为 `改造后采用`;合同不足的动作执行态关闭且产品完成度 BLOCKED,不能删入口或假成功 |
-| `D034` `家谱主页 – 43.png` | `D034-P01-A01` 查看人物资料空态;`A02` 资料/亲属切换;`A03` 邀请其激活绑定;`A04` 编辑 | `C-T-DETAIL/C-T-BIND-INVITE/C-T-BIND-IDENTITY/C-T-BIND-MUTATION/C-T-BIND-RESULT/C-T-EDIT` → T03/T05/邀请流程 | A01/A02/A04 `改造后采用`;A03 产品需求已批准但当前 `后端缺失,暂时关闭` |
-| `D035` `家谱主页 – 44.png` | `D035-P01-A01` 查看人物亲属列表;`A02` 点亲属继续查看 | `C-T-DETAIL/C-T-LIST` → T03 | 两项 `改造后采用`;避免递归叠原生页,沿用单实例轨迹 |
-| `D036` `家谱主页 – 45.png` | `D036-P01-A01` 选择/绑定成长对象;`A02` 编辑头像姓名排行等人物字段;`A03` 填成长日志 | `C-T-BIND-INVITE/C-T-BIND-IDENTITY/C-T-BIND-MUTATION/C-T-BIND-RESULT/C-T-EDIT/C-T-RANK/C-R-GROWTH` → T04/T05/T06/R08 | A01 `后端缺失,暂时关闭`;A02/A03 `改造后采用`且必须按 owner 拆分,不能把排行和人物编辑合为宽表单 |
-| `D037` `家谱主页 – 46.png` | `D037-P01-A01` 阅读富文本详情 | `C-R-CEREMONY/C-M-HELP-LIST` → 取决于来源 | `仅参考交互`;通用长文阅读形态可复用,但数据 owner 必须由入口决定 |
-| `D038` `家谱主页 – 47.png` | `D038-P01-A01` 编辑人物基础资料;`A02` 微信/QQ/地址/学历/职业等扩展隐私资料 | `C-T-EDIT` → T05 | A01 `改造后采用`;A02 `与当前产品冲突,明确舍弃`,当前需求未授权且后端无隐私/可见性 owner,不采集、不存储、不上传 |
-| `D039` `家谱主页 – 48.png` | `D039-P01-A01` 帮助分类;`A02` 搜索 | `C-M-HELP-LIST` → M06 | 两项 `改造后采用` |
-| `D040` `家谱主页 – 49.png` | `D040-P01-A01` 阅读帮助文章 | `C-M-HELP-LIST` → M06 | `改造后采用`;由完整列表项投影承接,不新增独立远端 owner |
-| `D041` `家谱主页 – 50.png` | `D041-P01-A01` 分享应用;`A02` 邀请奖励/积分;`A03` 微信小程序首次登录限制 | `C-M-PROMO/C-S-PLATFORM-SHARE/C-M-REWARD/C-A-WECHAT` → 无当前路由的 M 推广候选 | A01 `仅参考交互`;A02/A03 `待用户确认`并保持关闭,禁止承诺积分或微信链,更不得覆盖 M08 家谱邀请 |
-| `D042` `家谱主页 – 51.png` | `D042-P01-A01` 填标题/描述并提交反馈 | `C-M-FEEDBACK` → M07 | `改造后采用`;真实提交失败和结果未知不得清空 |
-| `D043` `家谱主页.png` | `D043-P01-A01` 家谱总览;`A02` 模块导航 | `C-G-OVERVIEW` → G05 | A01/A02 均为 `仅参考交互`;独立保留为可能的角色、主题或业务状态,待入口/数据/权限证据证明后才决定是否与 D012 共用状态实现 |
-| `D044` `家族视频.png` | `D044-P01-A01` 视频列表;`A02` 播放;`A03` 管理;`A04` 发布 | `C-F-VIDEO-READ/C-F-VIDEO-WRITE/C-F-VIDEO-DELETE` → F10 | 四项 `后端缺失,暂时关闭`;播放 UI 可做关闭页信息参考 |
-| `D045` `家族相册.png` | `D045-P01-A01` 照片墙;`A02` 预览;`A03` 上传照片;`A04` 编辑相册 | `C-F-ALBUM/C-F-PHOTO-READ/C-F-PHOTO-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → F08/F09 | A01—A04 均为 `改造后采用`;A03/A04 必须在文件、权限和两段写闭环后实施 |
-| `D046` `谱文(1).png` | `D046-P01-A01` 管理谱文分类 | `C-F-ARTICLE-CATEGORY-WRITE` → F04/F06 | `仅参考交互`;当前合同只有分类读取,无分类增改删,管理动作关闭 |
-| `D047` `谱文.png` | `D047-P01-A01` 浏览谱文分类;`A02` 进入内容 | `C-F-ARTICLE` → F04 | 两项 `改造后采用` |
-| `D048` `谱文详情.png` | `D048-P01-A01` 阅读谱文;`A02` 添加/编辑 | `C-F-ARTICLE` → F05/F06 | 两项 `改造后采用`;富文本和媒体必须消毒/归一化 |
-| `D049` `设置世代.png` | `D049-P01-A01` 编辑代数/字辈;`A02` 保存;`A03` 删除 | `C-G-POEM` → G12 | A01—A03 均为 `改造后采用`;A03 只能改造成停用/恢复,不得猜测为物理删除 |
-| `D050` `首页 – 14.png` | `D050-P01-A01` 我的家谱列表;`A02` 搜索;`A03` 创建;`A04` 普通申请加入;`A05` 邀请码直入 | `C-G-MINE/C-G-PUBLIC/C-G-OPTIONS/C-G-CREATE-GENEALOGY/C-T-PERSON-CREATE/C-G-CREATE-RECOVERY/C-G-JOIN-CREATE/C-G-JOIN-RECOVERY/C-G-INVITE-RESOLVE/C-G-INVITE-REDEEM/C-G-INVITE-RESULT` → G01/G03/G06/G08 | A01—A04 `改造后采用`;A05 `后端缺失,暂时关闭` |
-| `D051` `首页 – 16.png` | `D051-P01-A01` 家族动态列表;`A02` 图片墙;`A03` 评论/回复;`A04` 发布 | `C-F-FEED-READ/C-F-FEED-WRITE/C-F-COMMENT-READ/C-F-COMMENT-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → F01/F02/F03 | 四项 `改造后采用`;不复制示例图片、电话号码或静态评论 |
-| `D052` `首页 – 18.png` | `D052-P01-A01` 通知列表;`A02` 全部已读;`A03` 审核加入;`A04` 打开活动通知 | `C-N-LIST/C-N-READ-ALL/C-N-DETAIL-SAME-SESSION/C-N-DETAIL-COLD-START/C-G-JOIN-AUDIT` → N01/N02/G10 | A01—A03 `改造后采用`;A03 必须深链到 G10,不能由 N01 直接审核;A04 `后端缺失,暂时关闭`,不得在无目标合同时伪造跳转 |
-| `D053` `首页 – 19.png` | `D053-P01-A01` 查看本人资料;`A02` 推广;`A03` 反馈;`A04` 安全;`A05` 帮助;`A06` 退出 | `C-A-PROFILE-READ/C-M-PROMO/C-M-FEEDBACK/C-A-PASSWORD-CHANGE/C-A-PHONE-CHANGE/C-A-LOGOUT/C-M-HELP-LIST` → M01/M03/M06/M07/M10;A02 为无当前路由候选 | A01、A03—A06 `改造后采用`;A02 同为 `改造后采用`的候选证据,但不承诺奖励且不得覆盖 M08 家谱邀请 |
-| `D054` `首页 .png` | `D054-P01-A01` 我的家谱列表;`A02` 创建;`A03` 加入 | 同 D050 | A01—A03 均为 `仅参考交互`;独立保留为可能的主题、角色或业务状态,不能只按颜色相似度与 D050 合并 |
-| `D055` `思维导图.png` | `D055-P01-A01` APP 认证/家谱/世系/内容/族务/消息/我的全功能树;`A02` 后台;`A03` 网站;`A04` PC 管理端 | A/G/T/F/R/N/M;其他端无当前路由 | A01 `仅参考交互`并作为全项目反向检查目录;A02—A04 `与当前产品冲突,明确舍弃` |
-| `D056` `添加功德人.png` | `D056-P01-A01` 姓名/内容/图片并新增功德记录 | `C-R-MERIT-BASE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → R11 | `改造后采用`;当前无编辑/详情 operation,图片 owner 待确认 |
-| `D057` `添加谱文.png` | `D057-P01-A01` 标题/正文/落款/图片质量/媒体并保存 | `C-F-ARTICLE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → F06 | `改造后采用`;只提交当前合同白名单,图片质量不是后端业务字段 |
-| `D058` `相册.png` | `D058-P01-A01` 相册列表;`A02` 新建;`A03` 打开详情 | `C-F-ALBUM` → F07/F08 | 三项 `改造后采用` |
-| `D059` `新建相册.png` | `D059-P01-A01` 名称/描述并创建相册 | `C-F-ALBUM` → F07 | `改造后采用` |
-| `D060` `字辈谱.png` | `D060-P01-A01` 浏览字辈;`A02` 管理 | `C-G-POEM` → G12 | 两项 `改造后采用` |
-
-## 五、第二参考源:78 条活动路由
-
-“参考 wrapper”只证明旧项目尝试过某动作,不是当前合同。未列入 wrapper 的裸 `uni.request`、全局 store 传 URL、硬编码数据和被注释调用均不得迁入。
-
-### 5.1 J001—J026
-
-| 路由 ID / 参考路由 | 页面与逐动作 ID | 参考 wrapper | 当前合同键与 owner | 甄别结论与边界 |
-| --- | --- | --- | --- | --- |
-| `J001` `pages/index/index` | `J001-A01` 读用户/家谱;`A02` 切谱;`A03` 模块导航;`A04` 宣传视频 | `getALLCreatGenealogyList`, `getAuthByUserGenealogy`, `getCreatGenealogy`, `getDictDataByDictCode`, `getUserInfo`, `getVideopublicize` | `C-G-MINE/C-G-OVERVIEW/C-A-PROFILE-READ/C-M-PROMO-VIDEO` → G01/G05;A04 为无当前路由候选 | A01—A03 `仅参考交互`并拆 owner;A04 `后端缺失,暂时关闭`,拒绝跨域巨型首页 |
-| `J002` `pages/login/login` | `J002-A01` 密码登录;`A02` 注册;`A03` 重置;`A04` 微信登录 | `getCaptcha`, `getDictDataByDictCodeNoToken`, `login`, `register`, `userResetPwd`, `wechatAppLogin` | `C-A-TAC-API/C-A-TAC-A11Y/C-A-LOGIN/C-A-SMS-SEND/C-A-REGISTER/C-A-RESET/C-A-WECHAT` → A01/A04/A05 | A01—A03 `改造后采用`;A04 `后端缺失,暂时关闭`;页面必须拆 owner |
-| `J003` `pages/render/render` | `J003-A01` 阳历/农历日期时间选择演示 | 无 | `C-LOCAL` → 共享控件候选 | `与当前产品冲突,明确舍弃`活动路由;需要日期选择时只参考控件行为 |
-| `J004` `pages/index/addGenealogy` | `J004-A01` 输入邀请信息直接入谱 | `inviteCreatGenealogy` | `C-G-INVITE-RESOLVE/C-G-INVITE-REDEEM/C-G-INVITE-RESULT` → G06 | `后端缺失,暂时关闭`;与 G08 普通申请隔离 |
-| `J005` `pages/index/createGenealogy` | `J005-A01` 选字典/地区并创建家谱 | `addCreatGenealogy`, `getDictDataByDictCode` | `C-S-REGION-CHILDREN/C-S-REGION-PATH/C-S-REGION-SEARCH/C-S-REGION-DETAIL/C-G-CREATE-GENEALOGY/C-T-PERSON-CREATE/C-G-CREATE-RECOVERY` → G03 | `改造后采用`;旧一次提交改为两阶段顺序,首写结果未知时停止并人工对账 |
-| `J006` `pages/index/invite` | `J006-A01` 邀请家人空壳 | 无 | `C-G-INVITE-ISSUE` | `与当前产品冲突,明确舍弃`空壳;不冒充 T01 邀请绑定 |
-| `J007` `pages/index/genealogyList/index` | `J007-A01` 家谱列表/选择;`A02` 删除家谱;`A03` 读配置 | `delGenealogy`, `getCreatGenealogy`, `getDictDataByDictCode`, `getDictDataByDictCodeNoToken` | `C-G-MINE/C-G-DELETE` → G01 | A01/A03 `改造后采用`;A02 `待用户确认`且不执行真实删除 |
-| `J008` `pages/index/genealogyList/characterTable` | `J008-A01` 查看字辈 | `getCharacterTable` | `C-G-POEM` → G12 | `改造后采用` |
-| `J009` `pages/index/genealogyList/add` | `J009-A01` 添加/编辑字辈;`A02` 删除 | `addCharacterTable`, `deleteCharacterTable` | `C-G-POEM` → G12 | A01/A02 均为 `改造后采用`;A02 只能按停用/恢复合同改造,拒绝物理删除猜测 |
-| `J010` `pages/index/puwen/classList` | `J010-A01` 读取并选择谱文分类 | `getDictDataByDictCode` | `C-F-ARTICLE` → F04/F06 | `仅参考交互`;分类必须来自当前文章合同 |
-| `J011` `pages/index/puwen/index` | `J011-A01` 谱文列表/筛选;`A02` 访问密码;`A03` 删除 | `deleteLiterature`, `getDictDataByDictCode`, `getLiterature`, `pw_is_cehck` | `C-F-ARTICLE/C-S-CONTENT-LOCK` → F04/F05 | A01/A03 `改造后采用`;A02 `待用户确认`,当前无内容锁 owner |
-| `J012` `pages/index/puwen/genealogy` | `J012-A01` 谱文详情 | `getLiteratureDetails` | `C-F-ARTICLE` → F05 | `改造后采用`;作为独立入口/详情状态证据保留,证明等价后才与其他详情入口共用实现 |
-| `J013` `pages/index/puwen/add` | `J013-A01` 新建;`A02` 编辑;`A03` 读原详情 | `addLiterature`, `getLiteratureDetails` | `C-F-ARTICLE` → F06 | 三项 `改造后采用` |
-| `J014` `pages/index/puwen/wjmm` | `J014-A01` 重置谱文访问密码;`A02` 成长日志访问密码;`A03` 证件访问密码 | `addLiterature`, `cz_update_password`, `cz_update_password_hx`, `getLiteratureDetails`, `pw_update_password`, `pw_update_password_hx`, `zy_update_password`, `zy_update_password_hx` | `C-S-CONTENT-LOCK` | 三项 `待用户确认`;明确不映射 A05,拒绝跨 F/R/证件的复制污染 |
-| `J015` `pages/index/album/index` | `J015-A01` 相册列表 | `getPhotocategoryList` | `C-F-ALBUM` → F07 | `改造后采用` |
-| `J016` `pages/index/album/add` | `J016-A01` 新建相册 | `addPhotocategory` | `C-F-ALBUM` → F07 | `改造后采用` |
-| `J017` `pages/index/album/details` | `J017-A01` 照片列表;`A02` 上传;`A03` 删除照片 | `deletePhoto`, `getPhotoList`, `uploadPhoto` | `C-F-PHOTO-READ/C-F-PHOTO-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → F08/F09 | 三项 `改造后采用`;上传与记录两段确认 |
-| `J018` `pages/index/album/edit` | `J018-A01` 编辑相册 | `addPhotocategory` | `C-F-ALBUM` → F07/F08 | `改造后采用`;不复用“新增”旧 wrapper 语义 |
-| `J019` `pages/index/document/index` | `J019-A01` 证件列表;`A02` 密码校验;`A03` 删除 | `deletePhotodocument`, `getPhotodocument`, `zy_is_cehck` | `C-R-DOCUMENT/C-S-CONTENT-LOCK` | 三项 `待用户确认`;默认关闭,不迁移身份证明或真实 PII |
-| `J020` `pages/index/document/add` | `J020-A01` 新建/编辑证件;`A02` 选择类型 | `addPhotodocument`, `getDictDataByDictCode` | `C-R-DOCUMENT` | 两项 `待用户确认`且默认关闭 |
-| `J021` `pages/index/video/index` | `J021-A01` 视频列表;`A02` 播放;`A03` 删除 | `deleteVideo`, `getVideoList` | `C-F-VIDEO-READ/C-F-VIDEO-DELETE` → F10 | A01—A03 均为 `后端缺失,暂时关闭`;A03 不得因存在孤立删除 operation 就暴露入口 |
-| `J022` `pages/index/video/add` | `J022-A01` 上传;`A02` 发布/编辑视频 | `addVideo`, `uploadFile` | `C-F-VIDEO-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` → F10 | 两项 `后端缺失,暂时关闭` |
-| `J023` `pages/index/video/xcindex` | `J023-A01` 宣传视频列表 | `getVideopublicize` | `C-M-PROMO-VIDEO` | `待用户确认`;宣传与家族视频分离 |
-| `J024` `pages/index/video/details` | `J024-A01` 从全局 store 取 URL 播放 | 无 | `C-F-VIDEO-READ` → F10 | `仅参考交互`;全局 URL 传递方式明确舍弃 |
-| `J025` `pages/index/meritsVirtues/index` | `J025-A01` 功德列表;`A02` 删除 | `deleteVirtues`, `getVirtuesList` | `C-R-MERIT-BASE` → R11 | 两项 `改造后采用` |
-| `J026` `pages/index/meritsVirtues/add` | `J026-A01` 新增;`A02` 编辑;`A03` 读取详情 | `addVirtues`, `getVirtuesDetail` | `C-R-MERIT-BASE/C-R-MERIT-EDIT/C-R-MERIT-DETAIL` → R11 | A01 `改造后采用`;A02/A03 `后端缺失,暂时关闭`,当前无详情/编辑 operation,不能假完成 |
-
-### 5.2 J027—J052
-
-| 路由 ID / 参考路由 | 页面与逐动作 ID | 参考 wrapper | 当前合同键与 owner | 甄别结论与边界 |
-| --- | --- | --- | --- | --- |
-| `J027` `pages/index/meritsVirtues/details` | `J027-A01` 功德详情 | `getVirtuesDetail` | `C-R-MERIT-DETAIL` → R11 | `后端缺失,暂时关闭`独立详情;可在列表使用服务端已有投影,但不能伪造详情 |
-| `J028` `pages/index/gift/index` | `J028-A01` 贺礼邀请列表;`A02` 分类;`A03` 删除 | `deleteGift`, `getDictDataByDictCode`, `getGift` | `C-R-GREETING` | 三项 `待用户确认`;先定义业务语义 |
-| `J029` `pages/index/gift/details` | `J029-A01` 贺礼详情 | `getGiftInfo` | 同 J028 | `待用户确认` |
-| `J030` `pages/index/gift/add` | `J030-A01` 新建;`A02` 编辑;`A03` 分类;`A04` 读取详情 | `addGift`, `getDictDataByDictCode`, `getGiftInfo` | 同 J028 | 四项 `待用户确认` |
-| `J031` `pages/index/log/index` | `J031-A01` 成长列表;`A02` 删除/批量;`A03` 进入详情 | `deleteDevelopmentlog`, `development`, `getDevelopmentlogList` | `C-R-GROWTH` → R08 | A01—A03 均为 `改造后采用`;A02 只按当前单条合同和权限实现;与 J070/J071 分别保留为可能的入口/筛选/角色状态 |
-| `J032` `pages/index/log/details` | `J032-A01` 成长详情 | `getDevelopmentlogDetails` | `C-R-GROWTH` → R08 | `改造后采用` |
-| `J033` `pages/index/log/add` | `J033-A01` 新增;`A02` 编辑;`A03` 分类 | `addDevelopmentlog`, `getDevelopmentlogDetails`, `getDictDataByDictCode` | `C-R-GROWTH` → R08 | 三项 `改造后采用` |
-| `J034` `pages/index/favor/index` | `J034-A01` 人情簿列表;`A02` 删除 | `deleteCashgift`, `getCashgiftList` | `C-R-RELATIVE` → R03 | 两项 `改造后采用` |
-| `J035` `pages/index/favor/details` | `J035-A01` 人情记录详情 | `getCashgiftDetails` | `C-R-RELATIVE` → R03/R04 | `改造后采用` |
-| `J036` `pages/index/favor/add` | `J036-A01` 新增;`A02` 编辑 | `addCashgift`, `getCashgiftDetails` | `C-R-RELATIVE` → R04 | 两项 `改造后采用` |
-| `J037` `pages/index/memorandum/index` | `J037-A01` 备忘列表;`A02` 删除 | `deleteMemorandum`, `getMemorandum` | `C-R-MEMO` → R10 | 两项 `改造后采用` |
-| `J038` `pages/index/memorandum/add` | `J038-A01` 新增;`A02` 编辑;`A03` 读取详情 | `addMemorandum`, `getMemorandumInfo` | `C-R-MEMO` → R10 | 三项 `改造后采用` |
-| `J039` `pages/index/memorandum/details` | `J039-A01` 备忘详情 | `getMemorandumInfo` | `C-R-MEMO` → R10 | `改造后采用` |
-| `J040` `pages/index/admin/index` | `J040-A01` 管理员列表;`A02` 移除 | `getManageUserDel`, `getManageUserList` | `C-G-ADMIN/C-G-MEMBER-READ/C-G-MEMBER-REMOVE` | 两项 `待用户确认`;移除须影响预览和再认证 |
-| `J041` `pages/index/admin/add` | `J041-A01` 静态成员勾选;`A02` 进入权限页 | 无 | `C-G-ADMIN` | A01/A02 均为 `与当前产品冲突,明确舍弃`;该半成品不迁移,不把假成员列表带入当前产品 |
-| `J042` `pages/index/admin/power` | `J042-A01` 读取权限;`A02` 提交管理员权限 | `addManageUser`, `getManagePower` | `C-G-ADMIN` | 两项 `待用户确认`,合同缺失前关闭 |
-| `J043` `pages/index/familyCircle/index` | `J043-A01` 动态列表;`A02` 评论列表;`A03` 评论;`A04` 删除动态 | `addComment`, `deleteUsernews`, `getComment`, `getUsernewsList` | `C-F-FEED-READ/C-F-FEED-WRITE/C-F-COMMENT-READ/C-F-COMMENT-WRITE` → F01/F03 | 四项 `改造后采用`;列表和评论/删除拆 owner |
-| `J044` `pages/index/familyCircle/add` | `J044-A01` 发布动态;`A02` 取公开字典 | `addUsernews`, `getDictDataByDictCodeNoToken` | `C-F-FEED-WRITE` → F02 | A01/A02 `改造后采用`;A02 仅使用当前明确字段 owner |
-| `J045` `pages/index/tree/index` | `J045-A01` 按父母展开表格式世系 | `getGenealogyUserByParentsId` | `C-T-TREE` → T01 | `仅参考交互`;不复制旧接口和递归数据形状 |
-| `J046` `pages/index/tree/tree` | `J046-A01` 树谱;`A02` 查看资料;`A03` 添加/编辑亲属;`A04` 删除人物 | `getGenealogyUser`, `userDel` | `C-T-TREE/C-T-DETAIL/C-T-PARENT/C-T-SPOUSE/C-T-SIBLING/C-T-CHILD/C-T-EDIT/C-T-DELETE` → T01/T03—T05 | A01—A03 `仅参考交互`并按当前 owner 重做;A04 `待用户确认`,停用不是物理删除 |
-| `J047` `pages/message/index` | `J047-A01` 通知/广告/文章混排;`A02` 直接审核入谱;`A03` 人物列表 | `auditInGenealogy`, `getad_list`, `getArticleList`, `getNoticeList`, `getUserList` | `C-N-LIST/C-G-JOIN-AUDIT/C-T-LIST` → N01/G10 | A01 `仅参考交互`但须拆类型;A02 `改造后采用`为跳 G10,不在 N01 写;A03 `与当前产品冲突,明确舍弃`错位数据 |
-| `J048` `pages/message/details` | `J048-A01` 通知详情 | `getNoticeDetails` | `C-N-DETAIL-SAME-SESSION/C-N-DETAIL-COLD-START` → N02 | `后端缺失,暂时关闭` LIVE 详情;仅允许列表当代内存投影 |
-| `J049` `pages/mine/index` | `J049-A01` 我的主页/资料;`A02` 宣传/广告;`A03` 删除账号 | `delUser`, `getad_list`, `getDictDataByDictCodeNoToken`, `getUserInfo`, `getVideopublicize` | `C-A-PROFILE-READ/C-M-PROMO/C-A-DEACTIVATE` → M01/M10 | A01 `改造后采用`;A02/A03 `待用户确认`,A03 为敏感注销候选且不归主页直调 |
-| `J050` `pages/mine/help` | `J050-A01` 帮助分类;`A02` 文章列表 | `getArticleList`, `getHelpClass` | `C-M-HELP-LIST` → M06 | 两项 `改造后采用` |
-| `J051` `pages/mine/setting` | `J051-A01` 设置导航;`A02` 帮助/协议内容 | `getArticleList`, `getHelpClass` | `C-M-HELP-LIST/C-LOCAL` → M03/M10 | A01/A02 均为 `仅参考交互`;设置只做导航,不另建数据 owner |
-| `J052` `pages/mine/password` | `J052-A01` 修改密码 | `userEditPWD` | `C-A-PASSWORD-CHANGE` → M04 | `改造后采用`;旧密码 wire 不能迁移为新合同 |
-
-### 5.3 J053—J078 与注释路由
-
-| 路由 ID / 参考路由 | 页面与逐动作 ID | 参考 wrapper | 当前合同键与 owner | 甄别结论与边界 |
-| --- | --- | --- | --- | --- |
-| `J053` `pages/mine/opinion` | `J053-A01` 提交反馈 | `addUseropinion` | `C-M-FEEDBACK` → M07 | `改造后采用` |
-| `J054` `pages/mine/share` | `J054-A01` 展示推广;`A02` 立即分享 | 无 | `C-M-PROMO/C-S-PLATFORM-SHARE` → 无当前路由的 M 推广候选 | A01 `改造后采用`候选证据;A02 `仅参考交互`,旧错误跳创建家谱明确舍弃;不得覆盖 M08 家谱邀请 |
-| `J055` `pages/mine/vip_xf` | `J055-A01` 套餐;`A02` 创建/支付 VIP | `getMemberLevel`, `getUserInfo`, `payVip` | `C-M-VIP-READ/C-M-VIP-ORDER/C-M-VIP-PAY` → M09 | A01 `改造后采用`为只读;A02 `后端缺失,暂时关闭`支付闭环 |
-| `J056` `pages/mine/vip_success` | `J056-A01` 查询购买记录/成功 | `vip_log` | `C-M-VIP-READ/C-M-VIP-PAY` → M09 | `后端缺失,暂时关闭`成功页;只能由权威订单结果进入 |
-| `J057` `pages/mine/helpDetails` | `J057-A01` 帮助详情 | `getArticleDetails` | `C-M-HELP-LIST` → M06 | `改造后采用`产品意图;当前由列表项投影承接,旧独立详情 owner 不迁入 |
-| `J058` `pages/index/relationship/index` | `J058-A01` 静态人物/亲属资料;`A02` 邀请激活 | 无 | `C-T-DETAIL/C-T-BIND-INVITE/C-T-BIND-IDENTITY/C-T-BIND-MUTATION/C-T-BIND-RESULT` → T03/邀请流程 | A01 `仅参考交互`;A02 产品需求保留但当前 `后端缺失,暂时关闭` |
-| `J059` `pages/index/tree/personalData` | `J059-A01` 人物资料 | `getUserInfoId` | `C-T-DETAIL` → T03 | `改造后采用` |
-| `J060` `pages/index/tree/add` | `J060-A01` 绑定账号;`A02` 编辑头像/姓名/排行/父亲/生卒;`A03` 确认 | 无 | `C-T-BIND-INVITE/C-T-BIND-IDENTITY/C-T-BIND-MUTATION/C-T-BIND-RESULT/C-T-EDIT/C-T-RANK/C-T-PARENT` → T04—T06 | A01—A03 均为 `与当前产品冲突,明确舍弃`;宽静态表单实现不迁移,字段须逐 owner 甄别后重做 |
-| `J061` `pages/mine/userInfo` | `J061-A01` 本人资料;`A02` 添加父母;`A03` 配偶;`A04` 兄弟姐妹;`A05` 子女;`A06` 单人;`A07` 人物编辑;`A08` 排行/层级 | `addBrotherSister`, `addChildren`, `addOneUser`, `addParents`, `addUserspouse`, `getDictDataByDictCode`, `getDictDataByDictCodeNoToken`, `getLevelList`, `getMomList`, `getUserInfoId`, `getUserSpouseInfoId`, `userEdit` | `C-A-PROFILE-READ/C-A-PROFILE-WRITE/C-T-PARENT/C-T-SPOUSE/C-T-SIBLING/C-T-CHILD/C-T-EDIT/C-T-RANK` → M02/T04—T06 | A01—A05、A07/A08 `改造后采用`产品意图,但必须拆 owner;A06 与当前产品冲突,`明确舍弃`未绑定通用人物新建;旧一页多模式和旧 wrapper 全部舍弃 |
-| `J062` `pages/index/log/selectUser` | `J062-A01` 选择成长人物;`A02` 管理员选择分支 | `getUserList` | `C-T-LIST/C-R-GROWTH/C-G-ADMIN` → R08 | A01 `改造后采用`;A02 `与当前产品冲突,明确舍弃`未完成分支 |
-| `J063` `pages/index/genealogyList/ancestorsOrder` | `J063-A01` 调整始祖世代空占位 | 无 | `C-G-SORT` | `与当前产品冲突,明确舍弃`空文件;功能候选保持后端缺失关闭 |
-| `J064` `pages/mine/helpList` | `J064-A01` 按分类读帮助文章 | `getArticleList` | `C-M-HELP-LIST` → M06 | `改造后采用` |
-| `J065` `pages/content/detail` | `J065-A01` 账号协议;`A02` 帮助/关于富文本 | `getNewsDetails` | `C-LOCAL/C-M-HELP-LIST` → A/M06/M10 共享查看器 | A01/A02 均为 `仅参考交互`;入口决定 owner,明确不是 F05 谱文 |
-| `J066` `pages/mine/fenxiang` | `J066-A01` 推广推荐码/二维码;`A02` 复制;`A03` 下载 App;`A04` 分享变现 | 无 | `C-M-REFERRAL/C-M-PROMO/C-M-MONEY/C-S-PLATFORM-CLIPBOARD/C-S-PLATFORM-SHARE/C-S-SAFE-EXTERNAL-OPEN` → 无当前路由的 M 推广候选 | A01/A02 `后端缺失,暂时关闭`,明确不是家谱票据;A03 `仅参考交互`且只能由安全外链 owner 承接;A04 `待用户确认`;四项均不得覆盖 M08 |
-| `J067` `pages/login/register` | `J067-A01` 注册;`A02` 性别/邀请码;`A03` 协议 | `getCaptcha`, `getDictDataByDictCodeNoToken`, `register` | `C-A-TAC-API/C-A-TAC-A11Y/C-A-SMS-SEND/C-A-REGISTER/C-LOCAL` → A04 | A01—A03 `改造后采用`;A02 只保留当前合同字段,旧邀请码不迁入 |
-| `J068` `pages/mine/changemobile` | `J068-A01` 当前密码+新号换绑 | `userEditMobile` | `C-A-TAC-API/C-A-TAC-A11Y/C-A-PHONE-SEND/C-A-PHONE-CHANGE` → M05 | `改造后采用`产品目标;旧缺 TAC/OTP/会话撤销合同明确舍弃 |
-| `J069` `pages/index/sortGenealogy` | `J069-A01` 读取用户家谱;`A02` 批量排序 | `changeGenealogySort`, `getALLCreatGenealogyList` | `C-G-MINE/C-G-SORT` → G01 候选 | A01 `改造后采用`并复用 G01;A02 `后端缺失,暂时关闭`,不同于 T06/G12 |
-| `J070` `pages/index/log/list` | `J070-A01` 人物/分类成长列表;`A02` 密码校验;`A03` 删除;`A04` 新建 | `cz_is_cehck`, `deleteDevelopmentlog`, `getDevelopmentlogList`, `getDictDataByDictCode` | `C-R-GROWTH/C-S-CONTENT-LOCK` → R08 | A01/A03/A04 `改造后采用`并独立保留此筛选/入口状态;证明与 J031 等价后才共用实现;A02 `待用户确认` |
-| `J071` `pages/index/log/class` | `J071-A01` 成长分类;`A02` 进入列表;`A03` 错位删除逻辑 | `deleteDevelopmentlog`, `getDevelopmentlogList`, `getDictDataByDictCode` | `C-R-GROWTH` → R08 | A01/A02 `仅参考交互`;A03 `与当前产品冲突,明确舍弃` |
-| `J072` `pages/index/video/video2` | `J072-A01` 纵滑播放;`A02` 评论;`A03` 点赞;`A04` 分享;`A05` 裸请求旧 HTTP | 无 | `C-F-VIDEO-READ/C-F-VIDEO-COMMENT/C-F-VIDEO-REACTION/C-S-PLATFORM-SHARE` → F10 候选 | A01—A04 `仅参考交互`但分别进入浏览、评论、点赞、分享候选,不能共用读取 owner;A05 `与当前产品冲突,明确舍弃` |
-| `J073` `pages/index/video/video3` | `J073-A01` 宣传纵滑播放;`J073-A02@comment` 评论;`J073-A02@reaction` 点赞;`J073-A02@share` 分享;`J073-A03` 裸请求旧接口 | 无 | A01 → `C-M-PROMO-VIDEO`;A02@comment → `C-M-PROMO-VIDEO-COMMENT`;A02@reaction → `C-M-PROMO-VIDEO-REACTION`;A02@share → `C-M-PROMO-VIDEO/C-S-PLATFORM-SHARE` | A01 与三个 A02 语义子动作均 `仅参考交互`,不代表批准宣传业务;A03 `与当前产品冲突,明确舍弃` |
-| `J074` `pages/index/video/video4` | `J074-A01@browse` 第三套纵滑;`J074-A01@comment` 评论;`J074-A02` 旧 HTTP 与外部云接口 | 无 | A01@browse → `C-F-VIDEO-READ`;A01@comment → `C-F-VIDEO-COMMENT`;A02 无可迁移 owner | 两个 A01 语义子动作均 `仅参考交互`;A02 `与当前产品冲突,明确舍弃` |
-| `J075` `pages/message/ad_detail` | `J075-A01` 广告/宣传消息详情 | `ad_detail`, `getDictDataByDictCodeNoToken` | `C-N-DETAIL-SAME-SESSION/C-N-DETAIL-COLD-START/C-M-PROMO` → N02 | `待用户确认`;服务端消息类型/目标未闭合前关闭 |
-| `J076` `pages/mine/withdrawal` | `J076-A01` 余额;`A02` 资金流水;`A03` 进入提现 | `getUserInfo`, `money_log` | `C-M-MONEY` | 三项 `待用户确认`且关闭 |
-| `J077` `pages/mine/tixian` | `J077-A01` 提现金额;`A02` 上传收款码;`A03` 提交;`A04` 混入成长日志残留 | `add_tixian`, `addDevelopmentlog`, `getDevelopmentlogDetails`, `getDictDataByDictCode` | `C-M-MONEY/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | A01—A03 `待用户确认`且关闭;A04 `与当前产品冲突,明确舍弃`复制污染 |
-| `J078` `pages/mine/tixian_log` | `J078-A01` 提现记录/状态/审核时间 | `tixian_log` | `C-M-MONEY` | `待用户确认`且关闭 |
-| `JX001` `pages/index/vertical-swiper/vertical-swiper`(注释) | `JX001-A01` 纵向短视频实验 | 无 | `C-F-VIDEO-READ` → F10 | `与当前产品冲突,明确舍弃`活动路由候选;只保留交互证据且不计 78 分母 |
-
-## 六、7 个未注册页面文件
-
-| 文件 ID / 相对路径 | 页面与逐动作 ID | 参考 wrapper | 当前 owner | 甄别结论 |
-| --- | --- | --- | --- | --- |
-| `JU01` `pages/index/genealogyList.vue` | `JU01-A01` 全功能菜单导航;`A02` 错配按钮/文案 | 无 | `C-S-NAV/C-G-OVERVIEW` → G05 与各业务域 | A01 `仅参考交互`并作为可能的角色/菜单状态保留;A02 `与当前产品冲突,明确舍弃`;未注册页面不自动新增路由 |
-| `JU02` `pages/index/tree/tree2.vue` | `JU02-A01` 树谱;`A02` 资料;`A03` 父母;`A04` 配偶;`A05` 兄弟姐妹;`A06` 儿子;`A07` 女儿;`A08` 编辑;`A09` 其他关系入口;`A10` 删除 | `getGenealogyUser`, `userDel` | `C-T-TREE/C-T-DETAIL/C-T-PARENT/C-T-SPOUSE/C-T-SIBLING/C-T-CHILD/C-T-EDIT/C-T-DELETE/C-S-NAV` → T01/T03—T06 | A01—A09 `仅参考交互`并作为另一树状态证据保留,旧代码整体舍弃;A10 `待用户确认`。其中“女儿”复用 `addSon` 是反例 |
-| `JU03` `pages/index/vertical-swiper/j-video.nvue` | `JU03-A01` 视频子项播放/暂停 | 无 | `C-F-VIDEO-READ` → F10 | `仅参考交互`;随实验页不注册 |
-| `JU04` `pages/index/vertical-swiper/vertical-swiper.nvue` | `JU04-A01` 纵向列表;`A02` 播放切换 | 无 | `C-F-VIDEO-READ` → F10 | 两项 `仅参考交互`;这是 JX001 的目标文件,不计活动路由 |
-| `JU05` `pages/index/video/douyin-scrollview/douyin-scrollview.vue` | `JU05-A01` 纵滑;`JU05-A02` 播放;`JU05-A03` 评论;`JU05-A04@reaction` 点赞;`JU05-A04@share` 分享;`JU05-A05` 裸请求旧/外部接口 | 无 | A01/A02 → `C-F-VIDEO-READ`;A03 → `C-F-VIDEO-COMMENT`;A04@reaction → `C-F-VIDEO-REACTION`;A04@share → `C-F-VIDEO-READ/C-S-PLATFORM-SHARE` | A01—A03 与两个 A04 语义子动作均 `仅参考交互`;A05 `与当前产品冲突,明确舍弃` |
-| `JU06` `pages/index/video/douyin-scrollview/douyin-scrollview.nvue` | `JU06-A01` 纵滑;`JU06-A02` 播放;`JU06-A03` 评论;`JU06-A04@reaction` 点赞;`JU06-A04@share` 分享;`JU06-A05` 裸请求旧/外部接口 | 无 | A01/A02 → `C-F-VIDEO-READ`;A03 → `C-F-VIDEO-COMMENT`;A04@reaction → `C-F-VIDEO-REACTION`;A04@share → `C-F-VIDEO-READ/C-S-PLATFORM-SHARE` | A01—A03 与两个 A04 语义子动作均 `仅参考交互`;A05 `与当前产品冲突,明确舍弃` |
-| `JU07` `pages/mine/index2.vue` | `JU07-A01` 资料;`A02` 反馈;`A03` 帮助;`A04` 设置;`A05` 退出 | `getUserInfo` | `C-A-PROFILE-READ/C-M-FEEDBACK/C-M-HELP-LIST/C-A-PASSWORD-CHANGE/C-A-PHONE-CHANGE/C-A-LOGOUT/C-S-NAV` → M01/M06/M07/M10 | 五项 `仅参考交互`;作为可能的角色/布局状态保留,未注册事实不等同于无产品价值 |
-
-## 七、反向覆盖索引
-
-| 当前 owner | 设计证据 | 完成项目证据 | 规划结论 |
-| --- | --- | --- | --- |
-| A01/A04/A05 认证 | D005、D053、D055 | J002、J065、J067 | 密码/短信/注册/找回按 TAC 与当前合同改造;微信关闭 |
-| G01/G03/G05 家谱工作区 | D004、D012、D043、D050、D054、D055 | J001、J005、J007、JU01 | 列表/概览/两阶段创建采用;旧巨型首页和菜单壳不迁移 |
-| G06/G08—G10 加入与审核 | D011、D050、D052 | J004、J047 | 普通申请采用;邀请码直入关闭;通知只能回流 G10 |
-| G11/G12 设置与字辈 | D006、D010、D049、D060 | J008、J009、J063、J069 | 字辈采用;始祖世代和家谱排序缺 owner 关闭 |
-| G 管理员与破坏性成员动作 | D025—D028 | J040—J042 | 待用户确认;无 capability 前关闭 |
-| T01/T03—T08 | D030—D036、D038、D055 | J045、J046、J058—J062、JU02 | T01 十入口已批准;头像卡/面板按当前架构重做;排行/绑定按合同关闭但不删需求 |
-| F01—F03 动态 | D029、D051、D055 | J043、J044 | 动态/评论改造采用;置顶/加精关闭 |
-| F04—F06 谱文 | D046—D048、D057 | J010—J014 | 列表/详情/编辑采用;内容密码待确认 |
-| F07—F09 相册/媒体 | D003、D045、D058、D059 | J015—J018 | 相册/照片采用;共享文件链闭合前不假上传 |
-| F10 视频 | D002、D007、D044 | J021、J022、J024、J072、J074、JX001、JU03—JU06;J023/J073 为独立 M 宣传视频证据 | 家族视频完整后端链缺失,保持关闭;纵滑只作交互证据;宣传视频不得借 F10 owner |
-| R01/R02 人物录与人物资料 | D031、D034—D036、D038 | J058—J062 | R01、R02 分别作为 PA-049、PA-038/048 的独立路由状态,复用唯一列表/详情/编辑数据 owner;R02 通用新建本地预览舍弃,编辑只导航 T05 |
-| R03/R04 人情往来 | D021—D023 | J034—J036 | 改造采用 |
-| R05—R07 礼仪/贺礼候选 | D013—D016、D037 | J028—J030 | “贺礼邀请”语义待确认,不能强塞祭祀献礼 |
-| R08 成长 | D017—D020、D036 | J031—J033、J062、J070、J071 | 改造采用;各入口/筛选/角色状态分别保留,证明等价后才共用 R08 实现 |
-| R10/R11 备忘/功德 | D008、D009、D024、D056 | J025—J027、J037—J039 | 现有 operation 范围内采用;缺详情/编辑的动作关闭 |
-| R09/重要证件 | D055 | J019、J020 | 人生事件与证件均缺 owner;证件另有隐私风险,保持关闭/待确认 |
-| N01/N02 与 G01/M01 未读入口 | D052、D055 | J047、J048、J075 | 列表/已读采用;未读计数使用唯一 `C-N-UNREAD-COUNT` owner,当前缺 operation 不从分页长度推断;N02 仅列表当代投影,详情/目标跳转关闭 |
-| M01—M10 | D039—D042、D053、D055 | J049—J057、J064—J068、J075—J078、JU07 | M08 保持当前“家谱邀请票据” owner;资料/安全/帮助/反馈/关于采用;APP 推广、推荐码、奖励、变现均为无当前路由候选,分别使用 `C-M-PROMO/C-M-REFERRAL/C-M-REWARD/C-M-MONEY`,不得冒充家谱邀请 |
-| S-ID/S-PERM/S-FILE/S-REGION | D003、D004、D032、D036、D038、D045、D056、D057 | 所有含 ID、权限、上传、地区动作的 J/JU 记录 | 全域唯一 owner;任何一个域不得另造兼容 ID、权限或上传协议 |
-
-## 八、规范产品动作账本
-
-本账本在用户确认规划前冻结产品动作身份和分母。`PA-xxx` 是产品动作,不是来源文件数量;`CUR:` 表示当前路由基线,`!` 表示只作为反例、禁止迁移。`D001-A01`(全项目功能目录)与 `D055-A01`(全项目思维导图)由全部 PA 继承,不在每行重复。PA 的“来源证据反链”栏允许把单页、默认状态的设计动作简写为 `Dxxx-Axx`;它与源表中的完整 `Dxxx-P01-S01-Axx` 是同一 ID,不是新增来源。相同 PA 下的多个来源仍保留各自 `D/J/JX/JU` 状态 ID、六类结论和验收记录;共用 owner 不等于合并状态证据。
-
-边界固定为:`必需`进入产品完成分母;`候选`保留稳定 PA ID,但用户未单独批准时不进入完成分母,初始 `productCompletion=NOT_APPLICABLE`。规划阶段没有任何 PA 可标 `COMPLETE`。表中 `P/B/NA` 分别表示 `PARTIAL/BLOCKED/NOT_APPLICABLE`。
-
-### 8.1 A 认证:PA-001—PA-006
-
-| PA | 唯一 owner / 产品动作 | 边界 | 合同键 | 来源证据反链 | 初始 |
-| --- | --- | --- | --- | --- | --- |
-| `PA-001` | A01 密码+TAC 登录 | 必需 | `C-A-TAC-API/C-A-TAC-A11Y/C-A-LOGIN` | D005-A01;J002-A01;CUR:A01 | B |
-| `PA-002` | A01 短信 TAC、发码并登录 | 必需 | `C-A-TAC-API/C-A-TAC-A11Y/C-A-SMS-SEND/C-A-SMS-LOGIN` | D005-A01〔登录视觉态〕;CUR:A01 | B |
-| `PA-003` | A04 TAC、发码并注册 | 必需 | `C-A-TAC-API/C-A-TAC-A11Y/C-A-SMS-SEND/C-A-REGISTER` | D005-A03;J002-A02;J067-A01—A03;CUR:A04 | B |
-| `PA-004` | A05 TAC、发码并找回密码 | 必需 | `C-A-TAC-API/C-A-TAC-A11Y/C-A-SMS-SEND/C-A-RESET` | D005-A02;J002-A03;CUR:A05 | B |
-| `PA-005` | A-LEGAL 阅读服务条款/隐私协议 | 必需 | `C-LOCAL` | J065-A01;J067-A03;D005-A01—A03〔登录协议态〕 | P |
-| `PA-006` | A01 微信一键登录 | 候选 | `C-A-WECHAT` | D005-A04;D041-A03;J002-A04 | NA |
-
-### 8.2 G 家谱工作区:PA-007—PA-034
-
-| PA | 唯一 owner / 产品动作 | 边界 | 合同键 | 来源证据反链 | 初始 |
-| --- | --- | --- | --- | --- | --- |
-| `PA-007` | G01 查看/筛选我的家谱列表 | 必需 | `C-G-MINE` | D050-A01;D054-A01〔主题态〕;J001-A01;J007-A01/A03;J069-A01;CUR:G01 | B |
-| `PA-008` | G01 切换当前家谱上下文 | 必需 | `C-G-MINE/C-G-OVERVIEW` | J001-A02;D012-A01/A02、D043-A01/A02〔不同总览状态〕;CUR:G01 | B |
-| `PA-009` | G03 两阶段创建家谱及首位人物;仅首写稳定返回 ID 后续办 | 必需 | `C-S-REGION-CHILDREN/C-S-REGION-PATH/C-S-REGION-SEARCH/C-S-REGION-DETAIL/C-G-CREATE-GENEALOGY/C-T-PERSON-CREATE/C-G-CREATE-RECOVERY` | D004-A01;D050-A03;D054-A02;J005-A01;CUR:G03 | B |
-| `PA-010` | G05 查看家谱总览并进入模块 | 必需 | `C-G-OVERVIEW` | D012-A01/A02〔状态一〕;D043-A01/A02〔状态二〕;J001-A03;JU01-A01〔菜单态〕;!JU01-A02;CUR:G05 | B |
-| `PA-011` | G06 搜索公开家谱 | 必需 | `C-G-PUBLIC/C-G-OPTIONS` | D050-A02;CUR:G06 | B |
-| `PA-012` | G08 提交普通加入申请 | 必需 | `C-G-JOIN-CREATE/C-G-JOIN-RECOVERY` | D050-A04;D054-A03;CUR:G08 | B |
-| `PA-013` | G09 查看我的加入申请 | 必需 | `C-G-JOIN-MINE` | CUR:G09 | B |
-| `PA-014` | G09 撤回加入申请 | 必需 | `C-G-JOIN-WITHDRAW` | CUR:G09 | B |
-| `PA-015` | G10 查看待审核申请 | 必需 | `C-G-JOIN-PENDING` | D052-A03;J047-A02〔通知回流态〕;CUR:G10 | B |
-| `PA-016` | G10 审核申请(同意/拒绝) | 必需 | `C-G-JOIN-AUDIT` | D052-A03;J047-A02;CUR:G10 | B |
-| `PA-017` | G11 查看家谱设置 | 必需 | `C-G-OVERVIEW` | CUR:G11 | B |
-| `PA-018` | G11 更新允许修改的家谱设置 | 必需 | `C-G-SETTINGS` | CUR:G11 | B |
-| `PA-019` | G12 查看字辈/代次 | 必需 | `C-G-POEM` | D010-A01;D060-A01;J008-A01;CUR:G12 | B |
-| `PA-020` | G12 新增字辈 | 必需 | `C-G-POEM` | D010-A03;D060-A02〔管理入口〕;J009-A01;CUR:G12 | B |
-| `PA-021` | G12 编辑字辈 | 必需 | `C-G-POEM` | D010-A02;D049-A01/A02;J009-A01;CUR:G12 | B |
-| `PA-022` | G12 停用/恢复字辈 | 必需 | `C-G-POEM` | D049-A03;J009-A02 | B |
-| `PA-023` | M08 选择有正式邀请权限的家谱并查看当前活动票据状态 | 必需 | `C-G-MINE/C-G-INVITE-LIST` | CUR:M08 | B |
-| `PA-024` | G06 解析、确认、兑换家谱邀请码,查询结果并刷新权威工作区后直接入谱 | 必需 | `C-G-INVITE-RESOLVE/C-G-INVITE-REDEEM/C-G-INVITE-RESULT/C-G-MINE/C-G-OVERVIEW` | D011-A01;D050-A05;J004-A01;CUR:G06 | B |
-| `PA-025` | G01 调整多个家谱展示顺序 | 候选 | `C-G-SORT` | J069-A02 | NA |
-| `PA-026` | G-SORT 调整始祖世代 | 候选 | `C-G-SORT` | D006-A01;J063-A01〔空壳反例〕 | NA |
-| `PA-027` | G-ADMIN 查看管理员列表 | 候选 | `C-G-ADMIN/C-G-MEMBER-READ` | D025-A01;D026-A01〔管理态〕;J040-A01 | NA |
-| `PA-028` | G-ADMIN 选择并新增管理员 | 候选 | `C-G-ADMIN/C-G-MEMBER-READ` | D025-A02;D027-A01;!J041-A01;!J062-A02〔未完成分支〕 | NA |
-| `PA-029` | G-ADMIN 查看/修改管理员权限 | 候选 | `C-G-ADMIN` | D026-A03;D028-A01;J042-A01/A02;!J041-A02 | NA |
-| `PA-030` | G-ADMIN 移除管理员 | 候选 | `C-G-ADMIN/C-G-MEMBER-REMOVE` | D026-A02;J040-A02 | NA |
-| `PA-031` | G-MEMBER 移除家谱账号成员 | 候选 | `C-G-MEMBER-REMOVE` | 当前成员合同;D055-A01 | NA |
-| `PA-032` | G-MEMBER 主动退出家谱 | 候选 | `C-G-MEMBER-LEAVE` | 当前成员合同;D055-A01 | NA |
-| `PA-033` | G-MEMBER 转移家谱所有者 | 候选 | `C-G-MEMBER-TRANSFER` | 当前成员合同;D055-A01 | NA |
-| `PA-034` | G01 删除家谱 | 候选 | `C-G-DELETE` | J007-A02 | NA |
-
-### 8.3 T 世系与成员:PA-035—PA-052
-
-| PA | 唯一 owner / 产品动作 | 边界 | 合同键 | 来源证据反链 | 初始 |
-| --- | --- | --- | --- | --- | --- |
-| `PA-035` | T01 读取并呈现头像人物卡世系树 | 必需 | `C-T-TREE/C-S-FILE-READ` | D032-A01;D033-A01—A10〔面板前置态〕;J046-A01;JU02-A01〔另一树态〕;CUR:T01 | B |
-| `PA-036` | T01 横纵浏览、搜索并定位人物 | 必需 | `C-T-TREE/C-T-LIST` | D031-A01/A02;D032-A02;CUR:T01;CUR:T07 | B |
-| `PA-037` | T01 选择人物并打开唯一操作面板 | 必需 | `C-T-TREE` | D033-A01—A10〔十入口面板态〕;J046-A01—A03;JU02-A01—A09 | B |
-| `PA-038` | T03 查看人物真实资料;R02 为独立展示状态 | 必需 | `C-T-DETAIL` | D033-A01;D034-A01〔空/未绑定态〕;J046-A02;J058-A01;J059-A01;JU02-A02;CUR:T03;CUR:R02 | B |
-| `PA-039` | T03 查看亲属并继续进入亲属资料 | 必需 | `C-T-DETAIL/C-T-LIST` | D034-A02;D035-A01/A02;J058-A01 | B |
-| `PA-040` | T04 添加父亲 | 必需 | `C-T-PARENT` | D033-A02;J046-A03;J061-A02;JU02-A03;!J060-A02〔宽表单〕;CUR:T04 | B |
-| `PA-041` | T04 添加母亲 | 必需 | `C-T-PARENT` | D033-A03;J061-A02;JU02-A03;CUR:T04 | B |
-| `PA-042` | T04 添加配偶 | 必需 | `C-T-SPOUSE` | D033-A04;J046-A03;J061-A03;JU02-A04;CUR:T04 | B |
-| `PA-043` | T04 添加兄弟姐妹 | 必需 | `C-T-SIBLING` | D033-A05;J061-A04;JU02-A05;CUR:T04 | B |
-| `PA-044` | T04 添加儿子 | 必需 | `C-T-CHILD` | D033-A07;J061-A05;JU02-A06;CUR:T04 | B |
-| `PA-045` | T04 添加女儿 | 必需 | `C-T-CHILD` | D033-A08;J061-A05;JU02-A07〔`addSon` 反例〕;CUR:T04 | B |
-| `PA-046` | T06 原子调整同辈排行 | 必需 | `C-T-RANK` | D033-A06;D036-A02;!J060-A02;J061-A08;CUR:T06 | B |
-| `PA-047` | T-BIND 邀请并绑定人物与账号 | 必需 | `C-T-BIND-INVITE/C-T-BIND-IDENTITY/C-T-BIND-MUTATION/C-T-BIND-RESULT` | D033-A09;D034-A03;D036-A01;J058-A02;!J060-A01 | B |
-| `PA-048` | T05 编辑人物资料及头像;R02 编辑入口只委托本 owner | 必需 | `C-T-EDIT/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | D033-A10;D034-A04;D036-A02;D038-A01;!D038-A02〔扩展隐私字段〕;J046-A03;!J060-A02/A03;!J061-A06〔通用人物新建〕;J061-A07;JU02-A08;CUR:T05;CUR:R02 | B |
-| `PA-049` | T07 查看/搜索世系人物目录;R01 为独立展示状态 | 必需 | `C-T-LIST` | D031-A01/A02;J062-A01;CUR:T07;CUR:R01 | B |
-| `PA-050` | T08 查看人物/成员状态 | 必需 | `C-T-LIST/C-G-MEMBER-READ` | D034-A01〔未绑定态〕;CUR:T08 | B |
-| `PA-051` | T05 停用世系人物 | 候选 | `C-T-DELETE` | J046-A04;JU02-A10 | NA |
-| `PA-052` | T01 使用表格式世系辅助模式 | 候选 | `C-T-TREE` | D030-A01〔表格态〕;J045-A01〔递归态〕 | NA |
-
-### 8.4 F 家族内容:PA-053—PA-082
-
-| PA | 唯一 owner / 产品动作 | 边界 | 合同键 | 来源证据反链 | 初始 |
-| --- | --- | --- | --- | --- | --- |
-| `PA-053` | F01 查看家族动态列表 | 必需 | `C-F-FEED-READ` | D051-A01/A02;J043-A01;CUR:F01 | B |
-| `PA-054` | F03 查看动态详情 | 必需 | `C-F-FEED-READ` | D051-A01/A02〔动态内容态〕;CUR:F03 | B |
-| `PA-055` | F02 发布文字/图片动态 | 必需 | `C-F-FEED-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | D029-A01;D051-A04;J044-A01/A02;CUR:F02 | B |
-| `PA-056` | F02 唯一编辑 owner 编辑动态;F03 仅提供入口 | 必需 | `C-F-FEED-WRITE` | CUR:F02;入口 CUR:F03 | P |
-| `PA-057` | F03 删除动态 | 必需 | `C-F-FEED-WRITE` | J043-A04 | P |
-| `PA-058` | F03 点赞/取消点赞 | 必需 | `C-F-FEED-WRITE` | 当前 feed 合同;CUR:F03 | P |
-| `PA-059` | F03 评论或回复动态 | 必需 | `C-F-COMMENT-READ/C-F-COMMENT-WRITE` | D051-A03;J043-A02/A03 | B |
-| `PA-060` | F03 删除本人评论 | 必需 | `C-F-COMMENT-WRITE` | 当前评论合同;CUR:F03 | P |
-| `PA-061` | F01 置顶动态 | 候选 | `C-F-FEED-MODERATION` | D029-A02 | NA |
-| `PA-062` | F01 加精动态 | 候选 | `C-F-FEED-MODERATION` | D029-A03 | NA |
-| `PA-063` | F04 浏览谱文分类与列表 | 必需 | `C-F-ARTICLE` | D047-A01/A02;J010-A01;J011-A01;CUR:F04 | P |
-| `PA-064` | F05 阅读谱文详情 | 必需 | `C-F-ARTICLE` | D048-A01;J012-A01〔独立详情态〕;J013-A03;CUR:F05 | P |
-| `PA-065` | F06 新建谱文 | 必需 | `C-F-ARTICLE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | D048-A02;D057-A01;J013-A01;CUR:F06 | B |
-| `PA-066` | F06 编辑谱文 | 必需 | `C-F-ARTICLE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | D048-A02;D057-A01;J013-A02;CUR:F06 | B |
-| `PA-067` | F05 唯一删除 owner 删除谱文;F04 仅提供入口 | 必需 | `C-F-ARTICLE` | J011-A03;CUR:F05 | P |
-| `PA-068` | F04 增改删谱文分类 | 候选 | `C-F-ARTICLE-CATEGORY-WRITE` | D046-A01 | NA |
-| `PA-069` | F05 设置、校验或重置谱文访问密码;获批前不启用 | 候选 | `C-S-CONTENT-LOCK` | J011-A02;J014-A01 | NA |
-| `PA-070` | F07 查看相册列表 | 必需 | `C-F-ALBUM` | D058-A01/A03;J015-A01;CUR:F07 | P |
-| `PA-071` | F07 新建相册 | 必需 | `C-F-ALBUM` | D058-A02;D059-A01;J016-A01 | P |
-| `PA-072` | F07 编辑相册资料/封面 | 必需 | `C-F-ALBUM/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | D003-A01;D045-A04;J018-A01 | B |
-| `PA-073` | F07 删除相册 | 必需 | `C-F-ALBUM` | D003-A02 | P |
-| `PA-074` | F08 查看并预览相册照片 | 必需 | `C-F-PHOTO-READ/C-S-FILE-READ` | D045-A01/A02;J017-A01;CUR:F08 | B |
-| `PA-075` | F09 上传文件并新增照片记录 | 必需 | `C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ/C-F-PHOTO-WRITE` | D045-A03;J017-A02;CUR:F09 | B |
-| `PA-076` | F08 删除照片 | 必需 | `C-F-PHOTO-WRITE` | J017-A03 | P |
-| `PA-077` | F10 查看家族视频列表 | 必需 | `C-F-VIDEO-READ` | D044-A01;J021-A01;CUR:F10 | B |
-| `PA-078` | F10 播放/查看视频详情 | 必需 | `C-F-VIDEO-READ` | D044-A02;J021-A02;J024-A01〔全局 URL 反例〕 | B |
-| `PA-079` | F10 发布视频 | 候选 | `C-F-VIDEO-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | D007-A01;D044-A04;J022-A01/A02 | NA |
-| `PA-080` | F10 编辑视频 | 候选 | `C-F-VIDEO-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | D044-A03〔管理入口〕;J022-A02 | NA |
-| `PA-081` | F10 删除视频 | 候选 | `C-F-VIDEO-READ/C-F-VIDEO-DELETE` | D002-A01;J021-A03 | NA |
-| `PA-082` | F10 纵滑短视频浏览/播放模式 | 候选 | `C-F-VIDEO-READ` | J072-A01;J074-A01@browse;JX001-A01;JU03-A01;JU04-A01/A02;JU05-A01/A02;JU06-A01/A02;!J072-A05;!J074-A02;!JU05-A05;!JU06-A05 | NA |
-
-### 8.5 R 人物与族务:PA-083—PA-124
-
-| PA | 唯一 owner / 产品动作 | 边界 | 合同键 | 来源证据反链 | 初始 |
-| --- | --- | --- | --- | --- | --- |
-| `PA-083` | R03 查看/筛选人情往来记录 | 必需 | `C-R-RELATIVE` | D021-A01;D022-A01〔管理态〕;J034-A01;CUR:R03 | P |
-| `PA-084` | R04 查看人情记录详情 | 必需 | `C-R-RELATIVE` | J035-A01;CUR:R04 | P |
-| `PA-085` | R04 新建人情记录 | 必需 | `C-R-RELATIVE` | D021-A02;D023-A01;J036-A01;CUR:R04 | P |
-| `PA-086` | R04 编辑人情记录 | 必需 | `C-R-RELATIVE` | D023-A01;J036-A02;CUR:R04 | P |
-| `PA-087` | R04 唯一删除 owner 删除人情记录;R03 仅提供入口 | 必需 | `C-R-RELATIVE` | D022-A02;J034-A02;CUR:R04 | P |
-| `PA-088` | R05 查看祭祀/礼仪列表 | 必需 | `C-R-CEREMONY` | CUR:R05 | P |
-| `PA-089` | R06 查看祭祀/礼仪详情 | 必需 | `C-R-CEREMONY` | D037-A01〔通用长文状态,入口决定 owner〕;CUR:R06 | P |
-| `PA-090` | R07 新建祭祀/礼仪 | 必需 | `C-R-CEREMONY` | CUR:R07 | P |
-| `PA-091` | R07 编辑祭祀/礼仪 | 必需 | `C-R-CEREMONY` | CUR:R07 | P |
-| `PA-092` | R06 唯一删除 owner 删除祭祀/礼仪;R05 仅提供入口 | 必需 | `C-R-CEREMONY` | 当前 ceremony 合同;CUR:R06 | P |
-| `PA-093` | R06 查看祭祀献礼 | 必需 | `C-R-CEREMONY` | 当前 gifts 合同 | P |
-| `PA-094` | R06 新增祭祀献礼 | 必需 | `C-R-CEREMONY` | 当前 gifts 合同;CUR:R06 | P |
-| `PA-095` | R06 删除祭祀献礼 | 必需 | `C-R-CEREMONY` | 当前 gifts 合同;CUR:R06 | P |
-| `PA-096` | R08 查看/筛选成长记录 | 必需 | `C-R-GROWTH` | D017-A01/A02〔普通态〕;D019-A01〔管理态〕;J031-A01〔旧入口〕;J070-A01〔人物/分类态〕;J071-A01/A02〔分类态〕;CUR:R08 | P |
-| `PA-097` | R08 查看成长记录详情 | 必需 | `C-R-GROWTH` | D018-A01;J031-A03;J032-A01 | P |
-| `PA-098` | R08 新建成长记录 | 必需 | `C-R-GROWTH` | D017-A03;D020-A01;J033-A01/A03;J070-A04 | P |
-| `PA-099` | R08 编辑成长记录 | 必需 | `C-R-GROWTH` | J033-A02 | P |
-| `PA-100` | R08 删除成长记录 | 必需 | `C-R-GROWTH` | D019-A02;J031-A02;J070-A03;!J071-A03〔错位逻辑〕 | P |
-| `PA-101` | R08 选择成长记录对应人物 | 必需 | `C-T-LIST/C-R-GROWTH` | D036-A01/A03;J062-A01 | B |
-| `PA-102` | R08 设置、校验或重置成长记录访问密码 | 候选 | `C-S-CONTENT-LOCK` | J014-A02;J070-A02 | NA |
-| `PA-103` | R10 查看备忘录列表 | 必需 | `C-R-MEMO` | D024-A01;J037-A01;CUR:R10 | P |
-| `PA-104` | R10 查看备忘详情 | 必需 | `C-R-MEMO` | J038-A03;J039-A01 | P |
-| `PA-105` | R10 新建备忘 | 必需 | `C-R-MEMO` | D024-A02;J038-A01 | P |
-| `PA-106` | R10 编辑备忘 | 必需 | `C-R-MEMO` | J038-A02 | P |
-| `PA-107` | R10 删除备忘 | 必需 | `C-R-MEMO` | J037-A02 | P |
-| `PA-108` | R11 查看功德记录 | 必需 | `C-R-MERIT-BASE` | D008-A01〔普通态〕;D009-A01〔管理态〕;J025-A01;CUR:R11 | P |
-| `PA-109` | R11 新增功德记录 | 必需 | `C-R-MERIT-BASE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | D056-A01;J026-A01 | B |
-| `PA-110` | R11 删除功德记录 | 必需 | `C-R-MERIT-BASE` | D009-A02;J025-A02 | P |
-| `PA-111` | R11 查看独立功德详情 | 候选 | `C-R-MERIT-DETAIL` | D008-A02〔进入管理/详情证据〕;J026-A03;J027-A01 | NA |
-| `PA-112` | R11 编辑功德记录 | 候选 | `C-R-MERIT-EDIT` | J026-A02 | NA |
-| `PA-113` | R09 查看/管理人生事件 | 必需 | `C-R-LIFE` | D055-A01;CUR:R09 | B |
-| `PA-114` | R-DOCUMENT 查看重要证件列表 | 候选 | `C-R-DOCUMENT` | J019-A01 | NA |
-| `PA-115` | R-DOCUMENT 查看重要证件详情 | 候选 | `C-R-DOCUMENT` | J019-A01〔列表进入详情状态〕 | NA |
-| `PA-116` | R-DOCUMENT 新建重要证件 | 候选 | `C-R-DOCUMENT/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | J020-A01/A02 | NA |
-| `PA-117` | R-DOCUMENT 编辑重要证件 | 候选 | `C-R-DOCUMENT/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | J020-A01/A02 | NA |
-| `PA-118` | R-DOCUMENT 删除重要证件 | 候选 | `C-R-DOCUMENT` | J019-A03 | NA |
-| `PA-119` | R-DOCUMENT 校验或重置证件访问密码 | 候选 | `C-S-CONTENT-LOCK` | J014-A03;J019-A02 | NA |
-| `PA-120` | R-GREETING 查看/筛选贺礼邀请列表 | 候选 | `C-R-GREETING` | D013-A01/A02;D014-A01〔管理态〕;J028-A01/A02 | NA |
-| `PA-121` | R-GREETING 查看贺礼邀请详情 | 候选 | `C-R-GREETING` | D015-A01;J029-A01;D037-A01〔通用详情态〕 | NA |
-| `PA-122` | R-GREETING 新建贺礼邀请 | 候选 | `C-R-GREETING` | D013-A03;D016-A01;J030-A01/A03 | NA |
-| `PA-123` | R-GREETING 编辑贺礼邀请 | 候选 | `C-R-GREETING` | D016-A01;J030-A02/A04 | NA |
-| `PA-124` | R-GREETING 删除贺礼邀请 | 候选 | `C-R-GREETING` | D014-A02;J028-A03 | NA |
-
-### 8.6 N 消息:PA-125—PA-131
-
-| PA | 唯一 owner / 产品动作 | 边界 | 合同键 | 来源证据反链 | 初始 |
-| --- | --- | --- | --- | --- | --- |
-| `PA-125` | N01 查看通知活动集合,并由 G01/M01 消费同一未读计数 owner | 必需 | `C-N-LIST/C-N-UNREAD-COUNT` | D052-A01;J047-A01〔混排反例〕;CUR:N01;CUR:G01;CUR:M01 | B |
-| `PA-126` | N01 标记单条通知已读 | 必需 | `C-N-READ-ONE` | 当前通知合同;CUR:N01 | B |
-| `PA-127` | N01 全部标记已读 | 必需 | `C-N-READ-ALL` | D052-A02;CUR:N01 | B |
-| `PA-128` | N02 查看通知详情 | 必需 | `C-N-DETAIL-SAME-SESSION/C-N-DETAIL-COLD-START` | D052-A04;J048-A01;CUR:N02 | B |
-| `PA-129` | N01 从通知安全回流目标业务页 | 必需 | `C-N-LIST/C-N-DETAIL-COLD-START` | D052-A03/A04;J047-A02;!J047-A03 | B |
-| `PA-130` | N02 查看广告/宣传消息详情 | 候选 | `C-N-DETAIL-SAME-SESSION/C-N-DETAIL-COLD-START/C-M-PROMO` | J075-A01 | NA |
-| `PA-131` | N01 支持生日、疫苗、备忘等类型化提醒 | 候选 | `C-N-TYPED-REMINDER` | D055-A01 | NA |
-
-### 8.7 M 我的:PA-132—PA-160
-
-| PA | 唯一 owner / 产品动作 | 边界 | 合同键 | 来源证据反链 | 初始 |
-| --- | --- | --- | --- | --- | --- |
-| `PA-132` | M01 查看“我的”主页和本人资料摘要 | 必需 | `C-A-PROFILE-READ` | D053-A01;J049-A01;JU07-A01〔另一布局态〕;CUR:M01 | B |
-| `PA-133` | M02 编辑本人资料及头像 | 必需 | `C-A-PROFILE-READ/C-A-PROFILE-WRITE/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | J061-A01;CUR:M02 | B |
-| `PA-134` | M03 查看安全设置入口及脱敏绑定信息 | 必需 | `C-A-PROFILE-READ` | D053-A04;J051-A01;JU07-A04;CUR:M03 | B |
-| `PA-135` | M04 修改登录密码 | 必需 | `C-A-PASSWORD-CHANGE` | J052-A01;CUR:M04 | B |
-| `PA-136` | M05 换绑手机号 | 必需 | `C-A-TAC-API/C-A-TAC-A11Y/C-A-PHONE-SEND/C-A-PHONE-CHANGE` | J068-A01;CUR:M05 | B |
-| `PA-137` | M06 浏览/搜索帮助分类与列表 | 必需 | `C-M-HELP-LIST` | D039-A01/A02;J050-A01/A02;J064-A01;JU07-A03;CUR:M06 | B |
-| `PA-138` | M06 阅读帮助文章 | 必需 | `C-M-HELP-LIST` | D040-A01;D037-A01〔通用长文态〕;J057-A01;J065-A02 | B |
-| `PA-139` | M07 提交反馈 | 必需 | `C-M-FEEDBACK` | D042-A01;D053-A03〔反馈入口〕;J053-A01;JU07-A02;CUR:M07 | P |
-| `PA-140` | M07 查看本人反馈记录 | 必需 | `C-M-FEEDBACK` | 当前 feedback GET;CUR:M07 | P |
-| `PA-141` | M-PROMO 查看 APP 推广内容 | 候选 | `C-M-PROMO` | D053-A02;J049-A02;J054-A01 | NA |
-| `PA-142` | M-PROMO 分享应用 | 候选 | `C-M-PROMO/C-S-PLATFORM-SHARE` | D041-A01;J054-A02;!旧跳转创建家谱 | NA |
-| `PA-143` | M-PROMO 展示/复制 APP 推广推荐码或二维码 | 候选 | `C-M-REFERRAL/C-M-PROMO/C-S-PLATFORM-CLIPBOARD` | J066-A01/A02 | NA |
-| `PA-144` | M-PROMO 展示邀请奖励或积分 | 候选 | `C-M-REWARD` | D041-A02 | NA |
-| `PA-145` | M09 查看 VIP 套餐 | 必需 | `C-M-VIP-READ` | J055-A01;CUR:M09 | P |
-| `PA-146` | M09 创建 VIP 订单 | 必需 | `C-M-VIP-ORDER` | J055-A02;CUR:M09 | B |
-| `PA-147` | M09 查看 VIP 订单记录 | 必需 | `C-M-VIP-READ` | J056-A01;CUR:M09 | P |
-| `PA-148` | M09 支付并确认 VIP 最终结果 | 候选 | `C-M-VIP-PAY` | J055-A02;J056-A01〔假成功页反例〕 | NA |
-| `PA-149` | M10 查看关于、协议、版本信息 | 必需 | `C-LOCAL` | D053-A05;J051-A02;J065-A02;CUR:M10 | P |
-| `PA-150` | M10 唯一会话 owner 安全退出登录;M01/M03 仅提供入口 | 必需 | `C-A-LOGOUT` | D053-A06;JU07-A05;CUR:M10 | B |
-| `PA-151` | M03 注销账号 | 候选 | `C-A-DEACTIVATE/C-A-SMS-SEND` | J049-A03 | NA |
-| `PA-152` | M-MONEY 查看余额和资金流水 | 候选 | `C-M-MONEY` | J076-A01/A02 | NA |
-| `PA-153` | M-MONEY 提交提现申请及收款码 | 候选 | `C-M-MONEY/C-S-FILE-BINARY-WRITE/C-S-FILE-REFERENCE-WRITE/C-S-FILE-READ` | J076-A03;J077-A01—A03;!J077-A04 | NA |
-| `PA-154` | M-MONEY 查看提现记录和状态 | 候选 | `C-M-MONEY` | J078-A01 | NA |
-| `PA-155` | M-PROMO 调起平台分享并承接变现资格/结果 | 候选 | `C-M-MONEY/C-M-PROMO/C-S-PLATFORM-SHARE` | J066-A04 | NA |
-| `PA-156` | M-PROMO 查看广告/宣传视频 | 候选 | `C-M-PROMO-VIDEO` | J001-A04;J023-A01;J049-A02〔广告/视频混排反例〕;J073-A01;!J073-A03〔旧接口〕 | NA |
-| `PA-157` | M08 幂等签发家谱邀请票据并在结果未知时恢复权威状态 | 必需 | `C-G-INVITE-ISSUE/C-G-INVITE-LIST` | !J006-A01〔空壳反例〕;CUR:M08 | B |
-| `PA-158` | M08 显示、复制并系统分享当前活动家谱邀请票据 | 必需 | `C-G-INVITE-LIST/C-S-PLATFORM-CLIPBOARD/C-S-PLATFORM-SHARE` | CUR:M08 | B |
-| `PA-159` | M08 撤销活动家谱邀请票据并收敛竞态/未知结果 | 必需 | `C-G-INVITE-REVOKE/C-G-INVITE-LIST` | CUR:M08 | B |
-| `PA-160` | M-PROMO 经官方 allowlist 打开应用下载页 | 候选 | `C-M-PROMO/C-S-SAFE-EXTERNAL-OPEN` | J066-A03 | NA |
-
-### 8.8 F/M 视频互动追加候选:PA-161—PA-166
-
-这些动作追加在账本末尾,是因为交叉评审发现旧 PA-082 把浏览、评论、点赞、分享误并到读取合同,且宣传视频不能借家族视频 owner;稳定 PA 不回收、不重排。
-
-| PA | 唯一 owner / 产品动作 | 边界 | 合同键 | 来源证据反链 | 初始 |
-| --- | --- | --- | --- | --- | --- |
-| `PA-161` | F10 查看/发表短视频评论 | 候选 | `C-F-VIDEO-COMMENT` | J072-A02;J074-A01@comment;JU05-A03;JU06-A03 | NA |
-| `PA-162` | F10 点赞/取消点赞短视频 | 候选 | `C-F-VIDEO-REACTION` | J072-A03;JU05-A04@reaction;JU06-A04@reaction | NA |
-| `PA-163` | F10 系统分享短视频 | 候选 | `C-F-VIDEO-READ/C-S-PLATFORM-SHARE` | J072-A04;JU05-A04@share;JU06-A04@share | NA |
-| `PA-164` | M-PROMO 查看/发表宣传视频评论 | 候选 | `C-M-PROMO-VIDEO-COMMENT` | J073-A02@comment | NA |
-| `PA-165` | M-PROMO 点赞/取消点赞宣传视频 | 候选 | `C-M-PROMO-VIDEO-REACTION` | J073-A02@reaction | NA |
-| `PA-166` | M-PROMO 系统分享宣传视频 | 候选 | `C-M-PROMO-VIDEO/C-S-PLATFORM-SHARE` | J073-A02@share | NA |
-
-### 8.9 共享门禁、状态变体与冻结计数
-
-共享门禁不是额外的用户产品动作,不增加 PA 分母,但所有相关 PA 必须通过:
-
-| 门禁 owner | 完成前置 |
-| --- | --- |
-| `S-ID` | 全部 ID 使用安全十进制字符串 wire |
-| `S-PERM` | 服务端 capability、撤权刷新和 403 语义 |
-| `S-FILE` | 选择/上传、业务引用、访问 URL、重进显示 |
-| `S-REGION` | 行政区划和 `regionCode` |
-| `S-SESSION` | 会话持久化、失效、账号切换和迟到响应隔离 |
-| `S-NAV` | route key、必填参数、返回与根切换 |
-| `S-A11Y` | 触控、字号、焦点、读屏和系统返回 |
-
-PA 是产品动作分母,状态变体是独立验收分母。已知跨路由复用与 N02 状态先冻结为:
-
-| 状态 ID | 入口与条件 | `contractState` | `dataMode` | `productCompletion` |
-| --- | --- | --- | --- | --- |
-| `PA-038-S01` | 从 T01/T07 进入 T03 查看人物资料 | `CONTRACT_CONFLICT` | `LOCAL_PREVIEW` | `BLOCKED` |
-| `PA-038-S02` | 从 F01→R01→R02 的人物录上下文查看同一人物资料 | `CONTRACT_CONFLICT` | `LOCAL_PREVIEW` | `BLOCKED` |
-| `PA-048-S01` | T03 进入 T05 编辑;T05 是唯一 mutation owner | `CONTRACT_CONFLICT` | `LOCAL_PREVIEW` | `BLOCKED` |
-| `PA-048-S02` | R02 的编辑入口只导航 T05,不在 R02 本地保存或报成功 | `CONTRACT_CONFLICT` | `CLOSED` | `BLOCKED` |
-| `PA-049-S01` | T01 进入 T07 世系成员目录 | `CONTRACT_CONFLICT` | `LOCAL_PREVIEW` | `BLOCKED` |
-| `PA-049-S02` | F01 进入 R01 人物录,并保留 R01→R02→R01 返回现场 | `CONTRACT_CONFLICT` | `LOCAL_PREVIEW` | `BLOCKED` |
-| `PA-125-S01` | N01 读取通知活动集合 | `CONTRACT_CONFLICT` | `LOCAL_PREVIEW` | `BLOCKED` |
-| `PA-125-S02` | G01 显示共享未读计数;不得从分页列表长度推断 | `MISSING_OPERATION` | `CLOSED` | `BLOCKED` |
-| `PA-125-S03` | M01 显示同一共享未读计数;账号切换后必须失效 | `MISSING_OPERATION` | `CLOSED` | `BLOCKED` |
-| `PA-128-S01` | 从 N01 当前会话、且完整列表项快照仍在时打开 | `CONTRACT_CONFLICT` | `LOCAL_PREVIEW` | `PARTIAL` |
-| `PA-128-S02` | 冷启动、进程重启、外部深链或快照丢失 | `MISSING_OPERATION` | `CLOSED` | `BLOCKED` |
-
-R02 现存的“通用新建人物本地预览”和 T06 现存的“关系修正本地预览”不是已批准 PA:二者均不得保存、造 ID、改列表或显示成功;本轮分别关闭/移除,不能偷换成 T04 关系新增、G03 首人创建或 PA-046 排行。用户以后若明确需要独立创建人物或关系修正,必须重新规划独立产品动作及原子合同。
-
-其他外观相似、同路由或同动作来源也按 `PA-xxx-Snn` 追加独立状态验收记录;只有入口、对象、数据、接口、权限、动作和返回行为全部证明等价时才能复用状态实现,不能删除来源状态 ID 或减少验收分母。规划阶段的 `P/PARTIAL` 只说明当前存在结构或 `LOCAL_PREVIEW`,不代表动作是 LIVE,也不能绕过 `C-S-ID/C-S-CAPABILITY` 等共享冲突。
-
-冻结计数为:
-
-- `productActionsTotal=166`;
-- `requiredActions=111`,进入产品完成分母;
-- `candidateActions=55`,用户未单独批准时不进入完成分母;
-- `approvedCandidateActions=0`;
-- 规划阶段 `completeRequiredActions=0`、`partialRequiredActions=42`、`blockedRequiredActions=69`、`notApplicableCandidateActions=55`。
-
-候选日后获批只改变边界和完成态,不创建新 PA ID;用户拒绝的候选也保留 ID 与拒绝记录,不删除或重排。
-
-## 九、甄别分母与确认后冻结方式
-
-当前源证据共拆出 341 条动作记录:
-
-| 结论 | 设计源 | 完成项目活动/注释路由 | 未注册文件 | 合计 |
-| --- | ---: | ---: | ---: | ---: |
-| 直接采用 | 0 | 0 | 0 | 0 |
-| 改造后采用 | 86 | 75 | 0 | 161 |
-| 仅参考交互 | 19 | 26 | 26 | 71 |
-| 后端缺失,暂时关闭 | 15 | 18 | 0 | 33 |
-| 与当前产品冲突,明确舍弃 | 5 | 17 | 3 | 25 |
-| 待用户确认 | 14 | 36 | 1 | 51 |
-| 合计 | 139 | 172 | 30 | 341 |
-
-这里的 341 是“源状态动作记录”,不是 341 个已经判定互不相同或已经判定重复的产品功能。多个截图和旧页面可能是独立状态,也可能在证据充分后共用同一个实现 owner。
-
-`D001-A01` 与 `D055-A01` 是全部 PA 继承的全局覆盖目录;`D001-A02`、`D055-A02—A04` 是非本仓库端形态,统一作为全局冲突舍弃证据;`J003-A01` 是纯日期时间选择演示,统一作为全局冲突舍弃证据。`J003` 是唯一不生成 PA 反链的源基 ID;上述全局动作仍必须进入 341 条来源证据计数,不能用全局规则掩盖其他逐动作遗漏。
-
-本次交给用户确认的证据与产品动作范围分别冻结为:
-
-- `referenceEvidenceRecords=341`;
-- `adaptedReferenceEvidenceRecords=161`,只是“改造后采用”的来源证据数量,不是产品动作分母;
-- `interactionEvidenceRecords=71`,只增加独立交互/状态验收证据,不新增数据合同;
-- `closedReferenceEvidenceRecords=33`;
-- `rejectedReferenceEvidenceRecords=25`;
-- `pendingReferenceEvidenceRecords=51`,已反链到候选 PA,用户未单独批准时不进入实现范围;
-- `productActionsTotal=166`、`requiredActions=111`、`candidateActions=55`、`approvedCandidateActions=0`;
-- `approvedNewRoutes=0`,当前提案全部先落现有 owner 或诚实关闭。
-
-用户确认后,执行第 0 批只能:
-
-1. 重算源文件、活动/注释路由与未注册文件清单,确认 341 条状态动作记录未因源变化失效;
-2. 原样冻结 PA-001—PA-166、111 个必需动作、55 个候选动作及全部来源反链;执行阶段不得再归并、拆分、删除或重排 PA;
-3. 对已证明等价的状态动作可共用实现 owner,但每个来源状态 ID 仍保留独立验收记录;新发现的角色/数据/权限/错误状态追加 `PA-xxx-Snn`,不能覆盖既有状态或改变产品动作身份;
-4. “待用户确认”若本次仍无单独选择,一律维持候选 PA 的 `NOT_APPLICABLE`,不新增路由;
-5. 分别报告路由分母、`requiredActions=111`、`liveCompletedActions`、逐 PA 四字段和 341 条来源证据去向,不得把来源证据条数、代码复用或结构遍历充当产品完成率;
-6. 任一参考动作即使关闭态检查通过,其必需 PA 的 `productCompletion` 仍可为 `BLOCKED`;候选未获批则为 `NOT_APPLICABLE`,不能写成整个项目 PASS。
-
-## 十、参考项目资产复用索引
-
-用户已允许把第二参考源中的图标等资产作为当前产品的复用候选。当前只读分母为 `referenceAssetFiles=531`,全部位于 `Jiapu-App\static`,约 6.45 MiB;按声明扩展名为 PNG 307、GIF 221、SVG 2、JPG 1,按文件签名为 PNG 311、GIF 217、SVG 2、JPG 1。已发现 6 个扩展名/MIME 不一致和 14 组完全重复文件。
-
-资产不会增加或改变 PA 分母。任何文件在复制前必须建立 `RAxxx` 记录并绑定一个已批准 PA 及其目标路由/组件/状态;相似图标、不同选中态、禁用态、权限态或主题态仍分别留证。逐文件字段和来源、隐私、旧品牌、格式、安全、视觉、无障碍、性能、候选构建验收门禁以主计划第 11.10 节为准。
-
-当前候选分类只用于确定优先甄别顺序,不是逐文件采用结论;在 `RAxxx` 记录通过门禁前,以下各类采用数都仍为 0:
-
-| 类别 | 例子 | 初始决定 |
-| --- | --- | --- |
-| 水墨/宗祠/谱书氛围 | `iconpng/902.png`、`iconpng/z8526@2x.png`、`login/bj.jpg`、`iconpng/book.png` | 优先甄别,尚未形成采用结论;固定文字、裁切、格式和可读性先处理 |
-| 世系人物卡装饰 | `iconpng/treeBJ.png` | 优先甄别,尚未形成采用结论;若采用优先九宫格或重绘,避免 81×105 小图直接拉伸 |
-| 中性导航/功能图标 | `icon/index.svg`、`navigation/*`、`tabulation/*`、`pu/*`、`jr.png` | 优先逐文件甄别直接复用或重绘,尚未形成采用结论;必须统一当前图标系统 |
-| 默认头像风格 | `nan.png`、`nv.png`、`treeman.png` 及尺寸变体 | `待用户确认`具体风格;先过来源、肖像、偏见和重复哈希门禁 |
-| 水墨蝴蝶动效 | `login/hd*.gif` | 仅作动效方向候选;必须有静态降级、减少动态效果和性能预算 |
-| QQ 表情、抖音/视频实验、支付/微信/支付宝、VIP/奖励、旧 logo/口号 | `emojis/qq/*`、`douyin/*`、视频实验图、`wx.png`、`zfb.png`、`logo.png` 等 | `与当前产品冲突,明确舍弃`直接迁入;必要时仅参考语义并重绘 |
-
-规划确认时固定:
-
-- `referenceAssetFiles=531`;
-- `approvedDirectReuseAssets=0`;
-- `approvedAdaptReuseAssets=0`;
-- `assetReuseAuthorization=USER_ALLOWED_WITH_PER_FILE_GATES`。
-
-收到“开始执行”后,采用数只能随已完成门禁的 `RAxxx` 增加;不能整目录复制,不能用资产存在反向启用 F10、支付、邀请奖励等关闭或候选功能,也不能迁移旧组件、样式或外部资源地址。
diff --git a/docs/今晚全量联调与明早测试执行计划.md b/docs/今晚全量联调与明早测试执行计划.md
deleted file mode 100644
index eedaaf9..0000000
--- a/docs/今晚全量联调与明早测试执行计划.md
+++ /dev/null
@@ -1,628 +0,0 @@
-# 今晚全量联调与明早测试执行计划
-
-> 修订日期:2026-07-24(北京时间)
-> 时间口径:“今晚”固定指 2026-07-23 晚间,“明早”固定指 2026-07-24 上午。
-> 当前状态:用户已明确说“开始执行”,实施、测试与 MuMu 基座联调已启动;用户将本轮硬截止提前为 `T_due=2026-07-24 08:00`。55 个候选 PA 本轮仍不纳入(`approvedCandidateActions=0`)。
-
-> 本次续执行状态:逐页 Apifox 账本已覆盖 53 个页面文件;当前页面目录不再导入 `data/mock`。已接线但未实测的创建/维护动作仍统一记为 `DECLARED_UNVERIFIED`;缺 DTO、ID、权限或上传 owner 的页面已改为明确关闭态,不以 fixture、本地数组、timer 或本地成功提示冒充服务端结果。本次续执行只做静态 API 语法和源代码归属核验,未构建、未操作 MuMu、未发起任何真实写入。
-
-## 0. 已执行记录与人工回归保留
-
-- 已通过 HBuilderX 标准基座连接 `emulator-5554` 并完成差量编译、同步、启动;本轮不构建或安装独立测试包。
-- A01 密码登录页已在 MuMu 实机完成账号密码提交、协议勾选和真实供应商 TAC challenge 展示验证;TAC 已改为供应商原生呈现,不再叠加项目标题、主题、按钮或覆盖供应商刷新/关闭控件。
-- 已自动通过 A01/A04/A05 的认证合同、认证接口映射、短信冷却、TAC renderjs 安全传输、注册后导航和编译审计;原始截图仅保存在本机临时受限目录,仓库不保留账号、手机号、令牌、短信或 TAC 相关截图。
-- 2026-07-23 20:56 全量夜跑逻辑调度 `208` 项:`PASS=162`、`EXPECTED_BLOCKED=19`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`。27 项均依赖“`localhost:5173` 的 H5 页面 + `127.0.0.1:9222` 的 Chrome 调试页”;临时 H5 服务可启动,但当前执行环境拒绝启动 Chrome 调试端口,故夜跑器已将这组前置条件显式标为 `H5_CHROME_RUNTIME_UNAVAILABLE`,不将其写成产品失败或通过。临时 H5 服务已停止。
-- 2026-07-23 23:01 HBuilderX 5.07 已通过标准基座向 `emulator-5554` 完成最新差量编译;控制台末次记录为“项目 jiapuapp 编译成功”。未生成或安装独立测试包。
-- 同轮 Apifox 合同收紧后的最小验证已通过:`compile-audit`、`navigation-flow-contract`、`t04-relative-remote-close-contract`、`t05-member-remote-close-contract`、`lineage-write-apifox-contract`、`t03-t08-member-flow-contract`、`tree-member-fixture-runtime-smoke`。新增 Apifox 写入合同脚本尚未纳入 20:56 的历史全量夜跑,后续全量统计须重新计算,不得沿用 `208` 作为最新 inventory。
-- 2026-07-23 23:29 已移除 T01 旧固定底部抽屉;点击头像人物卡现在直接打开唯一人物操作面板,面板中央头像可进入 T03,十个入口仍由同一 `selected` 人物上下文承载。相关 T01 面板、视觉、导航、文档流与编译审计已通过;23:28 的 HBuilderX 标准基座差量编译同样成功,未生成或安装独立测试包。
-- 2026-07-23 23:37 已按 Apifox 的已登录改密 owner 接通 M04:`PUT /genealogy/app/auth/password`、`oldPassword/newPassword` 32 位 MD5 摘要、鉴权与 APP `clientId` 由统一请求层持有。页面移除“仅本地校验、不提交”伪流程,成功/明确失败/离页取消均有对应状态;本轮不实际修改测试账号密码,真实调用与密码恢复保留人工窗口。
-- 2026-07-23 23:42 已按 Apifox 的已登录退出 owner 接通 M10:REMOTE 模式使用 `DELETE /genealogy/app/auth/logout`,无请求体,鉴权与 APP `clientId` 继续由统一请求层持有;严格成功才可确认远端已响应。无论请求失败、取消或结果未知,本机会话均安全清理并回到 A01,不自动重试、不把失败写成服务端已退出。本轮未对测试账号发送该敏感请求。M10、M04 的静态契约、页面归属、导航和编译审计均已通过;23:42 HBuilderX 标准基座差量编译成功,未生成或安装独立测试包。
-- 2026-07-23 23:50 当前源码的全量夜跑已完整执行 `209/209`:`PASS=163`、`EXPECTED_BLOCKED=19`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。库存为 `baselineInventoryTests=204` 加本轮 `newExecutableTests=5`。27 项均是需 `localhost:5173` 页面及 `127.0.0.1:9222` Chrome 调试页的 H5 运行时检查,统一记 `H5_CHROME_RUNTIME_UNAVAILABLE`,不写成产品失败或通过;因此本轮尚无可冻结候选。T01 唯一操作面板替换造成的五项旧断言/孤儿资产偏差已外科式收口并重跑通过。23:50 HBuilderX 5.07 标准基座差量编译成功,未生成或安装独立测试包。
-- 2026-07-24 00:00 已从 `emulator-5554` 的 HBuilderX 标准基座读取 A01 实机画面:国风登录页、密码/验证码切换、协议入口、注册/忘记密码与微信登录入口均正常呈现,无白块、截断或覆盖。此检查未输入账号密码、未触发 TAC、短信、注册、找回或任何远端写操作;截图只保留在本机临时受限目录,不入库,也不替代登录后的完整实机验收。
-- 2026-07-24 00:13 已用 HBuilderX 临时 Web 运行复核 H5 页面服务,`http://localhost:5173` 返回 `200`;但 `127.0.0.1:9222/json/list` 仍超时,当前执行环境不允许启动隔离 Chrome 调试端口。故 27 项 H5 Chrome 运行时检查继续统一记 `H5_CHROME_RUNTIME_UNAVAILABLE`,不改变其测试口径,也不将 H5 服务可达写成浏览器运行时通过。
-- 2026-07-24 00:30 已在本机临时验收目录建立唯一 `role-seed-matrix.json`:仅登记脱敏测试角色别名、允许动作、人工 TAC/短信阻塞与清理责任,当前对象 ID 为零;不含账号、手机号、密码、令牌、验证码、TAC proof 或原始响应。
-- 2026-07-24 00:31 已对当前源码重新执行 T0 夜跑:`inventory=209`、`scheduled=25`、`executed=25`、`PASS=6`、`EXPECTED_BLOCKED=19`、`FAIL=0`、`INFRA_ERROR=0`、`timedOut=0`、`notRunScheduled=0`;其余 184 项为本次 T0 未调度项,不得写成已通过。输出仅保存在本机临时验收目录。
-- 2026-07-24 00:33 已重跑 T01/T03—T08 的 12 项人物流门禁:唯一人物操作面板、树状态/视觉/文档流、成员详情映射、亲属与资料写入合同、排行关闭态、Apifox 写入合同及树 fixture runtime 均通过。此为静态/运行时映射证据,不替代未取得的真实服务端写入响应。
-- 2026-07-24 00:36 已对受保护的“我的家谱”读取执行无鉴权只读探测:远端可达,HTTP 成功信封内业务码为 `401` 且数据为空。未携带账号、令牌或其他凭据,未发送写请求;后续受保护读取/写入的唯一下一步仍是人工完成 TAC 并建立会话。
-- 2026-07-24 00:40 已对当前源码完整执行 `ALL` 夜跑 `209/209`:`PASS=163`、`EXPECTED_BLOCKED=19`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。27 项均在连接 `localhost:5173` 的 Chrome 调试页前被统一标记 `H5_CHROME_RUNTIME_UNAVAILABLE`,没有进入产品断言;不得将它们记为产品失败或通过。输出仅保存在本机临时验收目录。
-- 2026-07-24 00:45 已再次读取 `emulator-5554` 的 HBuilderX 标准基座 A01 画面:国风背景、密码/验证码切换、手机号与密码输入区、协议入口、注册和找回入口完整可见,无白屏、截断或遮挡。未输入账号、未触发 TAC/短信或远端写操作;截图只保存在本机临时受限目录。
-- 2026-07-24 00:51 已在 Apifox 的 APP 目录核对“搜索行政区划” operation 为 `GET /genealogy/region/search`,随后以只读请求取得当前部署实证:HTTP `200`、业务码 `200`、服务器 `Date=Thu, 23 Jul 2026 16:51:08 GMT`,单条结果稳定含字符串 `regionCode`、`label`、`parentCode`、`ancestors`、`regionName`、`regionLevel`、`regionType` 与 `leaf`。当前部署的旧 `/genealogy/app/region/search` 同样返回该投影,但 Apifox 的 APP 目录 owner 仍以前者为准;不将双路径同响应静默写成兼容 owner。
-- 2026-07-24 00:52 已重订 G03 客户端历史门禁:页面在原子 bootstrap、结果查询和错误收口合同缺失时保持明确关闭态,不生成本地预览,也不存在虚构的远端请求;该关闭态门禁已转为可通过并从预期阻塞清单移除。保护 OpenAPI 门禁同时只报告实际快照与 Apifox 的合同冲突,不要求项目实现未声明的 bootstrap。
-- 2026-07-24 00:55 已对更新后的当前源码再次完整执行 `ALL` 夜跑 `209/209`:`PASS=164`、`EXPECTED_BLOCKED=18`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。库存仍为 `baselineInventoryTests=204` 加本轮 `newExecutableTests=5`。27 项均因当前执行环境拒绝提供 `127.0.0.1:9222` 的 Chrome 调试运行时而在产品断言前标记为 `H5_CHROME_RUNTIME_UNAVAILABLE`;不记为产品失败或通过。输出仅保存在本机临时验收目录。
-- 2026-07-24 00:56 已重订 M06 帮助中心的旧 OpenAPI 门禁:不再要求受保护快照提供 `RListHelpArticleVo`、文章分类/标题/纯文本正文等当前 Apifox 未声明的 DTO,也不引入独立详情 owner。门禁现已通过并从预期阻塞清单移除;M06 页面补充“本地使用说明、非服务端文章”的可见来源提示,仍只提供本地说明与 M07 反馈入口,远端列表保持 `DECLARED_UNVERIFIED`。
-- 2026-07-24 00:57 已对 M06 变更后的当前源码再次完整执行 `ALL` 夜跑 `209/209`:`PASS=165`、`EXPECTED_BLOCKED=17`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。27 项仍全部为 `H5_CHROME_RUNTIME_UNAVAILABLE`,未进入产品断言;输出仅保存在本机临时验收目录。
-- 2026-07-24 00:58 HBuilderX 5.07 控制台记录“开始编译…”后输出“项目 jiapuapp 编译成功”,已通过标准基座同步 `emulator-5554`;未生成或安装独立测试包。前台 CLI 未自行退出但对应基座仍正常前台,故只将 IDE 的成功回执计为编译证据,不将 CLI 常驻误记为失败或额外构建。
-- 2026-07-24 01:04 已读取同步后的 `emulator-5554` 标准基座 A01 画面:登录页完整可见,密码/验证码登录切换、手机号/密码输入、找回、微信、注册与协议入口均无白屏、截断或错位。未输入账号、未勾选协议、未触发 TAC/短信或任何远端写请求;截图只保存在本机临时受限目录。
-- 2026-07-24 01:08 已重订认证旧 OpenAPI 门禁:密码登录的唯一请求 wire 为 `phone`、MD5 `password` 与 `grantType=password`,原生 TAC 保持客户端前置,不上传 `validToken`;短信发送仍为唯一消费 `validToken` 的认证动作。门禁与认证 API runtime 均通过,并从预期阻塞清单移除。
-- 2026-07-24 01:10 已对当前源码完整执行 `ALL` 夜跑 `209/209`:`PASS=167`、`EXPECTED_BLOCKED=15`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。剩余 15 项均为仍缺真实合同、稳定 DTO/权限投影或人工前置的精确阻塞;27 项仍为未取得 `127.0.0.1:9222` Chrome 调试运行时的 `H5_CHROME_RUNTIME_UNAVAILABLE`,未进入产品断言。输出仅保存在本机临时验收目录。
-- 2026-07-24 01:12 已修复 G03 OpenAPI 门禁以中文计划文件名读取时在 Windows PowerShell 无 BOM 解析下产生的伪阻塞;该门禁现只依据快照/客户端合同判断并通过,也已从预期阻塞清单移除。若同版本快照以后出现错误 owner,仍会以精确 `BLOCKED` 报告。
-- 2026-07-24 01:20 已再跑最新 T0:`25/25`,`PASS=10`、`EXPECTED_BLOCKED=15`、`FAIL=0`、`INFRA_ERROR=0`、`NOT_RUN=184`。本轮 allowlist 与计划中的 15 条精确阻塞逐项一致;其余 H5 运行时前置只在 `ALL` 中作为基础设施阻塞统计。
-- 2026-07-24 03:59 已将 M04/M10 的旧快照门禁改为当前 Apifox 已核对客户端接线门禁:M04 校验 `PUT /genealogy/app/auth/password` 的 MD5 body 与取消归属;M10 校验 `DELETE /genealogy/app/auth/logout` 的无 body、取消归属与本机会话兜底。两项均通过并从预期阻塞清单移除;真实改密、服务端退出继续分别保留人工恢复/登录会话验证,未发起任何远端 mutation。随后完整执行 `ALL` 夜跑 `209/209`:`PASS=169`、`EXPECTED_BLOCKED=13`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。27 项仍均为缺失 `127.0.0.1:9222` Chrome 调试运行时的 `H5_CHROME_RUNTIME_UNAVAILABLE`,未进入产品断言;输出仅保存在本机临时验收目录。
-- 2026-07-24 04:00 已按更新后的 manifest 再跑 T0:`23/23`,`PASS=10`、`EXPECTED_BLOCKED=13`、`FAIL=0`、`INFRA_ERROR=0`、`NOT_RUN=186`;allowlist 与第 0.2 节的 13 条精确自动阻塞逐项一致。该结果只说明安全/合同候选门禁没有新增失败,不替代人工 TAC、短信、敏感 mutation 或登录后实机闭环。
-- 早晨人工回归保留:密码登录真实拖动 TAC;短信登录、注册、忘记密码的真实短信与 TAC。不得绕过、猜解或重复请求这些人机/短信步骤。
-
-### 0.1 明早人工回归最短清单
-
-1. 使用已启动的 HBuilderX 标准基座进入 A01;不构建或安装独立测试包。
-2. 人工勾选协议后,在密码登录页使用已单独提供的测试账号发起一次登录;在供应商原生 TAC 中由人工完成拖动,不添加任何项目自定义样式或覆盖层。成功后检查是否进入 G01,并冷启动一次确认会话恢复;不记录或截图凭据、令牌、验证码和 TAC proof。
-3. 短信登录、注册和忘记密码各自需要真实收码人和原生 TAC:每个场景只在本人在场时发起一次,遵守页面冷却;未能完成即记录“人工 TAC/短信阻塞”,不重试、不猜解、不绕过。
-4. 换绑手机号、修改密码、注销、支付、提现、删除和退出家谱均不在无人值守阶段执行。若人工验证修改密码,结束后按约定恢复,并只在本机临时脱敏台账登记结果。
-5. 人工结果只记录页面、动作、时间、四字段结论和非敏感对象 ID;远端返回、手机号、账号、密码、令牌、验证码、TAC proof、邀请码和个人资料一律不进入仓库、文档或截图文件名。
-
-### 0.2 当前 12 条精确自动阻塞与解除条件
-
-| 门禁 | 当前阻塞 | 解除条件 |
-| --- | --- | --- |
-| Android 认证无障碍 | 原生 TAC 的 TalkBack、键盘与大字号无法由当前自动化可靠判定 | 早晨在 MuMu/真机人工完成原生 TAC 无障碍回归 |
-| G11 家谱设置 | 依赖的 mine/overview 工作区读取未取得唯一稳定 owner | 先收敛工作区读取合同与真实权限投影 |
-| G12 字辈诗 | 正常列表、维护列表、批量预览与保存已接线,但尚未获得真实登录会话下的读取/预览/保存响应 | 在人工可观察会话中按“读列表→读维护→预览→保存→维护回读”验证;浏览器 CORS 仅是 H5 环境前置,不替代 APP 业务合同 |
-| 家谱工作区 | 单家谱 overview owner 在受保护快照中缺失或不唯一 | 以 Apifox 与同版本快照收敛唯一读取路径、DTO 与权限 |
-| 邀请票据 | 无“我的票据/签发/撤销/接受”当前 operation | 后端提供独立邀请票据闭环,不以普通申请替代 |
-| 加入申请 | public 搜索/申请 operation 标识与快照不一致 | 后端同版本合同明确查询、提交、撤回、审核及结果语义 |
-| 世系 locator | 缺少精确定位人物的读取 operation | 后端声明并实测人物定位/恢复读取 owner;不得从列表猜 ID |
-| 通知读取 | 缺未读数 operation 且列表无稳定通知 DTO | 后端提供未读数与列表 item 的 ID、正文、类型/跳转投影 |
-| 通知已读状态 | notification ID wire 与 `RVoid` 信封约束不完整 | 同一 owner 收紧 ID、响应和错误语义,再用可控通知种子实测 |
-| 换绑手机号 | 缺专用受保护发码 operation 与资料前置投影 | 后端补齐 operation/DTO 后,在人工 TAC/短信窗口实测 |
-| 个人资料读取 | `RObject` 未声明可消费资料字段 | 后端提供稳定资料 DTO、权限与脱敏语义 |
-| 个人资料更新 | 缺 profileVersion/If-Match 与合并 body 合同 | 后端提供版本并发与字段白名单,再对测试账号做可恢复验证 |
-
-M04 和 M10 的客户端接线门禁现只以 Apifox 已核对的 owner、方法、body/空 body、取消归属与本机会话收口为准,已不再把旧受保护导出中虚构的会话安全语义当作阻塞。两项真实远端 mutation 仍均为 `DECLARED_UNVERIFIED`:改密必须在可恢复的人工窗口完成后恢复约定密码;服务端退出必须由人工登录会话确认撤销结果。两者均不得在无人值守期间发起。
-
-F01/F02/F03 必须拆开处理:F01 已删除本地动态列表,因列表条目 DTO 缺失而明确关闭正文/详情入口;F02 已按唯一可映射的 `feedContent` 接通发布,不发送媒体、排序或状态猜测字段;F03 动态正文继续不接线、不猜字段,一级评论已有 `FamilyFeedCommentView[]` 和明确提交 body,客户端已按该合同接通真实读取/提交并在提交后回读。没有真实登录会话、实际响应和人工可观察写入前,三页均仍是 `DECLARED_UNVERIFIED`,绝不能把接线写成已完成。
-
-## 一、计划地位
-
-本文是今晚到明早的唯一执行顺序与验收入口;[产品参考页面功能映射表](./产品参考页面功能映射表.md) 是本文直接引用的权威附件,二者必须一起评审、一起确认。既有治理文档继续提供历史背景和长期发布约束,但与今晚的批次顺序、时间分配或“可测试”口径冲突时,以本文及该附件为准。`APP.openapi.yaml` 和 `APP.openapi.json` 只读且受保护,不得修改、格式化、覆盖或删除。
-
-当前处于“执行与验证”阶段。用户已完成三人交叉评审后的规划确认并明确说“开始执行”,因此允许按本文对业务代码、页面样式、接口接线、测试、HBuilderX 与 MuMu 标准基座做最小必要变更与验证;仍不得以已存在的半成品、旧报告、参考项目能运行或局部截图代替当前项目验收。
-
-## 二、明早交付目标与项目范围
-
-本规划对象是当前 `jiapuapp` UniApp 整个项目,不只覆盖认证或世系树。A、G、T、F、R、N、M 七个路由域、共享导航与会话、文件上传、权限、异常恢复、视觉、参考资产、无障碍、构建和 MuMu 验收都在范围内。参考思维导图中的后台管理、公司官网和独立 PC 管理端不是本仓库的实现范围,只能为 APP 角色、权限和后端依赖提供参考,不能据此在当前仓库静默扩张成三个新项目。
-
-当前 `pages.json` 的 52 条活动路由是今晚的最低活动基线,不是产品功能的永久上限,也不能单独代表整个项目完成。两个参考源中发现的候选功能必须先逐页面、逐动作、逐接口完成书面甄别;只有结论为“直接采用”或“改造后采用”,且明确当前路由归属或新增路由必要性后,才进入最终活动清单。最终遍历分母为“52 条基线路由+本轮明确采纳并已注册的新增路由”,报告必须同时给出基线分母和最终分母,禁止用 52/52 掩盖已确认但未纳入的产品功能。
-
-明早目标是在用户授权开始执行后,交付一套连接 `https://backend-api.ddxcjp.cn/`、能够在 MuMu 中从认证入口开始遍历的 UniApp 测试版本。最终活动清单中的页面必须可进入、可返回、无白屏和死路;后端已有且合同可用的动作必须调用真实接口,后端确实没有可靠 operation 的动作必须显示“服务暂未开放”或同义的明确状态,不得用 mock、fixture、timer、本地数组写入或假成功伪装闭环。
-
-测试版本不等同于正式发布版本。发布签名、正式域名 CORS、后端未实现合同和真实支付等外部条件可以保留为发布阻塞,但必须提供失败门禁、复现证据、解除条件和继续步骤。
-
-“全量”按五个互不替代的层级报告,禁止把较低层通过写成整个产品完成:
-
-1. **产品库存覆盖**:52 条当前基线路由、已批准新增路由、60 个设计文件、78 条参考活动路由、1 条注释路由声明、7 个未注册参考页面文件和 531 个参考媒体资产均有稳定 ID、候选池或书面去向;资产候选池覆盖不等于逐文件批准复用。
-2. **路由结构遍历**:某候选包中的已注册活动路由可进入、可返回、无白屏和死路;这只证明结构可遍历。
-3. **实时接口迁移**:单个动作的合同、权限、请求、响应、刷新和重进闭环均完成,并通过引导式真实设备实时验收;当前没有可证明自动操控设备与断言业务结果的完整 E2E harness,因此不使用“自动 live E2E”表述。
-4. **明早最低候选**:存在可追溯的冻结候选,当前 7 个直接 `appApi` consumer 的主链结果、其余页面的数据模式、参考甄别结论和精确剩余项齐全;完整九小时窗口的目标还包括 52 条基线路由结构结果。若有效窗口不足或结构遍历未完成,未跑路由必须记 `NOT_RUN`,本层不得冒充达成。
-5. **整个产品完成**:所有已批准产品动作均达到产品完成条件;任一必需动作仍为关闭、半成品、未运行或合同阻塞时,整个产品不得标记完成。
-
-完整九小时窗口的可靠目标是第 1、2、4 层和可在时间窗内诚实完成的第 3 层;窗口缩短时第 1 层与精确剩余项仍必须交付,第 2、3、4 层按实际结果报告,不承诺在一个夜间窗口内把全部 52 页与所有参考候选都迁成 LIVE。不得为了追求数字把路径拼接、宽 DTO 直传、页面内 fixture、timer 提示、诚实关闭页或单一成功样例提前标记为产品完成。
-
-## 三、已确认口径
-
-- 当前源码基线由用户在 2026-07-23 手动拉取最新 `main` 后提供。本轮及后续执行均不进行任何 Git 操作,也不读取或写入 HEAD、分支、dirty、提交哈希作为实施前置;计划中的旧提交哈希全部视为历史记录,不再代表当前基线。
-- 第一参考源为 `C:\Users\Rain\Desktop\job\app设计`,当前只读清单为 59 张 PNG 和 1 份 PDF。项目内 `docs/design/references/产品参考原稿` 与其中 59 个同名文件 SHA-256 一致;源目录新增 `思维导图.png`,本轮只把它作为规划证据,不在用户确认前复制或归档。
-- 第二参考源为 `C:\Users\Rain\Desktop\job\Jiapu-App`。第一轮只读盘点确认其 `pages.json` 有 79 个 `path` 文本,其中 `pages/index/vertical-swiper/vertical-swiper` 整段已注释,故活动路由为 78 条;另有 79 个 Vue 文件、6 个 NVue 文件、7 个未注册页面文件和 113 个旧 API wrapper。未安装依赖、未运行、未构建、未修改。它使用旧技术与旧接口封装,只能证明候选页面、动作和状态存在,不能证明当前后端合同可用。
-- 用户已明确允许把第二参考源中的图标、插画、背景等资产作为复用候选。该授权只改变“可以逐文件甄别”的边界,不代表整目录批准,也不证明第三方/商标素材的来源或平台规范;任何资产仍须绑定已批准 PA、页面和状态,并逐文件通过来源、隐私、旧品牌、格式、视觉、无障碍和性能门禁。
-- 产品目标以用户对当前项目的明确需求为第一优先;接口路径、方法、字段、权限、状态码和失败语义以当前真实后端合同与可复现响应为准;当前项目架构、安全和国风视觉决定落地方式;截图和已完成参考项目排在最后,只作候选证据。
-- 唯一后端为 `https://backend-api.ddxcjp.cn/`,今晚联调使用 remote 模式。
-- 已提供有效测试账号;账号凭据只用于本机联调,不写入源码、测试、文档、日志或 Git。
-- 规划前在 2026-07-23 曾以标准 JSON 观察到密码登录和 `/captcha/challenge` 返回 HTTP 200,challenge 摘要为 `TIANAI/SLIDER`;后端可识别版本未留存,敏感响应不进入规划。该记录只解释此前因命令行 JSON 引号破坏得到的空体 500,不属于本轮 `LIVE_VERIFIED` 或 `PASS`。收到“开始执行”后仍须对冻结的线上合同和部署重新取证。
-- 密码登录、短信登录、注册、忘记密码都必须显示并完成 TAC。密码登录接口不接收 `validToken`,滑动成功只作为客户端强制前置;短信发送接口必须消费对应场景的 `validToken`。
-- 只有用户明确说“开始执行”后才允许操作 MuMu,并把实机画面、返回路径和交互状态纳入验收;规划确认本身不构成 MuMu 授权。
-- 当前 `static` 国风视觉资产、token 和现有页面结构仍是唯一视觉基线;参考项目资产可在逐文件通过门禁后直接复用、裁切重导出或重绘,不能反向改变已批准产品动作,也不能把旧整页红色主题、旧组件或旧样式一并迁入。
-- 允许测试账号创建带“联调测试”标识的家谱、成员、申请、动态、文章、相册、礼仪、备忘、功德和反馈等测试数据。
-- 不删除已有真实数据;无人值守期间不执行支付、换绑手机号、注销账号或不可逆操作。修改密码若经人工窗口测试,结束后恢复约定密码。
-- 本轮不执行任何 Git 命令或 Git 写操作;源码同步由用户自行负责。
-
-## 四、单页完成定义
-
-一个页面只有同时满足以下五项才标记为完成:
-
-1. 从真实业务入口可进入,系统返回键、页面返回按钮和根页面切换行为正确。
-2. 后端已有操作使用真实接口,路径、方法、请求字段、响应字段和身份上下文与 Apifox、线上文档及真实响应一致。
-3. 正常、加载、空数据、失败、无权限和提交中状态完整;写操作另有校验、重复点击保护、成功、明确失败和结果未知处理。
-4. MuMu 实际画面没有白块、文字截断、控件错位、默认原生底色或不可点击区域;普通内容、长内容和状态页均可阅读。
-5. 页面对应的 mapper/runtime 测试、静态合同、编译检查和实机检查均通过。
-
-页面内存在按钮不等于功能完成。每个主动作还必须验证“入口人物或对象正确 → 参数身份正确 → 权限来自可靠合同 → 请求结果可判定 → 返回后源页面刷新为服务端事实 → 重进页面仍一致”的跨页闭环;其中任一环仍依赖 fixture、旧参考接口、timer 或本地数组写入时,该动作不得标记完成。一个页面有多个主动作时逐动作记状态,不能用一个成功动作覆盖其他未完成动作。
-
-自动脚本通过不能替代实机视觉合格,单张静态截图也不能替代接口与交互合格。
-
-每个动作必须同时记录四个正交字段,禁止用一个“通过”覆盖不同含义:
-
-| 字段 | 允许值 | 判定用途 |
-| --- | --- | --- |
-| `contractState` | `LIVE_VERIFIED`、`DECLARED_UNVERIFIED`、`CONTRACT_CONFLICT`、`MISSING_OPERATION`、`NOT_APPLICABLE` | 当前后端合同及真实部署证据;纯本地权威内容用 `NOT_APPLICABLE` |
-| `dataMode` | `LIVE`、`LOCAL_PREVIEW`、`CLOSED` | 页面当前从哪里取得或是否允许提交数据;唯一 owner 的正式本地静态内容可为 `LIVE` |
-| `checkResult` | `PASS`、`FAIL`、`EXPECTED_BLOCKED`、`NOT_RUN`、`INFRA_ERROR` | 某一次合同、测试、构建或实机检查的结果 |
-| `productCompletion` | `COMPLETE`、`PARTIAL`、`BLOCKED`、`NOT_APPLICABLE` | 用户所需产品动作是否真正闭环 |
-
-`CLOSED` 页面的关闭文案、返回路径和无假成功检查可以得到 `checkResult=PASS`,但必需动作仍须记 `productCompletion=BLOCKED`;不能由此把页面或产品写成完成。已知合同门禁脚本只有在“非零退出+精确 `... BLOCKED` 标记”同时成立时才记 `checkResult=EXPECTED_BLOCKED`,它与关闭页行为检查的 `PASS` 不是同一结果。`LOCAL_PREVIEW` 最多为 `PARTIAL`。只有已批准动作在 LIVE 模式完成权限、请求、结果确认、刷新和重进闭环时,动作才可为 `COMPLETE`。
-
-汇总规则固定为:
-
-1. 动作逐项保留四字段,不取平均值。
-2. 页面另报 `structuralCheck` 和 `productCompletion`;任一必需动作 `productCompletion=BLOCKED`,页面产品完成度即 `BLOCKED`;没有 BLOCKED 但存在 `productCompletion=PARTIAL`,或必需检查 `checkResult=NOT_RUN`,页面最多为 `PARTIAL`。
-3. 域与整个项目只按已批准必需动作向上汇总;出现 `BLOCKED` 即不得宣称完成,全部为 `COMPLETE/NOT_APPLICABLE` 才能标记域或产品 `COMPLETE`。
-4. 每个 `checkResult` 同时记录首次结果;允许重试时另记重试结果,不覆盖首次失败。
-
-## 五、接口判定和实现规则
-
-### 5.1 Apifox 桌面端优先的合同发现门禁(本轮新增硬约束)
-
-导出的 `APP.openapi.yaml`、`APP.openapi.json` 和线上 `/v3/api-docs` 均可能缺少 Apifox 工作区中已经维护、但未导出的接口;它们只能作索引和交叉核验,绝不能作为“接口不存在”或“接口完整”的结论。每个受影响动作在写代码、关闭入口、补测试或判定 `MISSING_OPERATION` 前,必须先在用户已打开的 **Apifox 桌面端**逐项只读核对:
-
-1. 所属目录、接口名称、HTTP 方法和完整路径;
-2. 鉴权方式、必填请求头、路径/查询/请求体字段及类型;
-3. 成功与失败响应示例、业务码、分页/ID wire 和权限语义;
-4. 是否存在同一业务动作的补充接口、前置接口或结果查询接口;
-5. 与导出文档、当前 `utils/api.js`、参考项目或真实请求不一致之处。
-
-核对结果须以“动作 → Apifox 证据 → 当前部署实测 → 结论”写入临时脱敏账本;不得记录 Token、手机号、验证码、TAC proof、邀请口令或原始敏感响应。Apifox 与导出文档不一致时,以 Apifox 的业务定义为先导,并用真实部署响应复核 wire/权限/失败语义;两者仍不能证实时标为 `CONTRACT_CONFLICT` 或 `DECLARED_UNVERIFIED`,不得凭导出缺项关闭功能。只有 Apifox 也不存在、且经目录/关键词/相邻业务链检索留证后,才可标记 `MISSING_OPERATION`。
-
-#### 5.1.1 本轮 Apifox 只读核对记录(2026-07-23 晚)
-
-下表只记录已在用户打开的 Apifox 桌面端逐页读取到的声明;尚未通过测试账号取得同一部署的脱敏真实响应,故均不得写成 `LIVE_VERIFIED`。
-
-| 动作/对象 | Apifox 桌面端声明 | 当前结论 |
-| --- | --- | --- |
-| 世系树读取 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/tree`,`genealogyId` 为必填 `int64` 路径参数,APP `clientId` header 必填 | 路径与当前读取 owner 一致;ID wire 和权限投影仍待实测,`DECLARED_UNVERIFIED` |
-| 人物详情 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}`,两个路径 ID 均为必填 `int64`,响应为 `LineagePersonResult` | 路径与当前读取 owner 一致;`DECLARED_UNVERIFIED` |
-| 人物新增/编辑 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons` 与 `PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` 均使用统一人物 body;`name` 必填,`sex` 仅说明“建议使用系统字典值”,`avatarOssId` 只能来自统一上传,`sortOrder` 仅说明“数值越小越靠前”。已以“字典”“性别”检索 APP/PC 目录,均未发现可供 APP 消费的枚举 operation | 首人/编辑可继续按 body 收紧;性别字典、上传闭环和单人排序的并发语义未证实,不能虚构枚举或把 `sortOrder` 当原子排行 |
-| 新增父母/子女/兄弟姐妹/配偶 | 已分别声明 `POST .../parents`、`POST .../children`、`POST .../siblings`、`POST .../spouses`,均返回 `LineagePersonResult` | 原来按导出文档作出的“无 operation”结论无效;关系方向、性别字典、冲突、权限、结果未知恢复尚待实测,先列为 `DECLARED_UNVERIFIED`,不得以本地成功替代 |
-| 统一文件上传与人物头像 | `POST /genealogy/app/files/upload`,APP `clientId` header 必填,`multipart/form-data` 仅有必填 `file`;返回 `ossId`、`url`、`thumbUrl`、`fileName`、`originalName`。树与人物详情只声明 `avatarOssId`,未声明可重进读取的头像 URL/file projection | 上传本身为 `DECLARED_UNVERIFIED`;不得把 `avatarOssId` 拼接为 URL,也不把一次上传响应 URL 持久化成资料事实。T01 使用确定性国风默认头像;真实头像显示仍等待文件读取投影与真实重进验证 |
-| 已登录密码修改 | `PUT /genealogy/app/auth/password`,要求鉴权与 APP `clientId`,body 为 `oldPassword`、`newPassword` 两个 32 位 MD5 字段 | 与 A05 的无登录态 `PUT /genealogy/app/auth/password/reset` 不是同一 owner;M04 已按独立 owner 接线,未发生本轮真实 mutation,仍为 `DECLARED_UNVERIFIED`,人工恢复窗口验证前不得标记完成 |
-| 已登录手机号换绑 | `PUT /genealogy/app/auth/phone`,要求鉴权与 APP `clientId`,body 为 `clientId`、新 `phone`、四位 `smsCode`;通用短信发送接口声明允许 `APP_PHONE_CHANGE`,但前置 `validToken` 需先完成验证码中心 | 当前 profile 响应未声明可安全消费的手机号 DTO,且真实 TAC/短信需要人工窗口;M05 不猜字段、不静默发码或换绑,保持人工 `DECLARED_UNVERIFIED` |
-| 已登录退出 | `DELETE /genealogy/app/auth/logout`,要求鉴权与 APP `clientId`,无 body,响应 `RVoid`/`data:null` | M10 已接严格 REMOTE owner;当前未发真实退出 mutation,仍为 `DECLARED_UNVERIFIED`。本机退出与服务端撤销确认分开记录,不能把前者写成后者 |
-| 家族圈列表、正文详情与发布 | 列表:`GET /genealogy/app/genealogies/{genealogyId}/feeds`(`ListResult`);详情:`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}`(`ObjectResult`);发布:同一路径 `POST`(`ObjectResult`)。三者均需鉴权与 APP `clientId`,路径 ID 均为 `int64`。发布 body 仅明确 `feedContent` 非空必填;`feedType` 默认 `text`、`mediaOssIds` 为英文逗号分隔 OSS ID、`sortOrder` 默认 `0`、`status` 默认正常 | 列表只见 `property1/property2` 通用项,正文详情和发布也未声明页面可消费 DTO;F01 已删除本地列表,F03 正文不猜字段。F02 只发送 `feedContent`,且只有严格成功信封后才显示已提交;不能把泛型响应当作列表条目或已完成验收;三者均为 `DECLARED_UNVERIFIED` |
-| 家族圈一级评论 | 读取:`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments` 返回 `FamilyFeedCommentView[]`;提交:同路径 `POST`,`commentContent:string` 必填且最多 1000 字,`parentCommentId:int64|null` 可选。读取 item 已声明 `commentId/genealogyId/feedId/appUserNickName/commentContent/replyCount/createTime` 等字段 | F03 已删除本地动态/评论 fixture;读取仅展示 `commentId`、昵称、内容、回复数和创建时间的已声明映射;提交只发送 `commentContent`,成功后重新读取服务端列表 | 客户端已接线,但未取得真实登录态响应或人工可观察的提交结果;仍为 `DECLARED_UNVERIFIED`,正文详情 DTO 缺失不影响评论 owner 的独立核对 |
-| 谱文列表、详情与创建 | 列表:`GET /genealogy/app/genealogies/{genealogyId}/articles`;详情:`GET .../articles/{articleId}`,均为通用响应。创建:`POST .../articles`,已声明 `articleTitle/articleContent` 必填,`categoryId/articleSummary/coverOssId/authorName/sortOrder/status` 可选 | F04/F05 已删除本地文章、分类、搜索和正文展示,等待稳定 item/详情 DTO;F06 只发送 `articleTitle/articleContent`,无分类 ID 来源时不发送分类。编辑需要可靠详情/文章 ID 来源而关闭 | 创建客户端已接线但未实测,列表/详情/编辑仍为 `DECLARED_UNVERIFIED`;不得用本地预览或泛型成功响应冒充谱文展示闭环 |
-| 帮助文章列表 | `GET /genealogy/app/help-articles`,Apifox 显示鉴权、`clientId`(带默认值)与通用 `ListResult`,`data` 为未声明字段的 object 数组;另有详情 endpoint,但尚未作为当前页面 owner 读取 | M06 需要稳定的分类、标题与纯文本正文;当前声明仍只有 `property1/property2`,不能把硬编码 FAQ 冒充远端帮助内容。继续保持本地说明与 M07 反馈入口,远端帮助读取为 `DECLARED_UNVERIFIED` |
-| 消息通知列表与已读 | 列表:`GET /genealogy/app/notifications`,鉴权与 APP `clientId` 必填,通用 `ListResult` object 数组;单条已读:`POST /genealogy/app/notifications/{notificationId}/read`,`notificationId:int64`、鉴权与 APP `clientId` 必填、无 body、`VoidResult/data:null`。目录还声明“全部标记已读” | 未发现通知详情读取 operation,列表没有类型、目标、正文或稳定 ID 的消费 DTO;N01/N02 不能由通用数组猜业务跳转,未读不能由分页长度推断。没有登录态和可控通知种子时不发送任何已读 mutation,读取/已读均为 `DECLARED_UNVERIFIED` |
-| 我的家谱列表 | `GET /genealogy/app/genealogies/mine`,鉴权与 APP `clientId` 必填,通用 `ListResult` object 数组 | G01 需要稳定的家谱 ID、名称、角色与上下文能力;Apifox 当前仍只给出 `property1/property2`。不把响应存在误记为工作区/切谱闭环,保持 `DECLARED_UNVERIFIED` |
-| 相册与图片 | 相册列表:`GET /genealogy/app/genealogies/{genealogyId}/albums`,`genealogyId:int64`、鉴权与 APP `clientId` 必填,通用 `ListResult`。创建 body 仅可安全使用 `albumName`;图片写入要求既有 `ossId` | F07 已删除相册 fixture,创建仅发送 `albumName` 并等待成功信封;F08 已关闭无 DTO 的照片展示;F09 已删除 mock 图片和预览,等待文件上传 owner、真实 OSS 回执和访问 URL 投影。创建待真实响应核验,其他展示/上传为 `DECLARED_UNVERIFIED` / `BLOCKED_BY_MEDIA_OWNER` |
-| 备忘录 | 列表:`GET /genealogy/app/genealogies/{genealogyId}/memos`,`genealogyId:int64`、鉴权与 APP `clientId` 必填,响应为通用 `ListResult`。新增:同路径 `POST`,body 明确 `memoTitle` 必填;`memoContent`、`remindTime`、`completed`、`mediaOssIds`、`sortOrder`、`status` 可选,其中 `mediaOssIds` 为逗号分隔 OSS ID。目录另有详情、修改、删除动作 | R10 已删除列表 fixture,创建只发送 `memoTitle/memoContent/remindTime`;完成状态、媒体、排序、状态无来源不发送,详情/修改/删除因无 DTO/ID 来源关闭。创建待真实响应核验,整体仍为 `DECLARED_UNVERIFIED` |
-| 成长记录 | 列表:`GET /genealogy/app/genealogies/{genealogyId}/growth-records`,`genealogyId:int64`、鉴权与 APP `clientId` 必填,响应为通用 `ListResult`。新增:同路径 `POST`,body 明确 `recordTitle` 必填;`lineagePersonId:int64`、`recordType`、`recordContent`、`recordDate`、`remindTime`、`mediaOssIds`、`sortOrder`、`status` 可选,其中 `mediaOssIds` 为逗号分隔 OSS ID。目录另有详情、修改、删除动作 | R08 已删除列表 fixture,创建只发送 `recordTitle/recordContent/recordDate`;人物绑定、类型、提醒、媒体、排序、状态无来源不发送,详情/修改/删除因无 DTO/ID 来源关闭。创建待真实响应核验,保持 `DECLARED_UNVERIFIED` |
-| 功德记录 | 列表:`GET /genealogy/app/genealogies/{genealogyId}/merit-records`,`genealogyId:int64`、鉴权与 APP `clientId` 必填,响应为通用 `ListResult`。新增:同路径 `POST`,body 的 `donorName`、`meritTitle` 必填;`meritType`、`meritContent`、`amount:double`、`meritTime`、`sortOrder`、`status` 可选。目录仅见删除,未见详情或修改 | R 功德列表及新增响应尚无稳定页面消费 DTO;不可把当前路径与参考项目的人情/贺礼混为一谈。未在无登录态下发送新增或删除 mutation,保持 `DECLARED_UNVERIFIED` |
-| 祭祀与祭祀献礼 | 祭祀列表:`GET /genealogy/app/genealogies/{genealogyId}/ceremonies`,通用 `ListResult`;创建:同路径 `POST`,`ceremonyType`、`ceremonyTitle` 必填,`ceremonyDesc`、`ceremonyTime`、`location`、`coverOssId:int64`、`sortOrder`、`status` 可选。献礼列表:`GET /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/gifts`,两个路径 ID 均为 `int64`;新增:同路径 `POST`,`giftAmount:double` 必填,`giverName`、`giftMessage` 可选。上述均要求鉴权与 APP `clientId`,目录还声明祭祀详情/修改、删除活动和删除单条祭品 | 祭祀和献礼均有专属父对象与语义;它们不是人情簿,也不是可发放/绑定的贺礼邀请。列表/新增响应仍无稳定页面 DTO,且未在无登录态下发送写入或删除请求,整体保持 `DECLARED_UNVERIFIED` |
-| 亲友记录 | 列表:`GET /genealogy/app/genealogies/{genealogyId}/relative-records`,`genealogyId:int64`、鉴权与 APP `clientId` 必填,响应为通用 `ListResult`。新增:同路径 `POST`,`relativeName` 必填;`relationName`、`eventName`、`eventTime`、`giftAmount:double`、`recordContent`、`mediaOssIds`、`sortOrder`、`status` 可选。目录另有详情、修改、删除动作 | R03/R04 已删除 fixture 列表和详情,创建只提交亲友姓名、关系、事项、时间、金额、备注;媒体/排序/状态无来源不发送。详情/修改/删除无 DTO/ID 来源关闭;创建待真实响应核验,保持 `DECLARED_UNVERIFIED` |
-| 人生事件与重要证件 | 已在 Apifox APP/PC 目录分别以“人生”“证件”检索,均未返回对应 operation;相邻的亲友、成长、备忘、功德、祭祀目录不能替代 | R09 没有当前业务 owner,维持硬关闭和可返回状态;`MISSING_OPERATION`,不以本地表单、文件上传或参考项目页面伪造保存 |
-| 视频 | Apifox 按“视频”检索只发现 APP 删除视频动作;未发现当前 F10 所需的视频列表、可播放 URL、发布/编辑、评论、点赞或分享闭环 | F10 继续保持非 LIVE;不能把参考短视频动作或单一删除 endpoint 扩展成视频产品能力,`MISSING_OPERATION` |
-| 意见反馈 | `POST /genealogy/app/feedback`,鉴权与 APP `clientId` 必填;body 的 `feedbackContent` 必填,`feedbackType` 与 `contactInfo` 可选,响应 `ObjectResult` | 与 M07 的严格 normalizer、POST owner 和提交状态机一致;静态/API 冒烟已通过,未用测试账号提交真实反馈,故远端结果仍为 `DECLARED_UNVERIFIED` |
-| 当前用户资料 | `GET /genealogy/app/auth/profile`,鉴权与 APP `clientId` 必填,响应 `ObjectResult`,当前仅给出 `property1/property2`;目录另有 `PUT /genealogy/app/auth/profile` | M01—M03/M05 需要稳定的账号、资料与手机号投影;不能从通用对象猜字段或让资料更新覆盖未知字段。读取、编辑与换绑前置均保持 `DECLARED_UNVERIFIED`,M05 另受人工 TAC/短信窗口约束 |
-| 微信登录 | 已以“微信”检索 Apifox APP/PC 目录,未返回登录授权、code 交换、回调、会话创建或结果查询 operation | A01 的微信入口不能借参考项目旧接口接通;保持 `MISSING_OPERATION` 关闭候选,是否长期纳入由用户后续确认 |
-| 家谱邀请码 | 已以“邀请码”检索 Apifox APP/PC 目录,未返回邀请码签发、校验、直入加入、撤销或结果查询 operation | G/M 的邀请码能力无当前 owner;普通加入申请、成员维护和人物邀请绑定都不能替代,保持 `MISSING_OPERATION` |
-| 行政区划搜索 | Apifox APP 目录声明 `GET /genealogy/region/search`:`keyword` 必填,`level` 可选(1 省、2 市、3 区县、4 街道、5 村社区),`limit` 可选;`clientId` header 可选,响应为通用 `ListResult`。2026-07-24 00:51 的只读部署响应为 HTTP/业务码 `200`,服务器时间 `Thu, 23 Jul 2026 16:51:08 GMT`,单条结果含字符串 `regionCode`、`label`、`parentCode`、`ancestors`、`regionName`、`regionLevel`、`regionType` 与 `leaf`;同目录另有下级查询、路径查询与详情 | 此读取 owner 为 `LIVE_VERIFIED`,G03 可消费返回的字符串 `regionCode`,但不能把 `leaf` 推断为可提交能力。非 APP 前缀为唯一业务 owner;当前部署旧 `/genealogy/app/region/search` 虽同响应,仍只记路径并存证据,不作兼容 owner。G03 两次写入及结果未知恢复仍分别按其独立合同判定,不能由该读取验证代替 |
-| 邀请绑定 | 已展开“家谱(12)”“家谱成员(6)”全部接口,并以“邀请”“绑定”检索 APP/PC 目录;仅见普通申请/审核和成员维护,无邀请票据、身份绑定、绑定 mutation 或结果查询接口 | `MISSING_OPERATION`;普通申请不能替代邀请绑定,保持诚实关闭 |
-
-### 5.2 通用判定和实现规则
-
-1. Apifox 用于优先发现和判断接口业务用途;线上 `/v3/api-docs` 和真实请求用于确认当前部署路径、字段及故障表现;受保护 OpenAPI 只作离线补充。参考项目 `api/index.js` 中的旧路径、参数和响应处理不属于当前接口证据。
-2. 每个动作先进入统一账本。`LIVE_VERIFIED` 只允许用于本轮开始后、绑定后端可识别版本或时间戳的真实证据;受保护 OpenAPI 有声明但未取本轮真实响应时为 `DECLARED_UNVERIFIED`;文档、部署、权限、静态门禁或页面期望冲突时为 `CONTRACT_CONFLICT`;没有可靠 operation 时为 `MISSING_OPERATION`。operation 是否存在另记为证据字段,不是第五种状态;同一最小动作同时“有声明但已知冲突”时必须取更严重的 `CONTRACT_CONFLICT`,不得写两个 `contractState`。不得把接口名相似、历史 HTTP 200 或参考项目成功写成已接通。
-3. 先列出当前批次的“当前页面 → 用户动作 → 对象身份 → 权限来源 → 方法 → 完整路径 → 输入 → 页面消费字段 → 成功/失败/结果未知表现 → 刷新确认”,再写该批次失败测试,随后实现。
-4. 只有 `LIVE_VERIFIED` 动作允许记为 LIVE。`DECLARED_UNVERIFIED` 先做只读或可控测试验证;`CONTRACT_CONFLICT` 记录冲突并失败关闭;`MISSING_OPERATION` 保留完整视觉和返回路径,动作显示服务未开放,不伪造保存、发送、上传、支付、邀请、绑定、排行或审核成功。
-5. 4xx、5xx、空体、缺字段或身份错配必须展示真实失败,不回退 mock。参考项目成功、受保护 OpenAPI 存在 operation 或当前页面已有 `appApi` 方法,都不能单独解除这一规则。
-6. 单个接口排查超过 15 分钟仍无本机解决路径时,立即记录复现证据并继续其他页面,避免阻塞整夜。
-7. 每个合同只有一个 owner;新合同落地时同步移除同类 fixture、旧入口、兼容读取和过时测试期望。若一个参考动作无法明确归入现有 owner,先判定是否需要新 owner,不能塞进名称相近的旧接口。
-8. 真实写操作仅限测试账号和本轮新建、带“联调测试”标识且已登记 ID 的对象。GET 可按退避规则重试;写操作只有接口明确提供幂等键且结果可判定时才允许重试,超时、5xx、断线或进程终止造成结果未知时立即停止该动作并查只读结果。
-9. 新增全域 P0 ID 门禁:`genealogyId`、`personId`、`memberId`、`appUserId`、父母/配偶/子女引用、内容 ID、文件 ID 与 `avatarOssId` 等 `int64` wire 必须验证服务端以十进制字符串返回且请求端接受十进制字符串。任何超出 JavaScript 安全整数的 JSON number 一经解析已不可恢复,禁止再转字符串继续使用;相关读写统一记 `CONTRACT_CONFLICT` 并关闭,直到同一 ID owner 在 schema、运行时、validator 和请求端同时收紧。
-10. 三个现有静态门禁本身与已确认规划/快照冲突,收到“开始执行”后的第一项测试工作是先按唯一 owner 重订失败期望,再实施业务:`auth-tac-openapi-contract.ps1` 不得再要求密码登录上传 `validToken`;两个 G03 门禁不得再要求未声明的原子 bootstrap、错误的 `/genealogy/app/region/search` 或不存在的结果查询;`help-center-openapi-contract.ps1` 与 M06 统一为“完整列表是唯一远端 owner、文章阅读由列表项投影承接”,不新增独立远端详情 owner。门禁目标路径不能写成当前 operation,也不能因旧测试期望而覆盖真实后端合同。
-
-每条路由的执行记录至少包含:`route`、真实入口、必填参数、测试角色/种子、四个正交状态字段、参考来源、候选动作、六类甄别结论、接口 owner、权限 owner、主动作、返回结果、页面状态证据、LIVE 请求响应证据、候选包 ID、MuMu 结果和 blocker。
-
-每次汇总必须同时列出这些分母,任何一个都不能被“52/52”代替:
-
-- `baselineRoutes=52`;
-- `approvedNewRoutes`(规划确认采纳、但不一定已注册);
-- `registeredRoutes`(候选包实际注册);
-- `traversedRoutes`(绑定该候选包完成结构遍历);
-- `referenceEvidenceRecords=341`,以及六类证据结论数量:直接采用、改造后采用、仅参考交互、后端缺失暂关、冲突舍弃、待用户确认;
-- `productActionsTotal=166`、`requiredActions=111`、`candidateActions=55`、`approvedCandidateActions=0`;产品完成分母固定为附件 PA-001—PA-166 中的 111 个必需动作;
-- `liveCompletedActions`、各动作的 `productCompletion`,以及按必需/可选、A/G/T/F/R/N/M/共享 owner 的分组结果;
-- `inventoryTests`、`scheduledTests`、`executedTests`、`notRunTests`、`timedOutTests` 与各 `checkResult` 数量。
-
-## 六、执行批次与相对时间
-
-以下计时只在用户明确说“开始执行”后启动。在此之前,参考映射与产品取舍必须已在权威附件中完成并由用户确认;执行第 0 批只能重算清单/哈希、冻结确认结果,不得再临场作重大产品决策。
-
-### 6.1 时间模型与降级规则
-
-- `T_start`:收到用户“开始执行”的北京时间。
-- `T_due`:用户已更新为 2026-07-24 08:00(北京时间)。
-- 正常候选周期为 `T_start + 9h`,但不得越过 `T_due`;要获得完整九小时窗口,最迟须在 2026-07-24 01:00 开始。
-- `T_test_cutoff = min(T_start + 6h, T_due - 3h)`。截止前必须完成本轮测试调度和首个候选尝试;截止后反向保留 0.5 小时候选修复/冻结、1.75 小时最终实机和 0.75 小时缓冲,不能用缩短窗口挤占这三段。
-- 首个候选固定预留 `firstCandidateWorstCase=30m`:2 分钟重算输入清单并准备全新输出根、15 分钟构建、3 分钟生成输出清单/指纹、7 分钟部署或安装、3 分钟设备身份确认。测试只有在 `now + testWorstCase + firstCandidateWorstCase <= T_test_cutoff` 时才允许启动;全部已调度测试收口后,首个候选只有在 `now + firstCandidateWorstCase <= T_test_cutoff` 时才允许启动。任何在途进程都不得跨越 `T_test_cutoff`:意外超时时在截止点终止本轮进程树,具体测试记 `timedOutTests/INFRA_ERROR`,候选尝试记基础设施失败,然后一次性冻结计数。不得以“已经开始”为由占用后续三小时。
-- `T_start >= T_due` 时不启动本轮执行,先请用户重新确认截止时间;`T_test_cutoff <= T_start` 时不启动代码、测试或构建批次,只交付预检与“无冻结候选”的精确原因。
-- 有效窗口不足 9 小时时不压缩人工认证和上述尾部三段:6—9 小时优先削减 F/R/N/M 的新增 LIVE 扩展;3—6 小时只在 `T_test_cutoff` 前做 P0 合同/安全修复、七个现有 `appApi` consumer 和首个候选尝试;不足 3 小时时不启动无法留出验证时间的代码批次,只做可完成的预检、现状与报告。所有被削减项记 `NOT_RUN`,不得改写成通过。
-- 九小时只是一次可靠候选周期,不是整个产品的完成承诺;明早报告必须把第 2 节五个层级分别结论化。
-
-### 6.2 正常九小时批次
-
-#### 第 0—0.5 小时:冻结基线、合同、角色与夜跑清单
-
-- 以用户手动拉取的当前文件为源码基线,不执行 Git;重算 52 条路由、60 个设计文件、78 条参考活动路由、1 条注释路由声明、7 个未注册参考页面文件、531 个参考媒体资产和权威附件覆盖率。
-- 在任何“接口缺失”、接口接线、写操作或页面关闭结论之前,先按第 5.1 节在 Apifox 桌面端完成当前批次动作的目录、请求、响应、鉴权和相邻链路检索;把未导出的接口和与导出文档不一致的字段列入脱敏合同账本,再决定实测、实现或阻塞。不得跳过此步骤直接按导出 OpenAPI 结论推进。
-- 冻结线上 `/v3/api-docs` 的取证时间与可识别版本;受保护 OpenAPI 保持只读。接口或参考源相对已确认附件发生变化时,只记录差异并暂停受影响动作,不静默改变产品范围。
-- 先在仓库外的本机临时验收目录建立唯一 `role-seed-matrix.json` owner:只记录脱敏角色别名、角色类型、对象类型、十进制字符串对象 ID、来源/创建时间、允许的动作和清理责任;不得写账号、手机号、Token、OTP、TAC proof 或其他凭据。普通成员、家谱所有者或管理员、第二账号,以及测试家谱、人物、申请、内容和媒体均由该矩阵登记。缺少角色、跨账号对象或收码号码时,对应动作标记测试数据阻塞。
-- 机械生成当前 204 个可执行脚本的 manifest 基表和显式 override,并冻结 `baselineInventoryTests=204=150 PS1+54 JS`。`tests/night-run.ps1` 与 `tests/night-run.manifest.json` 是编排入口/清单,不计测试项;实施中为本轮变更新建的每个可执行测试都记入 `newExecutableTests` 并追加到 manifest,最终 `inventoryTests=baselineInventoryTests+newExecutableTests`。每项先按第 6.3 节确定风险层级、依赖、是否远端写入及预期结果;第 0 批只校验已确认的 `PA-xxx` 产品动作和来源反链未漂移,禁止重新归并、拆分或改变产品动作分母。任何参考资产复制前另建逐文件 `RAxxx` 记录;资产选择可以在已批准 PA 内发生,但不能新增产品动作或跳过来源门禁。
-- 在仓库外的本机临时验收目录准备候选输入清单模板。每次候选构建/部署前,对项目自有源码、配置、资产和 lockfile 重算规范化逐文件 SHA-256;明确排除 `.git`、`unpackage`、依赖/工具缓存、日志、截图、报告和清单自身,并另记 HBuilderX、插件及解析后依赖版本。输入清单的规范化与第 6—6.5 小时输出清单使用同一算法,且不含凭据。
-- 检查 remote 配置、网络、磁盘、HBuilderX、MuMu 状态和测试账号,但此时不把任何历史运行结果算入本轮。
-
-#### 第 0.5—1.75 小时:A 认证人工窗口与会话
-
-- 本轮先完成密码登录页、账号密码提交、TAC challenge 展示、challenge/verify 合同、会话保存与 G01 跳转的可自动化验证;密码登录的真实拖动、短信登录、注册和找回密码的短信/TAC 全部保留为早晨人工回归,四条流程不互相替代。
-- 不循环发码、不破解或绕过 TAC。测试账号凭据只保留在当前安全会话,绝不写入仓库、文档、截图或日志。
-- 人工完成后验证页面重进和应用重启的会话;不记录 token。会话失效时停止身份写操作并熔断,不以临时接口 token 冒充认证页面验收。
-
-#### 第 1.75—4 小时:A/G/T P0 主链与 T01/T03
-
-- 按 A01 → G01 → G05 → T01、G03 两阶段建谱、G06/G08—G12、T03—T08推进;每个动作先过合同、ID、权限和结果未知门禁。
-- T01 优先完成头像人物卡、选择态和唯一人物面板;十入口逐项落到 T03/T04/T05/T06/邀请流程。合同不足的入口只允许诚实关闭,其关闭检查可 PASS,但 T01 产品完成度仍为 BLOCKED。
-- T03 始终从未完成半成品起算;已有 normalizer、fixture 或旧门禁不得计完成。
-- 本批时间用尽即停止扩张并留下可验证断点,不把 T01 大型布局和十条真实写链压缩成单一“完成”。
-
-#### 第 4—4.5 小时:F/R/N/M 风险优先扩展
-
-- 优先处理已经有当前后端声明、且能在剩余时间内完成闭环的读取和小型写入;无视频完整链、人生事件、重要证件、通知详情、支付/提现等保持诚实关闭。
-- 换绑、注销、支付、所有者转移、退出家谱、删除真实内容等敏感动作不在无人值守阶段执行。
-- 每域更新动作分母与四字段,不要求为了“全绿”把全部参考候选临时实现。
-
-#### 第 4.5—6 小时:分层测试、首个候选与全量硬截止
-
-- 唯一测试清单 owner 为执行时建立的 `tests/night-run.manifest.json`,唯一入口为 `tests/night-run.ps1`;二者只在用户说“开始执行”后创建。manifest 逐项明确脚本、解释器、排序、120 秒默认超时、依赖、预期退出码、预期标记、领域、是否允许写远端及检查点;当前 12 个 allowlist 项必须各自冻结完整且唯一的 `expectedBlockedMarker`,不得用包含匹配;4 个 JSON 数据文件不是可执行脚本。
-- 测试分三层:`T0` 为 P0 安全/合同、路由、编译及本轮实际修改 owner 的门禁,是形成候选的必要条件;`T1` 为 A/G/T/F/R/N/M 受影响域的其余 mapper/runtime/合同回归;`T2` 为未受影响域和历史扩展检查。204 个基线项与所有 `newExecutableTests` 全部进入 inventory,但只有 manifest 明确列入当轮的项目计入 `scheduledTests`;先执行 T0,再在硬截止前执行 T1,T2 仅在 T0/T1 完成且仍有时间时调度。未调度或未执行项分别如实进入 `notRunTests`,不得把 inventory 数量写成执行数量。
-- 一级顺序固定为 T0 → T1 → T2;每层内部再按纯静态/合同 PowerShell → 纯 Node mapper/runtime → 该层编译/专项检查排序,全部已调度测试收口后才形成候选构建。PowerShell 使用 `powershell.exe -NoProfile -ExecutionPolicy Bypass -File `;Node 使用 `node `。无网络、无共享写入且无相互依赖的本地脚本最多 4 个并发 worker;远端、写操作、编译和构建一律串行。单项失败继续下一项并回收子进程,域熔断只跳过同一远端风险动作。
-- 当前 150 个 PowerShell、54 个 Node 脚本以及实施中新增的每个可执行测试必须逐一进入 manifest;runner 和 manifest 自身不计测试项。本轮“预期阻塞”只允许以下 12 条精确脚本,并同时要求非零退出和各自精确 `... BLOCKED` 标记;其他非零均为 `FAIL`:`auth-android-accessibility-release-gate.ps1`、`g11-settings-openapi-contract.ps1`、`g12-generation-poem-openapi-contract.ps1`、`genealogy-workspace-openapi-contract.ps1`、`invite-ticket-openapi-contract.ps1`、`join-application-openapi-contract.ps1`、`lineage-openapi-contract.ps1`、`notification-read-openapi-contract.ps1`、`notification-read-state-openapi-contract.ps1`、`phone-change-openapi-contract.ps1`、`profile-openapi-contract.ps1`、`profile-update-openapi-contract.ps1`。已转绿的 `auth-tac`、两个 G03、F 家族圈、M04、M06、M10 与 T03 门禁不得再被列作预期阻塞;M04/M10 的真实 mutation 仍只进入人工窗口。清单冻结前须核对这些脚本的实际退出语义,不能仅因文件含 “BLOCKED” 字样放行。
-- allowlist 脚本若本轮变为退出码 `0` 且出现精确 PASS 标记,按 `PASS` 接受并从预期阻塞清单移除;只有非零退出且精确 BLOCKED 标记匹配才是 `EXPECTED_BLOCKED`。退出码与标记任一不匹配均为 `FAIL` 或 runner 错误,不能因历史预期而放行。
-- 夜跑在每项结束后原子写入本机临时验收目录中的 checkpoint(脚本、开始/结束、退出码、标记、耗时、首次结果),续跑只从最后完整记录之后开始。总入口退出码固定为:`0`=无 FAIL/INFRA 且预期阻塞完全匹配;`2`=测试或合同断言失败;`3`=构建、部署、安装或设备基础设施失败;`4`=manifest 漂移、单项超时、测试执行基础设施或 runner 自身错误;同时出现时按 `4 > 3 > 2 > 0` 聚合。单项超时记该测试 `checkResult=INFRA_ERROR` 并进入 `timedOutTests`;无法归到具体测试的 manifest/runner 故障另记 `runnerInfraErrors`,不塞入测试恒等式。任何 `EXPECTED_BLOCKED` 都必须在摘要中单列,退出 0 不等于产品全绿。
-- 全部已调度测试按层级收口后,首个候选严格使用第 6.1 节 30 分钟预算与同一构建入口;任一子段超时即本次候选失败,不把失败段的剩余时间转给另一段,也不在 cutoff 前启动第二次首候选尝试。第 6—6.5 小时只负责复用该候选或进行一次受限修复/最终冻结。
-- `T_test_cutoff` 是测试调度与首个候选尝试的硬截止;每项按第 6.1 节 `latestStart` 准入,不能在最坏耗时将越过 cutoff 时启动。截止时终止意外仍在途的项目,排队但未启动的已调度项进入 `notRunScheduledTests`,再一次性冻结 `scheduledTests/executedTests/notRunScheduledTests/notRunTests/timedOutTests` 和最终恒等式。T0 未全部取得允许结果或候选无法追溯时,不进入最终实机验收。
-- 构建入口固定为仓库根目录与 `.hbuilderx/launch.json` 中的 `uni-app:app-android`。执行前记录实际 HBuilderX CLI 绝对路径、版本、命令、退出码和输出目录;不得把旧 `unpackage` 产物冒充新包。
-
-#### 第 6—6.5 小时:仅修复候选阻塞并冻结最终候选
-
-- 本阶段只能二选一,不得借用后续 105 分钟实机窗口。若首个候选之后源码输入和生成输出均未变化,前 20 分钟内重算输入/输出 manifest 并逐项确认 hash 完全相同,必须复用该候选且不重复构建;随后最多使用 7 分钟部署/安装、3 分钟设备身份确认。若必须修复,前 5 分钟的组合硬上限同时覆盖一次 P0/P1 外科式修复、受影响的聚焦测试和 `sourceManifestSha256` 重算;随后 15 分钟的组合硬上限同时覆盖最终构建、完整输出 manifest 与 `outputManifestSha256`,再用 7 分钟 DBG 部署或 APK 安装、3 分钟设备身份确认,合计正好 30 分钟。任一组合段内的前置工作耗尽预算,后续工作来不及完成时即判该路径失败,不能把清单/指纹移出预算。
-- 任一路径在准入时无法按最坏预算于本阶段结束前收口,或任一硬上限内未完成,立即终止本轮启动的进程树、停止继续安装并记退出码 `3/INFRA_ERROR`,交付“无冻结候选”;不得重试、不得压缩身份核验,也不得挤占 MuMu 窗口。
-- 候选分两类且必须二选一取得可追溯、可复验的指纹:APK 使用 `APK-YYYYMMDD-HHMM-`,记录完整 APK SHA-256;HBuilderX 调试部署使用 `DBG-YYYYMMDD-HHMM-`。两类都绑定 `sourceManifestSha256`、测试 manifest 结果、开始/结束时间、输出目录、应用包名/版本、HBuilderX/插件/依赖版本、部署或安装回执,以及 MuMu 已安装包的包名、版本、签名摘要和安装时间。
-- 源码输入与 DBG 输出清单的规范化算法固定为:以各自声明的根目录生成相对路径,路径分隔符统一为 `/`,按相对路径 ordinal 升序,每行写 `sha256bytesrelativePath`,整体使用 UTF-8 无 BOM 与 LF。源码侧沿用第 0 批明确列出的排除集合。DBG 输出根固定为本轮 HBuilderX 新生成的准确输出目录,输出 manifest 存放在根目录之外并递归纳入全部生成文件;输出侧只允许排除存在时的 `Thumbs.db`、`.DS_Store`,且必须逐项记录,除此之外不得排除。`outputManifestSha256` 是完整规范化输出清单的 SHA-256,`sourceManifestSha256` 同理。
-- 找不到可重复构建/部署入口、无法取得上述任一指纹或安装结果与指纹不一致时记 `INFRA_ERROR`,明确报告“无冻结候选”,不得进入 MuMu 最终验收。任何代码或生成输出变化都会使旧设备证据失效,必须取得新候选 ID 并重验。
-
-#### 第 6.5—8.25 小时:冻结候选的最终实机验收
-
-- 本阶段 105 分钟固定拆为:前 10 分钟核对已安装身份、冷启动、证据目录和一次故障恢复余量;随后 65 分钟完成“52 条基线路由+已批准且已注册新增路由”的合计结构遍历,基线路由优先;最后 30 分钟做 P0 实时 smoke。结构遍历开始时计算 `routeBudgetSeconds=floor(3900/registeredRoutes)`(只有 52 条基线路由时为 75 秒),按基线路由优先的冻结顺序给每条路由一次预算;已启动路由超预算记 `FAIL` 并继续,65 分钟到点仍未启动的路由记 `NOT_RUN`。任何新增路由、低优先路由或故障恢复都不得侵占 P0 时段。
-- 结构遍历报告基线、已批准新增、实际注册、实际遍历和 `NOT_RUN` 五个分母/结果。P0 smoke 在同一候选上覆盖认证根页 A01、四个主入口 G01/F01/N01/M01、A/G/T P0 主链以及本轮改变的 F/R/N/M 动作;检查上下文、返回、空/错/无权限、重复点击、取消、前后台与迟到响应。更深的状态矩阵在各实现批次持续取证,最终候选至少重复 P0 smoke,旧候选证据不得沿用。
-- 本地故障注入只能证明客户端分支,不能证明远端实时接口;真实服务不做攻击性 4xx/5xx/429 压测。所有设备证据绑定候选 ID、分辨率、density、角色和种子。
-
-#### 第 8.25—9 小时:45 分钟保留缓冲与交付收口
-
-- 本时段是保留缓冲,不安排新功能。前面持续写入的报告在此校验四字段、首次结果、分母、熔断、人工项和继续步骤。
-- 若前序超时,缓冲只用于恢复、必要重建和最短复验;未完成项分别记清 `checkResult=NOT_RUN`、`productCompletion=PARTIAL` 或 `productCompletion=BLOCKED`,不得混写成一个状态。若缓冲未使用,可增加探索检查,但不得改变冻结候选或既定结论。
-
-### 6.3 测试风险层级与计数规则
-
-测试层级在第 0 批依据文件名、manifest 元数据和本轮人工变更账本机械生成,不依赖 Git diff,也不能由执行者为了赶时间临时降级:
-
-| 层级 | 确定性纳入规则 | 候选门禁 |
-| --- | --- | --- |
-| `T0` | `compile-audit.ps1`、路由/导航/会话/运行配置/共享 ID 与权限门禁、第 6.2 节预期阻塞 allowlist,以及本轮每个被修改 owner 对应的合同、runtime 和视觉专项 | 全部必须取得 `PASS` 或精确允许的 `EXPECTED_BLOCKED`;否则无冻结候选 |
-| `T1` | 与本轮被修改 owner 同域的其余 A/G/T/F/R/N/M mapper/runtime、文档流、状态和响应式回归 | 在 `T_test_cutoff` 前尽量全部执行;未执行项记 `NOT_RUN` 并降低相应域结论 |
-| `T2` | 未受影响域、历史扩展、仓库卫生与探索性检查 | 仅在 T0/T1 完成且时间有余时调度;不以 T2 未跑伪装全量测试通过 |
-
-计数恒等式固定为:
-
-- `baselineInventoryTests=204=150 PS1+54 JS`,4 个 JSON 仅作为数据文件,runner/manifest 仅作编排,均不计可执行测试;
-- `inventoryTests=baselineInventoryTests+newExecutableTests`,本轮未新增测试脚本时 `newExecutableTests=0`;
-- `scheduledTests=executedTests+notRunScheduledTests`;
-- `executedTests=passTests+failTests+expectedBlockedTests+infraErrorTests`,其中 `timedOutTests` 是 `infraErrorTests` 的诊断子集,不重复相加;
-- `notRunTests=(inventoryTests-scheduledTests)+notRunScheduledTests`。
-
-`runnerInfraErrors`、构建/部署/安装/设备基础设施错误另列,不进入上述测试项恒等式;只要存在任一此类错误,候选和报告仍按对应退出码失败。报告必须同时给出各层级数量、首次结果和重试结果。默认 120 秒只是单项上限,不是预计耗时;四 worker 也不能用理论并发量承诺完整 inventory 必然在 1.5 小时内跑完。冻结候选只宣称 T0 门禁已满足和实际执行范围,不能把 inventory 数量写成“全通过”。
-
-## 七、三人交叉复核
-
-三人固定为主代理和两位只读评审者,主代理是唯一写入者。三人都必须完整检查本规划,不能把范围割裂后只看自己的一部分;为增强对抗性,主代理重点复核产品全量覆盖与参考甄别,评审一重点攻击后端合同、权限和数据闭环,评审二重点攻击执行顺序、时间预算、测试证据和回归风险,然后互相核对对方领域。
-
-规划评审必须在交给用户确认前完成,至少检查:
-
-1. 是否覆盖 A/G/T/F/R/N/M、共享基础和参考候选,而非只覆盖认证或 T01。
-2. 每个采纳动作是否有唯一页面 owner、唯一接口 owner、权限来源、状态矩阵和完成定义。
-3. T03 是否始终标为未完成,T01 十个入口是否逐项落到真实流程或诚实关闭态。
-4. 两个参考源是否逐页面、逐动作、逐接口留有结论,是否误带旧地址、旧字段、旧组件、凭据、日志或视觉。
-5. 52 条基线路由与新增采纳路由是否分母清楚,时间预算是否把阻塞、人工项和最小可靠交付说清。
-6. 参考资产是否逐文件绑定已批准 PA 和具体页面状态,是否误把用户的候选复用许可解释为整包批准,是否遗漏第三方、隐私、旧品牌、格式、无障碍和性能风险。
-
-任一评审提出有证据的疑点时,主代理必须修改规划或书面保留为待用户确认项;不能以多数票掩盖未解决的合同冲突。实施开始后,三人仍在批次边界复核接口、业务、交互、异常和视觉,不并发写文件,也不把开放式讨论拖入下一批。
-
-本次规划评审已于 2026-07-23 收口:
-
-| 评审角色 | 最终结论 | 已复核证据 |
-| --- | --- | --- |
-| 产品主审(主代理) | `PASS` | A/G/T/F/R/N/M 七域、共享 owner、52 条 CUR、T01 十入口、T03 半成品、两个参考源 341 条基记录、166 个 PA、状态分离和 531 项资产逐文件门禁完整;当前项目职责没有被参考项目覆盖 |
-| 合同评审 | `PASS` | 122 个合同键唯一且 PA 无未定义引用;125 个唯一当前 operation 均可回到 153-operation 只读快照;M08 家谱邀请、G03、TAC、N02、帮助、家族视频与宣传视频 owner 已拆清 |
-| 执行评审 | `PASS` | 204 项测试基线与动态 inventory、`latestStart`、首候选 30 分钟预留、最终候选双路径、输出指纹、65 分钟路由预算、退出码和双门禁均可机械执行 |
-
-最终无剩余 P0/P1;评审提出的 P2 也已处理,包括复合来源证据的稳定 `@browse/@comment/@reaction/@share` 后缀。机械结果为:PA-001—PA-166 连续唯一(111 必需、55 候选),初始 42 `PARTIAL`+69 `BLOCKED`+55 `NOT_APPLICABLE`;52 条当前路由全部反链;341 条来源基记录均有 PA 或全局去向;两份权威文档无旧计数和表格列错位。
-
-## 八、无人值守边界
-
-- 本节只有用户明确说“开始执行”后生效;此前只允许规划范围内的只读核对和规划文档写入。
-- 执行授权生效后,可以继续读取、创建带测试标识的数据、运行测试、构建和操作 MuMu。
-- 不循环请求短信,不破解验证码,不使用生产数据做破坏性试验。除用户指定的最终停止通知外不发送外部消息;本轮真正停止时仅向用户已打开的微信“文件传输助手”发送“已经停下了”。
-- 不支付、不换绑、不注销、不删除已有家谱或用户内容。
-- 后端、测试账号、发布签名或 MuMu 人工验证码成为硬阻塞时,记录:失败门禁、请求与响应、复现步骤、解除条件、恢复后的第一步。
-- 用户有新消息时优先处理。只有已经收到“开始执行”后,“准备睡了”才可作为第 0.5—1.75 小时既定认证人工窗口的提前提醒或提前触发;它不改变 `T_start`、不另起第二套时间线,也不能单独授权代码、测试、构建或 MuMu。
-- Authorization、手机号、OTP、TAC proof、邀请码和个人资料不得进入报告、截图文件名或仓库日志。原始运行日志和截图放在本机临时验收目录,限制容量并在报告中只引用脱敏摘要。
-- TalkBack、系统大字号和无法可靠自动化的原生辅助功能只做可重复的早晨人工项,自动截图不得冒充无障碍通过。
-
-## 九、明早交付物
-
-1. MuMu 中可启动和遍历、且绑定 `APK-*` 或 `DBG-*` 可追溯/可复验指纹、`sourceManifestSha256` 和设备侧安装身份的冻结测试候选;若两类指纹均无法取得,明确交付“无冻结候选”与 `INFRA_ERROR` 证据,不能用旧安装包代替。
-2. 52 条基线路由及所有已采纳新增路由的入口和结构结果,并分别报告 `baselineRoutes`、`approvedNewRoutes`、`registeredRoutes`、`traversedRoutes` 与 `NOT_RUN` 路由。
-3. 当前页面—动作—接口映射、真实请求结果,以及两个参考源逐页面/逐动作/逐接口的采纳结论。
-4. `referenceEvidenceRecords` 与六类证据数量、权威 PA 动作分母、`liveCompletedActions` 和逐动作四字段结果。
-5. `inventoryTests`、`scheduledTests`、`executedTests`、`notRunTests`、`timedOutTests`,以及构建/部署和 MuMu 实机验收结果。
-6. 本轮实际评估/采用的 `RAxxx` 参考资产清单、来源确认、改造方式、重复 canonical owner、包体影响及逐状态验收证据;未使用的 531 项不冒充已审。
-7. 后端阻塞、测试数据阻塞和需要人工复验的精确清单。
-8. 明早从登录开始的最短人工回归步骤。
-9. 运行元数据:用户确认的源码基线说明、开始结束时间、后端地址与可识别版本、MuMu 分辨率/density、账号角色、各项耗时和熔断记录;不调用 Git 取得 HEAD/dirty 信息,不包含任何凭据。
-
-## 十、规划阶段只读核对记录
-
-| 核对对象 | 当前事实 | 规划结论 |
-| --- | --- | --- |
-| 当前源码 | 用户确认已手动拉取 2026-07-23 最新 `main`;本轮未执行任何 Git 命令 | 不再沿用旧 HEAD/dirty 断点;以当前文件事实为准 |
-| 当前活动范围 | `pages.json` 有 52 条活动路由,`pages` 下有 53 个 Vue 文件 | 52 是最低基线;最终分母还要加入明确采纳的新增路由 |
-| 当前数据接线 | `runtimeConfig.mode` 为 `remote`;仅 A01、A04、A05、G01、G05、T01、M07 七页直接消费 `appApi`;40 页直接导入 `data/mock`,28 页含 `setTimeout` | 七页也须逐动作验真;其余页面逐项归类 LIVE/LOCAL_PREVIEW/CLOSED;timer 不能自动等同假成功,也不能逃过甄别 |
-| 当前 T03 | 页面已调用 `appApi.getPerson` 的 Apifox 人物详情 owner,具备严格 normalizer、取消控制与无 fixture 回退;测试目录已有静态与 mapper 门禁 | 仍未取得测试账号下的本轮真实人物响应、权限投影、跨页刷新与重进证据;明确为未完成半成品,不得记为 `LIVE_VERIFIED`、页面完成或产品完成 |
-| 受保护 OpenAPI | 本地 JSON/YAML 快照为 112 paths、153 operations,只读 | operation 存在仅记 `DECLARED_UNVERIFIED`,仍需对照线上文档和真实响应 |
-| “app设计”源 | `C:\Users\Rain\Desktop\job\app设计` 共 59 PNG+1 PDF;项目归档与 59 个旧文件哈希一致,新增 `思维导图.png` | 作为第一参考源;新图先用于规划,不在确认前复制 |
-| 已完成参考项目 | `C:\Users\Rain\Desktop\job\Jiapu-App` 有 78 条活动路由+1 条注释路由声明、79 Vue、6 NVue、7 个未注册页面文件、113 个旧 API wrapper;使用旧后端封装且没有可用测试脚本 | 作为第二参考源;78 是活动分母,注释路由和未注册文件单列候选;禁止复制其请求层、旧地址、组件和数据模型 |
-| 参考项目资产 | `Jiapu-App\static` 有 531 个媒体文件、约 6.45 MiB;声明扩展名为 307 PNG、221 GIF、2 SVG、1 JPG,文件签名实为 311 PNG、217 GIF、2 SVG、1 JPG;已发现 6 个扩展名/MIME 不一致、14 组完全重复、第三方/商标、旧品牌、固定旧文案、示例头像与短视频实验素材 | 用户允许逐文件复用候选;不整目录复制。高价值候选优先看水墨/宗祠、谱书、人物卡边框和中性功能图标;QQ 表情、短视频实验、支付/微信品牌、VIP/奖励、旧 logo 先排除直接复用 |
-| 参考映射 | 权威附件逐一登记 60 个设计文件、78 条活动路由、1 条注释路由声明和 7 个未注册页面文件 | 产品取舍必须在用户确认前完成;执行阶段只重算并冻结,不再用前 30 分钟临场决定范围 |
-| 测试与设备 | `tests` 下有 208 个文件:150 PS1、54 JS、4 JSON;当前没有统一夜跑 manifest;本轮没有运行测试、构建或 MuMu | 收到“开始执行”后才建立显式 manifest 并取得新鲜证据,旧 PASS 不冒充本轮 PASS |
-
-### 当前接口覆盖初判
-
-| 域 | 本地受保护快照中的接口证据 | 明确缺口或待验真项 |
-| --- | --- | --- |
-| A 认证 | 登录、短信登录、注册、找回、发码、资料、安全操作均有声明 | TAC 服务端消费、密码 wire、短信场景、会话撤销和真实错误语义仍需验真;微信登录无当前 APP operation |
-| G 家谱 | mine/public/create/detail/update、普通申请/撤回/审核、成员、字辈和行政区划均有声明 | G03 只有“创建家谱+另建首位人物”两次独立写;`regionCode` 必填,但第一步响应尚未保证稳定返回词法 `genealogyId`,创建结果查询也没有 operation,因此恢复链为 `MISSING_OPERATION`。只有第一步真实响应本身稳定给出字符串 ID 才允许进入第二步;首写超时、断线、5xx、空体或缺 ID 时立即停止并人工对账,禁止按展示名/“联调测试”标识从无正式 item DTO 的 mine 列表猜 ID,也禁止重复建谱;邀请码签发/直接加入、家谱排序、管理员 capability 没有可靠当前 owner |
-| T 世系 | tree、人物列表/详情/增改停用、父母/配偶/兄弟姐妹/子女写入均有声明 | 所有读取权限字段缺失;int64 wire、T04 性别字典、T06 原子排行、邀请四段链、两个绑定 mutation owner、头像上传到访问闭环均冲突或缺失 |
-| F 家族内容 | 动态、评论/回复/点赞、谱文、相册、照片和文件上传有声明 | 视频仅见删除操作,列表/发布/详情链不完整;视频评论、点赞和分享分别是独立候选,不能借动态互动或视频读取合同;置顶等参考动作无当前 owner |
-| R 族务记录 | 亲友记录、祭祀/献礼、成长记录、备忘录、功德记录有声明 | 人生事件和重要证件无明确 APP owner;参考“贺礼”与当前“祭祀献礼”语义必须先拆清 |
-| N 消息 | 通知列表、单条已读、全部已读有声明 | 未读计数没有 operation,G01/M01 不得从分页列表长度推断;没有通知详情 operation,列表还是无 item schema 的通用结果;N02 同一会话且列表项含完整正文时的投影单独记 `dataMode=LOCAL_PREVIEW`,冷启动、深链或缓存缺失状态单独记 `dataMode=CLOSED`;业务跳转、消息类型和目标参数均不能从文案猜测 |
-| M 我的 | 资料、安全、帮助、反馈、推广内容、VIP 套餐/订单有声明 | M08 保持当前家谱邀请 owner,票据查看、签发、撤销分别由 `C-G-INVITE-LIST/ISSUE/REVOKE` 拥有,复制与系统分享分别由唯一平台剪贴板、分享 owner 负责拒绝/失败/返回;邀请票据 operation 当前缺失。参考 APP 推广/推荐码/奖励无当前路由且保持候选;真实支付、提现/变现及部分敏感操作缺完整结果链;“关于”只用本地静态 owner,不依赖帮助列表 |
-
-## 十一、产品参考功能基线与 T01 世系树重做计划
-
-### 11.1 参考资料的归档与换路径办法
-
-1. 第一参考源固定为 `C:\Users\Rain\Desktop\job\app设计`,只作为本机规划输入,不是运行依赖。业务代码、测试、接口合同和构建脚本均不得硬编码该绝对路径。
-2. 该目录当前有 59 张 PNG 和 1 份 PDF。项目相对目录 `docs/design/references/产品参考原稿` 保存了其中 58 张 PNG 和 1 份 PDF,59 个同名文件的 SHA-256 全部一致;源目录新增 `思维导图.png`。在用户确认规划前,不复制新增文件、不删除旧副本。
-3. `思维导图.png` 同时包含 APP、后台管理、公司官网和 PC 管理端分支。只有“用户端苹果安卓 APP”分支可直接进入当前产品候选池;其他分支只用于理解角色、权限和服务依赖,不能自动变成当前 UniApp 路由。
-4. 第二参考源固定为 `C:\Users\Rain\Desktop\job\Jiapu-App`。第一轮只读盘点已完成路由、页面和 API wrapper 清单;继续甄别时不安装依赖、不运行构建、不修改参考仓库,也不读取或迁移其 Git 历史。
-5. 参考项目使用旧的 Vue/uView 结构、旧后端地址和宽松请求封装,且请求层会输出参数和响应;这些实现、环境值、日志方式、Token 处理、组件和数据模型全部禁止迁入当前项目。API wrapper 只用于证明“参考项目曾尝试过某动作”,不能作为当前接口合同。
-6. `docs/产品参考页面功能映射表.md` 必须在交给用户确认前完成。第一源使用 `Dxxx-Pxx-Sxx-Axx` 标识文件、PDF 页/区域、页面、状态和动作;每张单页 PNG 默认自身就是独立 `S01` 状态证据,表内可省略 `S01` 作短写。第二源按 `Jxxx-Sxx-Axx` 标识 78 条活动路由的状态与动作,注释路由单列 `JX001`,7 个未注册文件使用 `JUxx-Sxx-Axx`。附件必须有正向逐项表和按当前 A/G/T/F/R/N/M owner 的反向覆盖索引;组合展示不能省略任何源 ID。
-7. 参考截图和参考项目不按文件整包采纳。甄别最小单位固定为“一个页面状态下的一个用户动作”。文件名相近、画面相似、路由目标相同或代码结构近似都不能直接判为重复:它们可能是普通、管理、编辑、空、错误、权限、角色或主题状态。只有入口、对象、动作、数据、接口和返回行为均被证明等价后,才能共用当前 owner;共用后仍须保留每个来源状态 ID。查看、创建、编辑、删除、邀请、分享、支付等动作可以分别得出不同结论。
-8. 当前项目继续使用已确定的国风资产、色彩和组件语言。参考稿的亮红导航、原卡片比例、旧弹窗、默认 uView 控件和旧图标只表达信息结构,不默认成为视觉验收目标。
-9. 参考源出现、当前项目没有路由或接口 owner 的功能先进入“候选缺口”,必须判断是复用现有页面、增加新路由、后端缺失暂关,还是与当前产品冲突舍弃;不得为了保持 52 条路由而遗漏,也不得为追求功能数量临时创建假页面。隐私资料、重要证件、资金、删除、退出家谱、所有者转移和账号注销一律作为敏感候选单列,参考源存在不构成采纳授权。
-10. 两个源再次变化时,重复“只读文件清单与哈希差异 → 更新页面/动作映射 → 记录新旧结论”的流程;不因源目录缺文件自动删除项目内归档,也不在业务代码里保存机器绝对路径。
-
-### 11.2 T01 目标画面与交互
-
-T01 的验收目标不是“能显示一棵文字树”,而是能够识别人、关系、代际并对选中人物执行明确动作的长世代世系树:
-
-1. 人物节点使用头像卡片,至少呈现头像、姓名、关系标签和代际信息;配偶位于同一代并保持成组关系,父母、子女、兄弟姐妹的连接线不能断裂或指向错误人物。
-2. 有真实头像时通过统一文件投影显示;无头像、文件缺失或加载失败时使用确定性的国风默认头像,不使用随机网络图片或伪造真人照片。不能把 `avatarOssId` 直接拼成 URL。
-3. 支持横向与纵向浏览长世代内容;选中人物需有清晰高亮。长姓名、大字号、大量成员和数十代数据下,卡片、代际标签和连接线仍可辨认。
-4. 点击人物卡后打开唯一的人物操作面板,取代互相竞争的旧底部操作条。面板中央放大展示当前人物卡,头像区域提示并支持“点击头像查看资料”。
-5. 操作面板必须包含以下功能入口,并始终携带当前 `genealogyId` 和 `personId`:
- - 点击头像查看资料;
- - 添加父亲;
- - 添加母亲;
- - 添加配偶;
- - 添加兄弟姐妹;
- - 调整排行;
- - 添加儿子;
- - 添加女儿;
- - 邀请绑定;
- - 编辑信息。
-6. 面板遮罩点击、关闭按钮、Android 系统返回键、页面返回键、重复点击和焦点恢复行为必须一致。提交中的动作禁用重复触发;页面离开或响应迟到时不得把结果写入错误人物。
-7. 当前 Apifox 的 tree/person/member 投影均没有稳定 `canEdit/canInvite/canManage/actionCapabilities` 字段,前端不得猜测角色或伪造 capability。十个必需入口保持可发现;已有单一 declared write operation 的入口可提交最小白名单请求,由服务端最终裁决,并对 403/409/5xx/超时明确失败且不本地假成功。403 只能证明该次请求被拒绝,不能反推出可持续的前端权限。每个动作账本仍须记录权限字段、来源 operation、撤权后的刷新和 403 语义。
-
-已完成参考项目只证明这组动作是产品候选,不证明实现可迁移:其树页面中“添加女儿”仍复用了 `addSon` 意图、“添加母亲”存在注释掉的入口、“邀请绑定”按钮没有闭合动作,删除又混用旧通用用户接口。因此 T01 必须按十个入口分别定义意图和合同,不能复制参考页面后把同名按钮视为完成。
-
-### 11.3 页面职责与唯一 owner
-
-| 页面 | 唯一职责 | 不得承担 |
-| --- | --- | --- |
-| T01 世系树 | 读取树、布局、浏览、选择人物、展示操作面板并导航到对应流程 | 不直接伪造任何写操作成功,不保存另一份成员详情 |
-| T03 成员详情 | 读取并展示真实人物资料;承接“点击头像查看资料” | 不以本地 fixture 冒充服务端人物 |
-| T04 添加亲属 | 统一承接父亲、母亲、配偶、兄弟姐妹、儿子、女儿六类新增关系 | 不为六个入口复制六套提交合同,不猜测缺失 ID |
-| T05 编辑成员 | 修改头像和允许编辑的基础人物资料 | 不承担排行或关系拓扑修改 |
-| T06 排行调整 | 原子调整同辈排行 | 不退化为另一份通用人物编辑页,也不保留旧“关系修正本地预览”假成功路径;关系修正若以后获批必须另立产品动作和原子合同 |
-| 邀请绑定流程 | 在独立合同下邀请用户并绑定人物 | 不与普通加入家谱申请或邀请码直接加入混为一条链 |
-| T07/T08 | 成员目录、成员状态等辅助读取 | 不成为 T01 写操作的旁路 owner |
-
-T04 的六个入口只在路由内部传递经 validator 验证的十进制字符串 ID、内部 `relationType` 枚举和必要意图提示;`relationType` 不是 wire 字段,严禁发送到 `additionalProperties:false` 的 `LineagePersonBody`。页面先展示当前人物和待添加关系,只有性别字典、关系约束和真实响应共同确认后才允许提交。不得复制人物模拟配偶,也不得仅凭中文按钮在本地猜测 wire 值。
-
-| UI 意图 | 完整 endpoint | 请求意图约束 | 当前状态 |
-| --- | --- | --- | --- |
-| 添加父亲 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/parents` | 关系方向由 `/parents` owner 决定;只发送当前已声明并采集的基础人物字段,不发送 `relationType` 或猜测的性别 code | `DECLARED_UNVERIFIED`,待测试账号实测服务端性别/冲突/权限与读后刷新 |
-| 添加母亲 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/parents` | 同上;不得将“母亲”中文标签直接当成 `sex` wire | `DECLARED_UNVERIFIED`,待实测 |
-| 添加配偶 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/spouses` | 不发送 `relationType`;`relationName` 未由页面采集,暂不猜测 | `DECLARED_UNVERIFIED`,待关系方向、重复/冲突、权限与读后刷新实测 |
-| 添加兄弟姐妹 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/siblings` | 不发送 `relationType`;不把单人 `sortOrder` 当同辈排行 | `DECLARED_UNVERIFIED`,待字典/冲突/权限实测 |
-| 添加儿子 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/children` | 关系方向由 `/children` owner 决定;不猜测性别 code | `DECLARED_UNVERIFIED`,待实测 |
-| 添加女儿 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/children` | 同上 | `DECLARED_UNVERIFIED`,待实测 |
-
-### 11.4 接口映射与启用条件
-
-| 用户动作 | 页面 owner | 计划接口 | 启用条件 |
-| --- | --- | --- | --- |
-| 展示世系树 | T01 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/tree` | 树 DTO、稳定 ID、代际、配偶与父子连接关系已收紧并通过运行时测试 |
-| 查看人物资料 | T03 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` | 路由参数与响应投影一致,不回退 fixture |
-| 添加儿子/女儿 | T04 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/children` | 性别 enum、请求 DTO、写入结果、重复提交与结果未知规则明确 |
-| 添加父亲/母亲 | T04 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/parents` | 同上,并由服务端校验关系冲突 |
-| 添加兄弟姐妹 | T04 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/siblings` | 性别/排行合同明确,不通过复制已有节点伪造 |
-| 添加配偶 | T04 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/spouses` | 请求合同明确,并能读取提交后的真实关系 |
-| 编辑人物资料/头像引用 | T05 | `PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` | 字段白名单、头像上传/引用/访问 URL 闭环和结果确认完整 |
-| 调整排行 | T06 | 仅有候选 `PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` 的 `sortOrder` | 当前为 `CONTRACT_CONFLICT`:无批量/原子同辈重排、版本或冲突协议,不得逐人写出部分成功 |
-| 邀请签发、送达与接受 | 独立邀请流程 | 无可靠 operation | `contractState=MISSING_OPERATION`,保持关闭 |
-| 邀请目标身份查找 | 独立邀请流程 | 无隐私安全的可靠 operation | `contractState=MISSING_OPERATION`,保持关闭 |
-| 绑定 mutation | 独立邀请流程 | 成员 PUT 的 `lineagePersonId` 与人物 PUT 的 `appUserId` 是两个候选 | `contractState=CONTRACT_CONFLICT`,确认唯一 owner 前禁止双写 |
-| 邀请绑定结果查询 | 独立邀请流程 | 无可恢复查询 operation | `contractState=MISSING_OPERATION`,结果未知时禁止重试 |
-
-`avatarOssId` 的 owner 是统一上传与文件访问链路;未确认上传、业务实体更新、文件引用和可访问 URL/重进显示四段闭环前,T05 不显示假上传成功。
-
-邀请绑定拆成四段独立账本:
-
-1. 邀请签发、送达、接受:当前没有 operation,保持关闭。
-2. 查找目标身份:当前没有隐私安全的独立 operation,保持关闭。
-3. 绑定已有成员/用户:`PUT /genealogy/app/genealogies/{genealogyId}/members/{memberId}` 的 `lineagePersonId` 与 `PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}` 的 `appUserId` 是两个冲突候选;真实合同确认后只能选择一个 owner。
-4. 结果查询:当前没有可恢复 operation,结果未知时不得重试或双写。
-
-邀请绑定不能借用普通加入申请、邀请码直入或同时调用两个候选 mutation。关闭态检查可以为 `PASS`,但该必需动作的 `productCompletion` 仍为 `BLOCKED`。
-
-所有写操作都必须定义提交中、成功、明确失败和结果未知四种结果。只有后端合同明确支持幂等或存在无副作用的结果查询时才允许安全恢复;超时、断网或 5xx 后不能用 timer 自动提示成功,也不能把本地草稿当成服务端已提交。
-
-### 11.5 数据与状态约束
-
-- `genealogyId`、`personId`、`memberId`、`appUserId`、文件与亲属引用都以十进制字符串为唯一 ID owner。当前 OpenAPI 的 `integer/int64` 与 JavaScript 安全精度冲突;只有服务端响应以字符串返回且请求接受字符串后才能启用。超过安全整数的 number 不得在解析后转字符串补救。
-- 树投影至少明确头像访问结果、姓名、关系类型、代际、父母引用、配偶引用、同辈排行 `sortOrder` 和权限/能力;当前 capability 未声明,所有写入口先关闭。字段缺失必须进入可解释失败或降级状态,不能静默拼错树。
-- 关系类型采用单一枚举 owner,页面、API adapter、validator、测试和文档共同消费,禁止各页面维护中文字符串分支。
-- `sex`、关系、人物状态和排行语义都必须由真实合同提供 enum;T04 内部意图不能充当 wire 字典。
-- 排行调整当前为 `CONTRACT_CONFLICT`。在后端提供原子同辈顺序结果或明确并发协议前,前端只可展示关闭说明,不得逐人物写 `sortOrder` 或在失败后保留假顺序。
-- 恢复信息不得持久化手机号、头像原图、身份证明、邀请凭据等 PII;只保留完成恢复所需的最小非敏感标识和状态。
-
-### 11.6 测试先行与实施顺序
-
-只有规划经用户确认且用户随后明确说“开始执行”后,T01/T03—T06 才按以下独立小批次执行。每批由主代理写入、两位评审者只读复核接口、业务、交互、异常和视觉,当前批通过后才进入下一批:
-
-1. **T01-0 失败门禁**:先新增会失败的合同,锁定头像节点、姓名/关系/代际、唯一人物操作面板、十个动作入口,并禁止旧底部操作条与新面板并存。
-2. **T01-1 树 DTO 与布局**:收紧树 normalizer 和 validator,验证父母、配偶、子女、代际、排行、缺头像、失真 ID、重复节点、断链及循环关系;旧宽 DTO 必须失败。
-3. **T01-2 视觉与交互**:实现头像人物卡、连接线、选中态、横纵浏览和操作面板;覆盖遮罩、返回键、焦点恢复、重复点击、快速切换人物和迟到响应。
-4. **T01-3 页面导航合同**:逐项验证 T01 → T03/T04/T05/T06 的参数、返回后选中态和树刷新;邀请绑定若无合同,只验证诚实关闭态。
-5. **T03/T04/T05/T06 真实接线**:每个页面先写 mapper/runtime 失败测试,再接对应 GET/POST/PUT;六种亲属动作分别验证请求意图,但复用一份 T04 提交合同。
-6. **异常与恢复**:覆盖空树、加载失败、403、404、409、429、500、超时、断网、离页取消、结果未知、权限变化、头像加载失败和提交后重新读取不一致。
-7. **性能与视觉验收**:以小树、数十代、数百成员、长姓名、无头像和多配偶数据检查布局预算、滚动流畅度、连接线及内存;不以无限数据承诺替代明确上限。
-8. **MuMu 与无障碍**:先在 720×1280 实机检查,再补 320/412 响应式检查;验证触控尺寸、文本缩放、读屏名称、焦点顺序、弹层焦点约束、系统返回和低性能设备操作反馈。TalkBack 等无法稳定自动化的项保留可复现人工步骤。
-
-### 11.7 T01 检查结果与产品完成定义
-
-T01 必须分别报告结构/关闭态检查和产品完成度:
-
-- 头像卡、连接线、选择态、唯一操作面板、十个入口可发现、禁用原因、返回行为等可以分别得到 `checkResult=PASS/FAIL`。
-- 某入口因真实后端缺失而正确显示“服务暂未开放”,只表示该关闭态检查 `PASS`;该入口的 `productCompletion=BLOCKED`,T01 产品完成度也不得为 `COMPLETE`。
-- T01 只有以下全部成立时才可记 `productCompletion=COMPLETE`:
-
-1. 真实头像或确定性默认头像可见,姓名、关系、代际和连接线正确。
-2. 点击任一人物只打开一个完整操作面板;查看资料、父亲、母亲、配偶、兄弟姐妹、排行、儿子、女儿、邀请绑定和编辑十个入口均完成真实权限与业务闭环。
-3. T03 展示真实详情;T04 六类关系写入、T05 编辑、T06 原子排行及独立邀请绑定各自遵守唯一 owner,没有 fixture、timer、兼容旁路或假成功。
-4. 树刷新和重进后能以服务端数据确认变更;写结果未知时停止重复写并提供只读恢复路径。
-5. 当前国风视觉一致,长世代滚动、卡片、连接线、遮罩和返回行为在目标尺寸上稳定,无白块、截断、误触和不可读状态。
-6. 接口、业务、交互、异常、视觉、性能和无障碍门禁通过三人交叉评审;自动测试、编译检查和绑定冻结候选包的 MuMu 实机证据齐全。
-
-### 11.8 当前暂停项
-
-- T03 的远端 `GET` 已按 Apifox 人物详情 owner 接线并通过静态/运行时映射门禁,但尚未以测试账号取得本轮脱敏真实响应,仍是 `DECLARED_UNVERIFIED`,不能计入 `LIVE_VERIFIED` 或页面完成。
-- T01 旧的固定底部“查看资料/添加亲属”抽屉已经移除;当前只有点击人物卡打开的唯一人物操作面板。任何单张 MuMu 预览都不构成本节完整验收证据。
-- 在用户明确说“开始执行”前不继续修改 T01/T03—T06,不批量处理参考图,不运行测试、构建或 MuMu 验收。
-
-### 11.9 已完成参考项目的逐项甄别门禁
-
-参考项目与当前项目可能属于不同版本、不同产品边界、不同技术实现或不同后端合同,因此采用优先级固定为:
-
-1. 用户对当前产品明确确认的需求和取舍;
-2. 当前真实后端、Apifox、线上接口文档及可复现响应;
-3. 当前 UniApp 的路由、架构、安全约束和已确定国风视觉基线;
-4. 参考截图与已完成参考项目。
-
-参考项目中的每个候选功能必须逐项回答:
-
-- 业务目标是否与当前产品一致;
-- 使用角色、权限来源和数据归属是否一致;
-- 当前后端是否有对应 operation,请求、响应、枚举和错误语义是否一致;
-- 是否适合当前 UniApp、Android、导航结构和低性能设备;
-- 正常、加载、空、失败、无权限、重复提交和结果未知状态是否完整;
-- 视觉是否能融入当前国风体系,无障碍和触控要求是否满足;
-- 是否包含旧接口、硬编码、兼容分支、fixture、PII、凭据或其他不可继承风险。
-
-每个候选功能只能得出以下一种书面结论:
-
-| 结论 | 含义 | 后续动作 |
-| --- | --- | --- |
-| 直接采用 | 业务、合同、交互和视觉均与当前项目一致 | 先写当前项目失败测试,再按本项目结构实现 |
-| 改造后采用 | 功能有价值,但接口、权限、状态或视觉需要调整 | 在映射表中列出差异和改造边界后实施 |
-| 仅参考交互 | 只能借鉴信息结构或操作方式 | 不复制其数据层、API 代码和环境配置 |
-| 后端缺失,暂时关闭 | 当前服务没有可靠 operation 或结果确认链 | 保留诚实关闭态并登记解除条件 |
-| 与当前产品冲突,明确舍弃 | 违反当前需求、架构、安全或视觉口径 | 记录舍弃原因,禁止后续人员再次误迁移 |
-| 待用户确认 | 证据足够但会扩大产品范围、引入敏感能力或改变既有需求 | 保留书面选项,不进入代码批次 |
-
-`docs/产品参考页面功能映射表.md` 对完成项目增加以下列:参考仓库相对路径、参考路由、候选动作、参考状态流、当前目标路由、当前接口证据、差异、甄别结论、改造边界、测试 owner 和用户待确认项。存在分歧或证据不足时标记“待确认”,不得由代理静默选择。
-
-参考项目不得向当前仓库带入旧后端地址、账号、Token、密钥、签名、应用标识、用户数据、构建产物、依赖缓存或 Git 历史。采用其功能也必须重新通过当前项目的合同测试、运行时测试、编译、MuMu 视觉与三人交叉评审;“参考项目里能运行”不能作为当前项目完成证据。
-
-### 11.10 参考项目资产逐文件复用门禁
-
-用户已经允许把参考项目中的图标等资产拿来补足当前产品。该许可按“可进入逐文件甄别池”执行,不按“整包照搬”执行。规划期只读盘点得到:
-
-- `C:\Users\Rain\Desktop\job\Jiapu-App\static` 共 531 个媒体文件、6,764,740 bytes(约 6.45 MiB);`assets` 只有 JS/CSS/SCSS,`uni_modules\uni-id.zip` 是依赖包而非产品资产。
-- 声明扩展名为 PNG 307、GIF 221、SVG 2、JPG 1;文件签名实为 PNG 311、GIF 217、SVG 2、JPG 1。6 个文件扩展名与 MIME 不一致,迁入前必须规范重导出。
-- SHA-256 完全重复 14 组、28 个文件,迁入时每组只能选择一个 canonical owner。
-- `static/emojis/qq` 434 项、`static/douyin` 18 项及旧视频实验图标、微信/支付宝/支付/VIP/奖励素材、旧 logo 和固定旧文案均有第三方、旧品牌或未批准业务风险,不能因文件存在而启用对应产品功能。
-- 水墨/宗祠、谱书、人物卡边框、中性功能图标和默认头像风格是高价值候选;其中固定姓氏、口号、生成者/提示词式文件名、示例人物、水印及低分辨率仍须逐文件处理。
-
-每个实际考虑复用的文件在复制前建立 `RAxxx` 记录,至少包含:源绝对/相对路径、SHA-256、重复组与 canonical ID、声明扩展名/检测 MIME、尺寸/帧数/透明度/bytes、来源页面和状态、目标 PA/路由/组件/状态、语义用途、决策、复用方式、用户对参考项目的许可记录、第三方/商标信号、个人数据/旧品牌/固定文字/无障碍/性能风险、必要改造和验收证据。决策仍使用六类口径;复用方式固定为原文件、裁切重导出、重绘、仅构图参考或禁用。
-
-逐文件门禁为:
-
-1. **产品门**:必须绑定已批准 PA、页面、状态和动作;资产不能反向新增功能、解除后端关闭或扩大 55 个候选 PA。
-2. **状态门**:相似图标或画面也可能代表普通、选中、禁用、权限、错误等不同状态;未证明语义和行为等价前分别记录、分别验收。
-3. **来源门**:用户已允许评估并复用参考项目资产;带 QQ、抖音、微信、支付宝等第三方/商标信号的文件还需满足当前平台规范,来源不清时只能重绘或不用,规划不写“已拥有版权”结论。
-4. **隐私与品牌门**:不带示例真人/头像、二维码、手机号、姓名、水印、定位、旧 logo、旧口号、奖励/VIP/支付旧文案或固定姓氏。无 EXIF 不等于无个人数据,仍须看画面。
-5. **技术与安全门**:扩展名与 MIME 一致;SVG 不含脚本、外链或未经审查的 data URI;位图去无用元数据;重复哈希只保留 canonical;不得沿用旧绝对路径或外部 URL。
-6. **视觉与无障碍门**:服从当前国风 token;覆盖普通、选中、禁用、加载、错误和关闭态;小图放大不糊,功能图标有语义文本,装饰图不进入读屏,动图提供静态降级和减少动态效果。
-7. **性能与验证门**:记录解码尺寸、包体和首屏影响;超预算就压缩、重绘或按需加载。只对实际采用的 RA 在目标路由各批准状态做 MuMu 截图、缩放、离线/失败检查,并绑定冻结候选 ID。
-
-首批优先甄别而非预先批准的候选包括 `static/iconpng/902.png`、`static/iconpng/z8526@2x.png`、`static/login/bj.jpg`(实为 PNG)、`static/iconpng/treeBJ.png`、`static/iconpng/book.png`、`static/icon/index.svg`、`static/navigation/*`、`static/tabulation/*`、`static/pu/*`、`static/jr.png`、默认头像风格和 `static/login/hd*.gif`。`jiap.svg` 约 397 KiB 且内嵌大位图与固定文字,只作构图参考。规划确认时固定 `referenceAssetFiles=531`、`approvedDirectReuseAssets=0`、`approvedAdaptReuseAssets=0`;收到“开始执行”后,只有通过上述逐文件门禁的 RA 才增加采用数,这属于已批准 PA 内的实现选择,不改变产品动作分母。九小时批次只甄别本轮已批准 PA 实际需要的资产,未选中的候选保持未审、未复制,不把“531 个进入候选池”写成“531 个必须在今晚迁入”。
-
-### 11.11 全项目功能补足矩阵
-
-下表是本轮权威规划的全项目检查骨架;逐页、逐动作和逐接口结论已经落在权威附件中。执行第 0 批只重算并冻结这些结论,不得再临场扩大产品范围。
-
-| 当前域 | 当前活动路由 | 两个参考源提供的候选 | 本轮必须做出的结论 |
-| --- | --- | --- | --- |
-| A 认证 | A01、A04、A05 | `登陆.png`、参考项目登录/注册/找回页,以及账号密码、短信、注册、找回、微信登录等动作 | 四条现有认证流程继续以 TAC 和当前后端为准;微信登录没有当前 APP operation,只能标记候选关闭或待用户确认,不能借旧接口接入 |
-| G 家谱工作区 | G01、G03、G05、G06、G08—G12 | 家谱列表、创建、加入、邀请码、家谱主页、字辈、家谱排序、始祖世代、管理员及权限 | G03 固定为“创建家谱→创建首位人物”两阶段,但恢复链按 `MISSING_OPERATION` 关闭:`regionCode` 由共享行政区划 owner 提供;只有第一步真实响应本身稳定返回词法 `genealogyId` 才登记待续办 ID 并进入第二步。首写结果未知或缺 ID 时停止并人工对账,禁止从 mine 列表按展示名/测试标识猜 ID,禁止假定通用对象壳含 ID,也禁止重复建谱。其余列表/搜索/普通申请/审核/设置/字辈逐项验真,邀请码直入、家谱排序、始祖世代和管理员权限分别判断 owner |
-| T 世系与成员 | T01、T03—T08 | 头像树、表格/树谱模式、人物资料、父母/配偶/兄弟姐妹/儿女、排行、邀请绑定、编辑及参考项目中的删除 | T01 十个必需入口逐项落到 T03/T04/T05/T06/独立邀请流程;T03保持未完成;删除人物/配偶不是本轮十个入口之一,须单列敏感候选,不能因参考项目有按钮而默认加入 |
-| F 家族内容 | F01—F10 | 家族圈、发布/删除/评论、谱文分类与增改删、相册分类与照片管理、视频列表/发布/编辑及短视频评论/点赞/分享 | 动态、谱文、相册、上传逐动作核对当前合同;视频浏览、评论、点赞、平台分享已拆成独立候选 owner,缺合同时诚实关闭,不用旧 API、动态评论 owner 或本地计数假成功 |
-| R 人物与族务 | R01—R11 | 人物、人情簿、贺礼邀请、成长日志、备忘录、功德录、重要证件 | R01/R02 分别作为人物目录、人物资料的独立路由状态,数据只消费 T07/T03/T05 的唯一列表/详情/编辑 owner;R02 不保留通用“新建人物本地预览”,编辑入口只导航 T05。亲友记录、祭祀/献礼、成长、备忘、功德按当前业务语义接线;“贺礼邀请”与“祭祀献礼”先拆分语义;人生事件和重要证件缺 owner 时进入候选缺口 |
-| N 消息 | N01、N02 | 加入申请、生日、贺礼、备忘、疫苗、点赞评论、推广、广告消息及详情 | 当前只有列表与已读合同,未读计数缺 operation,G01/M01 使用同一个关闭 owner 而不从分页长度推断;N02 无详情 operation。同一会话且列表项含完整正文时的投影是独立状态,记 `dataMode=LOCAL_PREVIEW`;冷启动、深链或缓存缺失是另一独立状态,明确返回 N01 并记 `dataMode=CLOSED`。只有服务端提供闭合详情、消息类型、目标 route key、参数和权限失效语义后才恢复 LIVE 详情与业务跳转 |
-| M 我的 | M01—M10 | 个人资料、帮助、设置、修改密码/手机、反馈、家谱邀请、VIP、注销、提现/变现 | M08 保持“选择家谱并管理家谱邀请票据”的当前职责,票据查看/签发/撤销与本地复制/系统分享分别归 `C-G-INVITE-LIST/ISSUE/REVOKE`、`C-S-PLATFORM-CLIPBOARD/SHARE`,缺真实 operation 时保持关闭;参考 APP 推广、推荐码、奖励和变现不得覆盖 M08,均维持无当前路由候选。支付、注销、换绑和提现属于敏感动作,必须有独立合同、人工窗口和结果确认 |
-
-跨域共享项也必须进入映射:登录态与账号切换、当前家谱上下文、角色/capability、文件上传与访问 URL、通知回流、深链参数、缓存失效、写结果未知、Android 返回、触控、系统字号、TalkBack 和长列表性能。任何一个共享项不得在 A/G/T/F/R/N/M 各自复制一份合同。
-
-第一轮已识别但不能静默纳入今晚代码的参考候选如下:
-
-| 候选 | 参考证据 | 当前判定 |
-| --- | --- | --- |
-| 微信一键登录 | 思维导图与参考登录页 | 当前后端无 APP operation,`后端缺失,暂时关闭`;是否长期需要由用户后续确认 |
-| 管理员列表与细粒度权限 | 思维导图、参考 `admin` 三页 | 当前只有成员类接口证据,没有闭合的管理员角色/权限 owner,先列 `待用户确认` 与后端缺口 |
-| 家谱排序、始祖世代调整 | 参考 `sortGenealogy`、`ancestorsOrder` 与设计图 | 与 T01 人物排行、G12 字辈排序不是同一合同;分别缺可靠 owner,不能互相借用 |
-| 重要证件 | 参考 `document` 页面 | 当前 52 路由和 APP 合同均无 owner,列产品候选,不临时新增假入口 |
-| 家族圈置顶 | 思维导图 | 当前动态合同未见置顶 capability,暂时关闭 |
-| 广告/宣传视频 | 参考消息广告和宣传视频页面 | 与当前普通通知、通用推广和 F10 家族视频分开甄别;独立使用 `C-M-PROMO-VIDEO` 及其评论/点赞/分享候选 owner,无可靠 operation 时不采用 |
-| 提现、分享变现 | 参考“我的”页面 | 涉及真实资金且不属于已确认当前需求,保持 `待用户确认`,今晚不执行 |
-| 删除世系人物/配偶 | 参考 T01 操作面板 | 当前后端虽有停用人物声明,但用户本轮明确的是十个其他入口;删除必须另设权限、影响预览和二次确认后再决定 |
-| 扩展个人隐私资料 | 设计人物表单中的微信、QQ、住址、学历、职业等字段及参考重要证件页 | 当前需求未授权扩展收集,后端也无闭合隐私/可见性 owner,结论为 `与当前产品冲突,明确舍弃`;只保留反例证据,不采纳、不存储、不上传 |
-| 移除成员、退出家谱、所有者转移、账号注销 | 参考家谱列表/我的页与当前成员类声明 | 均为破坏性或身份敏感动作,必须单独产品确认、影响预览、再认证、结果查询和人工窗口;不因存在 operation 自动启用 |
-
-### 11.12 确认与执行门禁
-
-1. 用户已明确“需求说完了”,需求收集门禁已关闭。
-2. 主代理完成本文修订后,由三人按第七节交叉评审;只允许主代理吸收意见修改本文。
-3. 三人评审收口后,把完整修订版、主要变化、评审结论和仍待确认项交给用户。
-4. 交付用户时必须把两项单独列明并取得确认:`T_due=2026-07-24 08:00` 是否接受;55 个候选 PA 本轮是否维持 `approvedCandidateActions=0`。笼统沉默不视为接受具体截止时间或批准候选。
- - 用户已于 2026-07-23 确认将截止更新为 08:00,并确认 55 个候选 PA 本轮维持 `approvedCandidateActions=0`。
-5. 用户确认规划只代表规划定稿,业务代码、接口接线、样式、测试、构建和 MuMu 仍保持冻结。
-6. 只有用户明确说“开始执行”,第六节计时和第 0 批才启动;第 0 批只重算、冻结已确认映射和环境,不得重新解释为需求收集。
-7. 用户未说“开始执行”时,不因时间已到“今晚”而自行开工,也不把只读规划核对解释为代码阶段已经开始。
diff --git a/docs/全量页面接口联调交接说明-2026-07-24.md b/docs/全量页面接口联调交接说明-2026-07-24.md
deleted file mode 100644
index 53934cd..0000000
--- a/docs/全量页面接口联调交接说明-2026-07-24.md
+++ /dev/null
@@ -1,140 +0,0 @@
-# 全量页面接口联调交接说明
-
-更新日期:2026-07-26
-适用项目:家谱 APP 前端(`jiapuapp`)
-
-## 一、交接结论
-
-本轮已按 `pages.json` 对 **52 个已注册页面**做了重新复核:页面可进入、页面调用的接口方法存在、真实服务端可读取的数据已回读验证、没有继续以页面 mock/fixture 冒充服务端结果。
-
-不能把本轮结论简化成“所有接口均已联调通过”。世系首位成员创建目前由服务端返回业务 `code: 500`,导致依赖真实成员的详情、编辑与关系链路没有可用测试实体,仍是明确阻塞项。
-
-2026-07-26 的浏览器真实上传复测还确认了第二个合同阻塞:H5 已能从页面选择本地图片并完成 `init/chunk/complete` 上传,但 `complete.ossId` 是 19 位字符串,而照片/封面等业务 DTO 仍要求数值 `int64`。前端不能安全地把该值转成 JavaScript number,因此目前不会伪造照片创建成功。完整请求、响应和后端所需统一字段合同见 `docs/后端接口缺口与首位成员阻塞清单-2026-07-24.md` 的“八”。
-
-## 二、本轮已验证的范围
-
-### 2.1 页面路由与接线
-
-| 模块 | 页面数 | 浏览器逐页打开 | 结论 |
-| --- | ---: | ---: | --- |
-| A 认证 | 3 | 3/3 | 页面入口、表单和会话态下的路由行为已检查;未触发短信、注册、找回密码等敏感写入。 |
-| G 家谱 | 9 | 9/9 | 家谱列表、创建、概览、搜索、申请、审核、设置、字辈页面均可稳定进入。 |
-| T 世系 | 7 | 7/7 | 树、成员目录及安全错误态可进入;真实成员读写见“阻塞项”。 |
-| F 家族 | 10 | 10/10 | 动态、谱文、相册、上传等页面均可进入;真实动态/谱文/相册数据已读回。 |
-| R 记录 | 11 | 11/11 | 人物、亲友往来、礼仪、成长、备忘、功德等页面均可进入;多类真实创建已回读。 |
-| N 通知 | 2 | 2/2 | 通知中心可读取;消息详情保持缺少读取 owner 的关闭态。 |
-| M 我的 | 10 | 10/10 | 资料、帮助、推广、VIP 等页面可进入;敏感安全操作未执行。 |
-| 合计 | **52** | **52/52** | 路由稳定渲染通过。 |
-
-页面内共扫描到 71 个 `appApi` 调用,均能在 `utils/api.js` 找到对应方法;页面目录未发现 `data/mock` 或 fixture 导入。
-
-### 2.2 已做过真实服务端读回的业务
-
-以下均只使用测试账号和测试家谱数据,未做删除、退出、改密、短信或支付操作。
-
-| 业务 | 已验证闭环 |
-| --- | --- |
-| 家谱创建 | G03 创建后,可在 G01 列表和 G05 概览读回。 |
-| 家族动态 | F02 创建后,可在 F01 列表、F03 详情读回。 |
-| 谱文 | F06 创建后,可在 F04 列表、F05 详情读回。 |
-| 相册 | F07 创建后,可在 F08 相册详情读回。 |
-| 亲友往来 | R04 创建后,可在 R03 列表读回。 |
-| 礼仪活动 | R07 创建后,可在 R05 列表读回。 |
-| 成长记录 | R08 创建后重新读取列表。 |
-| 家族备忘 | R10 创建后重新读取列表。 |
-| 功德记录 | R11 创建后重新读取列表。 |
-| 个人资料、帮助、推广、VIP、通知 | 已完成真实读取页面验证;不输出账号或会话敏感信息。 |
-
-### 2.3 本轮修正
-
-- F01/F03 不再把服务端 `feedType=text` 原码直接展示给用户,统一显示为“文字动态”。
-- 更新了 F 模块业务合同测试,使其校验当前真实 API 读写路径,而非旧 fixture/预览路径。
-- 新增全页面浏览器审查脚本:`tests/all-page-route-runtime-smoke.js`。
-
-## 三、明确阻塞:世系首位成员创建
-
-### 现象
-
-测试家谱为空世系时,T04 “录入首位成员”已完成前端表单校验与请求组装;使用合法最小请求(姓名、第一世)调用:
-
-```text
-POST /genealogy/app/genealogies/{genealogyId}/lineage/persons
-```
-
-HTTP 返回成功,但业务响应为 `code: 500`,未创建成员;之后读取世系树仍为空。
-
-### 影响范围
-
-- T03 成员档案:没有真实 `personId`,无法完成真实详情读回。
-- T04 新增亲属:没有首位成员,不能继续建立亲属关系。
-- T05 编辑成员、T06 调整排行、T08 成员状态:没有真实成员实体,不能完成真实读写验证。
-- R01/R02 的真实人物详情同样没有可用实体可验证。
-
-### 需要后端协助确认
-
-1. 查询上述创建请求对应的服务端异常栈和租户/家谱初始化条件。
-2. 确认创建首位成员是否还存在 Apifox 未声明的必填字段或前置初始化操作;如有,补充到 APP 接口合同。
-3. 修复后提供一个可创建或可读取的测试成员,再继续 T03–T08、R01–R02 的真实闭环验证。
-
-前端不会猜测额外字段,也不会用本地假成员伪造成功。
-
-## 四、正确关闭的页面/动作
-
-下列不是漏接,而是当前 APP 接口没有足以支撑该页面真实业务的 owner,或操作超出本轮授权范围:
-
-| 页面/能力 | 当前处理 | 原因 |
-| --- | --- | --- |
-| F10 家族视频 | 明确提示暂未开放 | 仅见删除 operation,未见视频列表、详情、播放、发布等读取/写入合同。 |
-| R09 人生事件 | 明确提示暂未开放 | APP 目录中无独立人生事件资源。 |
-| N02 消息详情 | 明确提示暂未开放 | 只有通知列表和标已读,没有单条详情读取 owner。 |
-| M03 安全概览 | 已接真实 profile 只读概览 | 2026-07-26 实测 `GET /auth/profile` 返回 `phone`、`userNo`、`status`;页面仅展示掩码手机号、账号编号和状态。设备与登录记录仍无独立读取 operation,不展示或推断。 |
-| M05 换绑手机号 | 等待人工 TAC/短信验证 | 缺少可安全消费的当前手机号 DTO 与已核实验证码链路。 |
-| 删除、退出、改密、支付 | 未执行 | 本轮测试范围禁止敏感操作。 |
-
-## 五、复测方式
-
-### 5.1 前置条件
-
-- 启动本地 Web 预览,默认地址:`http://localhost:5173`。
-- 使用已登录的测试账号浏览器,Chrome 远程调试端口为实际可用端口。
-- 设置一个测试家谱 ID;不要使用生产数据。
-
-### 5.2 全页面路由复核
-
-为避免一次跑完整 52 页超过终端时限,可分四段执行:
-
-```powershell
-$env:CDP_PORT='9777'
-$env:GENEALOGY_ID='<测试家谱ID>'
-$env:PAGE_AUDIT_START='0'; $env:PAGE_AUDIT_END='26'; node tests\all-page-route-runtime-smoke.js http://localhost:5173
-$env:PAGE_AUDIT_START='26'; $env:PAGE_AUDIT_END='34'; node tests\all-page-route-runtime-smoke.js http://localhost:5173
-$env:PAGE_AUDIT_START='34'; $env:PAGE_AUDIT_END='45'; node tests\all-page-route-runtime-smoke.js http://localhost:5173
-$env:PAGE_AUDIT_START='45'; $env:PAGE_AUDIT_END='52'; node tests\all-page-route-runtime-smoke.js http://localhost:5173
-```
-
-脚本会为有测试实体的页面读取真实数据;成员专属页面在后端首位成员故障未修复前只验证安全错误态,不把这当作真实成员接口通过。
-
-### 5.3 静态和编译检查
-
-```powershell
-powershell -ExecutionPolicy Bypass -File tests\compile-audit.ps1
-powershell -ExecutionPolicy Bypass -File tests\interface-page-mapping-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests\active-page-business-ownership-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests\f-business-flow-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests\r-business-flow-contract.ps1
-git diff --check
-```
-
-## 六、继续推进顺序
-
-1. 后端先解决首位成员创建 `code:500`,或提供可读取的测试成员。
-2. 用真实成员复测 T03–T08、R01–R02 的读取和允许的写入闭环。
-3. 对接口已存在但页面因没有稳定 ID 暂未开放的单条详情/编辑能力,拿到响应 DTO 和 ID 后逐项补齐。
-4. 需要判断视觉问题时,以模拟器为准;浏览器主要用于接口、路由和网络请求验证。
-
-## 七、交接边界
-
-- 不应把“页面能打开”或“表单显示成功”写成后端业务成功;必须以服务端返回和后续读取回显为准。
-- 不应添加 mock 成员、mock 视频、mock 消息详情或本地成功态补齐后端缺口。
-- 不应在无人值守时执行短信、换绑、改密、退出、删除、审核或支付。
-- 测试过程中产生的是测试家谱中的测试数据;后续清理需要由具备删除授权的人员单独确认后执行。
diff --git a/docs/后端接口缺口与首位成员阻塞清单-2026-07-24.md b/docs/后端接口缺口与首位成员阻塞清单-2026-07-24.md
deleted file mode 100644
index a051082..0000000
--- a/docs/后端接口缺口与首位成员阻塞清单-2026-07-24.md
+++ /dev/null
@@ -1,545 +0,0 @@
-# 后端接口缺口与首位成员阻塞清单
-
-更新日期:2026-07-24
-适用范围:家谱 APP 前端(`jiapuapp`)与 APP API 合同维护
-
-## 目的与边界
-
-本文供后端确认接口 owner、DTO 和测试数据,不要求前端猜测字段或用本地数据绕过接口。下文的“需要”分为两种:
-
-- **已有接口但不可闭环**:路径和当前参数已存在,需修复服务端行为或补全可消费的 DTO。
-- **缺少业务 owner**:现有 APP OpenAPI 没有该页面所需的读取/写入 operation;需要后端和产品先确定资源归属,再发布合同。
-
-除非下文明确写为“当前已声明字段”,字段名、枚举、分页形式和响应结构都由后端在 APP OpenAPI 中一次性定义;前端不会从其他模块、PC 接口或示例数据推断。
-
-## 通用请求约束
-
-当前已声明的受保护 APP 接口均需要当前测试账号的认证会话和 `clientid` 请求头。若请求体含 `clientId`,其值必须与该 Header 一致。本文不记录真实 token、手机号或生产数据。
-
-后端交付一个新 operation 或 DTO 时,请同时在 APP OpenAPI 的 YAML/JSON 中补齐:路径、HTTP 方法、鉴权、所有 path/query/body 参数、成功响应、可预期的 4xx/5xx 业务码及字段必填性。仅有 HTTP 200 而业务 `code` 为失败,不能视为接口成功。
-
-## 一、缺少业务 operation 的页面
-
-### F10 家族视频:缺视频读取 owner
-
-现状:`pages/family/f10-video-list.vue` 已明确关闭。当前 OpenAPI 只声明:
-
-```text
-DELETE /genealogy/app/genealogies/{genealogyId}/videos/{videoId}
-```
-
-没有视频列表、详情、播放地址或发布 operation。删除接口不能反推出读取和播放合同。
-
-当前页面入口可提供的业务上下文只有:
-
-| 参数语义 | 来源 | 状态 |
-| --- | --- | --- |
-| `genealogyId` | 页面路由 | 已有,必需 |
-| 当前登录账号 | 认证会话 | 已有,必需 |
-| `clientid` | APP 请求头 | 已有,必需 |
-
-请后端/产品先确认视频资源是否归属某个家谱。若是,最小可用的首个 operation 应是“读取该家谱可见视频列表”,并明确:
-
-1. 是否分页;若分页,统一选择并声明 `pageNum/pageSize` 或 `cursor/pageSize` 之一,不能让前端猜测。
-2. 每条记录的稳定视频标识,以及当前页面用于渲染列表所需的明确字段和字段类型。
-3. 当前账号无权、资源不存在、空列表的响应语义。
-
-视频详情、播放、发布、编辑、评论、点赞和分享目前没有对应页面表单或页面数据模型;若产品要开放这些能力,请为每项单独给出 operation 与 DTO,不要用相册或动态接口兼容代替。
-
-### R09 人生大事:缺独立资源与归属定义
-
-现状:`pages/records/r09-life-events.vue` 已明确关闭;APP/PC OpenAPI 中都未发现独立“人生事件/life event”资源。
-
-从 R02 人物详情跳转 R09 时会传入 `genealogyId` 和 `personId`,但 R09 当前没有读取或写入表单,因此不能从 UI 推断事件到底是“人物专属”还是“家谱公共”。请后端/产品先在以下两种归属中选择一种:
-
-| 资源归属 | 最少识别参数 |
-| --- | --- |
-| 人物专属事件 | `genealogyId`、`personId` |
-| 家谱公共事件 | `genealogyId` |
-
-归属确定后,请提供对应的列表/详情/创建或编辑 operation(以产品实际要开放的页面为准),并定义事件的必填业务字段、时间字段、排序/分页、权限和错误语义。归属未确定前,前端不会把成长记录、备忘或人物简介映射成人生大事。
-
-### N02 消息详情:缺单条详情读取 operation
-
-现状:当前已声明:
-
-```text
-GET /genealogy/app/notifications
-POST /genealogy/app/notifications/{notificationId}/read
-POST /genealogy/app/notifications/read-all
-```
-
-没有单条详情读取 owner,因此 `pages/notification/n02-message-detail.vue` 不展示 fixture 正文,也不从通知字段推断业务跳转。
-
-建议后端补一个单条详情读取 operation;具体路径可由后端确定,但其最小输入和输出语义应为:
-
-| 位置 | 需要项 |
-| --- | --- |
-| path 参数 | `notificationId`;应与现有“标记已读”接口使用同一通知标识语义 |
-| 请求上下文 | 当前登录账号、`clientid` |
-| 响应必需内容 | 通知标题、完整纯文本正文、发布时间、已读状态,以及供服务端内部定位的稳定通知标识 |
-| 错误语义 | 当前账号无权/通知不存在时应明确失败,不能返回其他账号的通知 |
-
-业务跳转不是本次最低需求。若后端未来要返回业务目标,需另行提供受权限约束的 `bizType → 前端路由键 + 必填参数 + 失效语义` 闭合字典;前端不会由 `bizId`、标题或正文猜路由。
-
-## 二、已有路径但缺少可安全消费合同的页面
-
-### M03 账号与安全:已解除(真实 profile 只读概览)
-
-2026-07-26 已用测试账号真实读取 `GET /genealogy/app/auth/profile`。响应含 `phone`、`userNo`、`status`;M03 已接入并只显示本地掩码手机号、账号编号和账号状态。页面不把明文手机号写入路由、日志或缓存。
-
-“设备列表”“登录记录”“安全等级”仍没有独立读取 owner,也不属于当前 M03 的数据模型;页面不会展示或推断这些内容。建议后端仍在 Apifox 为 profile 发布明确 DTO;如产品要展示上述资源,应分别定义 operation、字段、权限和保留期。
-
-### M05 换绑手机号:已有最终 PUT,但缺可验证的安全链路与读取 DTO
-
-当前 OpenAPI 已声明最终写入接口:
-
-```text
-PUT /genealogy/app/auth/phone
-```
-
-当前已声明的请求参数如下;它们是现状记录,不是前端新增猜测:
-
-| 位置 | 字段 | 约束 |
-| --- | --- | --- |
-| Header | `clientid` | 必填 |
-| Body | `clientId` | 必填,必须等于 Header `clientid` |
-| Body | `phone` | 必填,新手机号 |
-| Body | `smsCode` | 必填;当前导出合同为 4 位数字 |
-| 请求上下文 | 当前登录账号 | 必填 |
-
-当前 OpenAPI 还声明通用发码接口:
-
-```text
-POST /genealogy/app/auth/sms/code
-```
-
-其当前 body 必填字段为 `clientId`、`tenantId`、`grantType`、`sceneCode`、`phone`、`validToken`;换绑场景为 `APP_PHONE_CHANGE`。当前 profile 已能只读获取并掩码显示手机号,但没有经过人工确认的换绑专用 TAC/发码/校验闭环;M05 因而继续保持关闭,且不在无人值守时发送短信或换绑。
-
-请后端确认并在同一版本交付:
-
-1. `APP_PHONE_CHANGE` 的 `validToken` 获取、绑定手机号主体校验、过期和一次性消费语义;如通用发码接口不适合作为换绑 owner,请提供专用 operation,而不是要求前端复用未知场景。
-2. 最终 PUT 成功、验证码错误/过期/重复、手机号已占用、无权限和结果未知时的明确 HTTP 与业务码语义。
-
-本问题单只要求合同和人工可控的测试条件,不授权前端执行短信、换绑或其他账号安全写入。
-
-## 三、已有接口但被服务端 `code:500` 阻断的成员页面
-
-这不是“缺接口”,而是首位成员无法创建导致没有真实 `personId`。阻断请求为:
-
-```text
-POST /genealogy/app/genealogies/{genealogyId}/lineage/persons
-```
-
-当前已验证的最小请求:
-
-| 位置 | 参数 | 值/约束 |
-| --- | --- | --- |
-| Path | `genealogyId` | 可访问的测试家谱 ID |
-| Header | `clientid` | 必填 |
-| 请求上下文 | 当前测试账号 | 必填 |
-| Body | `name` | 当前 `LineagePersonBody` 唯一 required 字段;非空成员姓名 |
-| Body | `generation` | 首位成员固定为整数 `1` |
-
-2026-07-26 又从 T04 页面填写了可安全收集的全量资料并真实提交:姓名、人物编号、示例字典值、排序、别名、字辈、生卒日期、生卒地、安葬地、简介、备注;HTTP `200`,业务仍返回 `code:500 / 发生未知异常,请联系管理员`。首位成员不应伪填 `fatherId`、`motherId`、`relationName`;`appUserId` 缺同类型候选映射,头像 `avatarOssId` 仍受 19 位 `ossId` 类型冲突阻断。`sex`、`birthLunar`、`deathLunar`、`personStatus` 虽为可选,但 Apifox 仅称项目字典值、无枚举,页面不能把猜测的代码或农历文本作为正式交互。
-
-已复现结果:最小请求与上述全字段页面请求均为 HTTP 层成功、业务响应 `code:500`;随后读取世系树仍为空。
-
-请后端处理:
-
-1. 查询该请求的异常栈,以及空世系创建首位成员所需的家谱/租户初始化条件。
-2. 修复后使该最小合法请求返回业务成功,并返回可读取的成员结果(至少可取得稳定 `personId`)。
-3. 以同一测试家谱验证后续读取:世系树、成员目录分页、成员详情均能读到该成员。
-4. 若暂不能修复,请提供当前测试账号有访问权限的测试 `genealogyId` 与真实 `personId`,供只读和允许写入的回读验证;不要提供生产数据。
-
-解锁范围为 T03–T08、R01–R02:成员详情、首位成员/亲属创建、编辑、排行、成员目录与成员状态等。已有读取/写入路径应在取得真实 `personId` 后按页面顺序验证,不应改成 mock 或本地假成功。
-
-## 四、后端回传模板
-
-请每个问题按下列项目回复,便于前端不重做已接线部分:
-
-```text
-页面/问题:
-资源 owner:
-APP operation(HTTP 方法 + 路径):
-鉴权和 clientid 要求:
-path/query/body 参数(字段、类型、必填、枚举/范围):
-成功响应 DTO(字段、类型、必填):
-错误响应(HTTP 状态 + 业务 code + 可展示文案):
-分页/排序/权限语义(如适用):
-可使用的测试 genealogyId / personId(仅测试数据):
-OpenAPI YAML/JSON 更新版本:
-```
-
-前端收到更新后的合同和测试数据后,会先做最小浏览器真实请求,并以服务端成功响应后的列表/详情回读作为验收依据;样式问题另在模拟器复核。
-
-## 五、A01 密码登录:已解除
-
-2026-07-25 已在桌面版 Apifox 核对并用测试账号直连验证。最新已发布合同如下:
-
-| 位置 | 字段 |
-| --- | --- |
-| Header | `clientid` |
-| Body | `grantType=password`、`tenantId`、`phone`、32 位 MD5 `password`;`validToken` 仅在验证中心策略开启时必传 |
-
-`clientId` 与 `sceneCode` 不再属于密码登录 body:后端根据 `POST /genealogy/app/auth/login` 绑定 `APP_PASSWORD_LOGIN` 场景。前端先查询 `GET /genealogy/app/auth/verification/password-login/require`;服务端返回 `required:false` 时不伪造滑块或票据,直接提交上述 body;返回 `required:true` 时才完成验证中心 challenge/verify 并提交真实 `validToken`。
-
-实际结果:`password-login/require` 返回 `HTTP 200 / code:200 / required:false`;随后密码登录返回 `HTTP 200 / code:200`,响应含 `access_token`。本项不再是后端阻塞。
-
-## 六、2026-07-25 Apifox 认证动作合同更新(已接入)
-
-Apifox 当前“家谱”项目新增并发布了下列 APP 认证动作接口;本地旧 `APP.openapi.json/yaml` 尚未同步这次导出,不能再作为认证链的 source of truth:
-
-```text
-GET /genealogy/app/auth/verification/{operationCode}/require
-POST /genealogy/app/auth/verification/{operationCode}/challenge
-POST /genealogy/app/auth/verification/{operationCode}/verify
-POST /genealogy/app/auth/sms/{operationCode}/code
-```
-
-`operationCode` 的已发布枚举为:
-
-```text
-password-login | sms-login | register | forgot-password | phone-change | account-deactivate
-```
-
-合同要点:
-
-| 操作 | Header | path/query/body |
-| --- | --- | --- |
-| 查询策略 | `clientid` | path `operationCode`;query `tenantId`、`subject` |
-| 获取挑战 | `clientid` | path `operationCode`;body `tenantId`、`subject` |
-| 校验挑战 | `clientid` | path 必须与挑战使用同一 `operationCode`;body `tenantId`、`subject`、`challengeId` 和验证码证据 |
-| 发送短信 | `clientid` | path `operationCode`;body `tenantId`、`phone`、`grantType=sms`;仅服务端策略开启时提交 `validToken` |
-
-所有新接口都明确禁止前端再提交 `clientId` 或 `sceneCode`;服务端按 APP 路由的当前激活绑定解析验证场景。
-
-已做的最小真实验证(仅测试手机号、未发送短信):
-
-| 请求 | 结果 |
-| --- | --- |
-| `GET …/verification/APP_SMS_LOGIN/require` | `HTTP 200`,业务 `code:500`:不支持的认证业务动作 |
-| `GET …/verification/sms-login/require` | `HTTP 200`,业务 `code:200`,`required:true`,`TIANAI/SLIDER` |
-| `GET …/verification/password-login/require` | `HTTP 200`,业务 `code:200`,`required:false`,服务端绑定 `sceneCode: APP_LOGIN` |
-
-前端已将 A01/A04/A05 的验证、挑战、校验和发码链接到新路径;A01 密码登录使用 `password-login`,策略为 `required:false` 时直接调用最新密码登录 body;返回 `required:true` 时携带真实 `validToken`。短信、注册、找回仍只在服务端返回 `required:true` 后完成 TAC 并携带真实 `validToken`。
-
-已用测试账号验证 A01 密码登录的真实成功响应;本轮未发送短信、注册、改密、换绑、退出或执行其他敏感操作。
-
-## 七、2026-07-25 桌面 Apifox 复核:仍缺 owner 与分页响应异常
-
-以下结论直接来自桌面版 Apifox 当前 APP 目录,前端不以其他资源替代:
-
-| 页面 | Apifox 当前 operation | 缺口 |
-| --- | --- | --- |
-| F10 家族视频 | 仅 `DELETE /genealogy/app/genealogies/{genealogyId}/videos/{videoId}` | 缺视频列表、详情、播放地址、发布/上传和编辑 owner |
-| R09 人生大事 | “族务记录”目录仅有成长记录、备忘、亲友记录、功德记录四类 operation | 缺人生事件的列表、详情、创建、编辑、删除 owner |
-| N02 消息详情 | 通知目录只有列表、单条标已读、未读数、全部标已读 | 缺单条消息详情读取 owner |
-
-另发现一个后端响应异常,不影响当前 F01(F01 使用非分页 `GET …/feeds`,已真实返回数组),但会使已发布分页 operation 无法使用:
-
-```text
-GET /genealogy/app/genealogies/{genealogyId}/feeds/page?pageNum=1&pageSize=20
-```
-
-桌面 Apifox 将成功响应声明为 `PageResult`;同一测试账号实际得到 `HTTP 200 / code:200`,却完全省略 `data`。客户端的分页合同需要 `data.rows`(数组)和 `data.total`(整数),因此当前会精确拒绝为分页响应无效,不能把空 envelope 当成空列表。
-
-请后端:
-
-1. 为 F10、R09、N02 分别提供独立 APP operation 与完整 DTO;不要让前端复用相册、成长记录或通知列表字段。
-2. 修复 `feeds/page` 成功响应,使 `data.rows` 和 `data.total` 与 Apifox `PageResult` 一致;若该 operation 已废弃,请在 Apifox 明确下线,避免保留可调用但无结果的合同。
-
-## 八、2026-07-26 真实 H5 图片上传:`ossId` 跨接口类型冲突
-
-本项使用测试家谱的 F09「添加照片」页面、浏览器文件选择器和本地真实图片
-`static/assets/foundation/transparent/auth-login-outline.png` 验证;没有使用 mock、fixture 或手工伪造上传回执。
-
-实际请求链路均返回 `HTTP 200 / code:200`:
-
-```text
-POST /genealogy/app/files/resumable/init
-POST /genealogy/app/files/resumable/chunk
-POST /genealogy/app/files/resumable/complete
-```
-
-`complete` 的真实响应为(URL 已省略):
-
-```json
-{
- "code": 200,
- "data": {
- "fileName": "auth-login-outline.png",
- "ossId": "2081232520259612673"
- }
-}
-```
-
-该 `ossId` 是 19 位雪花标识,必须以字符串原样传递。它大于 JavaScript `Number.MAX_SAFE_INTEGER`;转换为 number 会丢失精度。当前照片创建 DTO 却把 `ossId` 声明为 `int64` 数值,F09 无法在不篡改标识的前提下提交:页面已经明确提示并停止在关联业务数据之前。
-
-受影响的是所有“上传回执 → 业务表单”页面,而不只是 F09:动态配图、谱文封面、相册封面/照片、家谱封面、礼仪图片、备忘附件等。前端不会把字符串转为不安全 number,也不会提交截断后的 ID。
-
-请后端在同一 APP OpenAPI 版本统一文件标识合同:
-
-| 位置 | 需要确定的合同 |
-| --- | --- |
-| 上传完成响应 | `ossId` 保持十进制字符串(现网已如此返回),并明确为稳定文件标识 |
-| 所有消费该标识的 APP 请求 DTO | 对应字段统一接受同一十进制字符串;不要在 JSON 中要求前端传 `int64` 数值 |
-| 响应 DTO 与字段示例 | 同步明确字符串类型、正整数词法约束和真实大于 `2^53-1` 的示例 |
-| Apifox 发布内容 | 更新照片创建、封面、附件等所有相关 operation,避免上传接口和业务接口各自定义一套类型 |
-
-后端发布统一合同后,请提供仅测试数据可写入的家谱上下文。前端会重新从 F09 页面选择真实文件,完成“上传 → 创建照片 → 相册列表/详情回读”验收;在此之前不会猜测创建照片接口是否私下兼容字符串。
-
-## 九、2026-07-26 Apifox 全量复核:贺礼邀约缺少受邀人候选来源
-
-桌面 Apifox 当前已发布以下 4 个“贺礼邀约” operation:
-
-```text
-PUT /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/invitees
-GET /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/invitations
-PUT /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/invitations/me
-GET /genealogy/app/genealogies/ceremony-invitations/mine
-```
-
-其中请求合同已明确,前端不会补猜字段:
-
-| operation | 必填参数 | 可选参数 | 备注 |
-| --- | --- | --- | --- |
-| 替换活动受邀人 | path `genealogyId`、`ceremonyId`;body `inviteeUserIds` | 无 | `inviteeUserIds` 是唯一业务用户 ID 的完整数组;空数组表示取消全部尚未响应的邀请 |
-| 查询活动邀请名单 | path `genealogyId`、`ceremonyId` | 无 | 返回邀请记录列表 |
-| 响应当前用户邀请 | path `genealogyId`、`ceremonyId`;body `inviteStatus` | 无 | 枚举仅允许 `ACCEPTED` 或 `DECLINED` |
-| 查询我的活动邀请 | 无业务 path/body | 无 | 当前登录业务用户的有效邀请列表 |
-
-当前 `CeremonyInvitationVo` 可读取字段为:`invitationId`、`genealogyId`、`ceremonyId`、`inviteeUserId`、`inviteStatus`(`PENDING` / `ACCEPTED` / `DECLINED` / `CANCELED`)、`inviteVersion`、`deliveredTime`、`readTime`、`responseTime`、`ceremonyTitle`、`ceremonyTime`、`location`、`locationAddress`、`longitude`、`latitude`。这些 ID 均为 `int64`,真实雪花 ID 必须统一允许十进制字符串传递,不能要求 H5 转为不安全的 JavaScript number。
-
-### 阻塞点
-
-R07 需要的是 `inviteeUserIds`(业务用户 ID),但当前 APP 家谱成员列表没有声明可供选择的业务用户 ID,也没有“可受邀用户候选列表” operation。`memberId`、`lineagePersonId` 和 `inviteeUserId` 是不同资源标识,前端不会用任一个替代另一个,也不会提供让用户手输未知业务 ID 的伪流程。
-
-请后端在同一版 APP OpenAPI 中二选一,并提供仅测试数据:
-
-1. 在现有“家谱成员列表/选项”成功 DTO 中明确返回稳定的 `appUserId`(或等价字段),并声明该字段就是 `inviteeUserIds` 的合法值;或
-2. 新增“查询活动可邀请用户候选列表” operation,至少返回业务用户 ID、展示名、是否可邀请、不可邀请原因。
-
-同时请确认 `int64` 业务用户 ID 在所有 APP JSON 请求/响应中使用十进制字符串合同,避免与第八节 `ossId` 相同的精度丢失问题。候选来源和字符串 ID 合同发布前,前端只接入邀请读取/响应的精确 API 方法,不会把“替换受邀人”伪装成可用页面功能。
-
-## 十、2026-07-26 Apifox 路径修正:行政区划
-
-桌面 Apifox 当前正式路径为:
-
-```text
-GET /genealogy/region/children?parentCode={parentCode}
-GET /genealogy/region/path/{regionCode}
-GET /genealogy/region/search?keyword={keyword}&level={level?}&limit={limit?}
-GET /genealogy/region/{regionCode}
-```
-
-其中 `search.keyword` 必填;`search.level`、`search.limit` 可选;其余 `regionCode` path 参数必填,`children.parentCode` 可选。G03 原先错误使用了 `/genealogy/app/region/children`,已改为正式路径并在 H5 浏览器验证省、市、区三级均返回业务 `code:200`。其余 3 个 operation 尚无当前页面交互入口,待桌面 Apifox 补齐可消费的响应 DTO 后按实际页面需求接入;不会以 `additionalProperties` 的导出占位结构猜字段。
-
-## 十一、2026-07-26 F03 真实点赞后缺少当前用户状态
-
-测试账号通过 F03 动态详情页面执行了一次真实“点赞”(没有执行取消点赞或其他删除操作):
-
-```text
-POST /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/likes
-```
-
-该请求返回 `HTTP 200`。随后页面重新读取详情,`likeCount` 从 `0` 变为 `1`,说明服务端已写入点赞;但详情响应没有给出可用的当前用户点赞状态,前端读取到的 `likedByMe` 仍为 `false`/缺失,按钮继续显示“点赞”而不是“取消点赞”。
-
-这不是前端可以用本地布尔值补齐的缺口:页面刷新后必须以服务端状态决定下一次应该调用 `POST /likes` 还是 `DELETE /likes`。当前合同会导致重复点击语义不明确,也无法安全展示已点赞状态。
-
-请后端在以下 APP 读取 DTO 中统一提供当前登录用户维度的必填布尔字段 `likedByMe`(或同义且明确的字段),并与点赞写入立即一致:
-
-```text
-GET /genealogy/app/genealogies/{genealogyId}/feeds
-GET /genealogy/app/genealogies/{genealogyId}/feeds/page
-GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}
-```
-
-字段必须是 `boolean`,不能以点赞总数、空值或仅他人点赞记录代替。后端发布后,前端会再从 F03 页面验证“点赞 → 详情回读为已点赞 → 仅在用户主动操作时取消点赞”的完整闭环。
-
-前端已将缺失/非布尔值保留为“状态未知”,并在 F03 禁用点赞按钮、显示明确原因;不会再把它转换为 `false` 后重复发送点赞请求。
-
-## 十二、2026-07-26 谱文分类列表缺少可消费的条目 DTO
-
-桌面 Apifox 的正式 operation 为:
-
-```text
-GET /genealogy/app/genealogies/{genealogyId}/article-categories
-```
-
-请求仅要求 path `genealogyId`(以及认证 `clientid`),成功响应在当前桌面文档中标注为通用 `ListResult`,没有声明列表项字段模型、字段示例或 `categoryId` 的类型。F06 的创建谱文请求可选 `categoryId`,但前端不能在不知道“分类标识”和“分类展示名”字段的情况下把任意对象渲染成选择器。
-
-请后端把该 operation 的 `data[]` 明确为具名 DTO,至少包含:
-
-| 字段 | 合同要求 |
-| --- | --- |
-| `categoryId` | 稳定分类标识;若为 int64,APP JSON 统一使用十进制字符串 |
-| `categoryName` | 非空展示名称 |
-| `status` / `enabled` | 明确是否允许在新建谱文中选择;若不需要则明确只返回可选项 |
-| `sortOrder` | 可选的稳定排序字段;若服务端已排序则在文档明确 |
-
-在条目 DTO 发布前,F06 继续允许按现有创建合同不带 `categoryId` 发布,不会把导出文件里的通用对象或本地硬编码分类当作真实分类数据。
-
-## 十三、当前全部已确认阻塞总表
-
-本表是当前 APP 136 operation 审计的唯一汇总入口;详情、请求字段和回传模板见本文件对应章节,以及 `APP-136请求参数字段核对表-2026-07-26.md`。这里的“阻塞”不等于前端缺少调用代码:可能是 operation 根本不存在、响应 DTO 无法消费、服务端真实失败,或 H5 不存在安全参数来源。
-
-| 编号 | 类别 | operation / 合同 | 影响页面 | 已验证事实 | 后端解除条件 |
-| --- | --- | --- | --- | --- | --- |
-| B01 | 缺 operation | 视频仅有 `DELETE /videos/{videoId}` | F10 | 无列表、详情、播放地址、创建、上传、编辑等 owner | 发布视频读取与发布完整 operation/DTO |
-| B02 | 缺 operation | 人生大事无资源 owner | R09 | 族务目录只有成长、备忘、亲友、功德 | 明确人物专属或家谱公共归属后发布列表/详情/写入 DTO |
-| B03 | 缺 operation | 通知仅有列表和标已读 | N02 | 无 `notificationId` 单条详情读取 | 发布单条详情读取及授权/错误语义 |
-| B05 | 安全链路缺失 | `PUT /auth/phone` | M05 | 只有最终 PUT,缺经确认的当前账号读取、TAC/发码闭环 | 发布专用换绑验证合同与读 DTO;敏感写入仍需人工测试许可 |
-| B06 | 服务端异常 | `POST /genealogies/{genealogyId}/lineage/persons` | T03–T08、R01–R02 | 2026-07-26 从 T04 页面分别以最小首位成员数据、以及包含编号/示例字典值/排序/生卒信息/简介备注的全字段资料真实提交,均为 HTTP `200` 但业务 `code:500 / 发生未知异常`,未生成本地或伪造 `personId`;同谱只读 `GET .../lineage/persons/options` 实测 `200 / data: []`,因此也没有可读取的真实人物候选 | 修复最小合法 body,返回并可读取真实 `personId` |
-| B08 | ID 类型冲突 | 上传 complete 与所有消费 `ossId` 的 DTO | F02/F06/F07/F09/G03/G11/R04/R07/R08/R10/T04/M02 | 真实 complete 返回 19 位字符串,消费者声明 `int64` number | APP JSON 统一十进制字符串 `ossId`;同版更新示例与所有消费者 |
-| B09 | 候选 ID 缺失 | `PUT .../ceremonies/{ceremonyId}/invitees` | R06/R07、我的邀请入口 | body 需要 `inviteeUserIds`,现有 member/person DTO 无同类型候选 | 公开 `appUserId` 对应关系或新增可邀请用户候选 operation |
-| B10 | 当前用户状态缺失 | 动态列表/分页/详情 `likedByMe` | F03 | 实际点赞后数量变更,详情未给当前用户布尔状态 | 三个读取 DTO 均返回同步的 required boolean `likedByMe` |
-| B11 | 条目 DTO 缺失 | `GET .../article-categories` | F06 | 只有通用 `ListResult`,无分类 ID/名称/状态/排序字段 | 发布 `categoryId`、`categoryName`、可选状态与排序 DTO |
-| B12 | 页面交互待确认 | 行政区划 path/search/detail | G03/G11 后续回填、搜索 | 2026-07-26 复测已返回 `value`、`label`、`regionCode`、层级等真实条目;但当前产品页面没有搜索/路径回填入口 | 产品确认地区搜索与路径回填交互后接入页面;接口 DTO 不再阻塞 |
-| B13 | 资源语义不能混用 | `members` 与 `lineage/persons` | 成员管理、R06/R07 | `memberId`、`personId`、`appUserId` 是不同资源,当前无独立成员管理页 | 提供成员管理页需求与稳定候选/映射 DTO,不得前端猜代 |
-| B14 | 业务绑定 owner 缺失 | `POST /files/reference` | 所有附件业务 | 需要 `bizTable`、`bizId`、`bizField`,页面没有可信业务表/字段来源 | 后端为各业务资源声明文件绑定 owner,或明确由创建 DTO 原子绑定 |
-| B15 | 枚举/候选缺失 | 多个 body 中的 `sex`、`birthLunar`、`deathLunar`、`personStatus`、`roleType`、`status`、`payType` 等 | T04/T05 及 T/M/G/R/F 写入扩展 | 2026-07-26 复核 `LineagePersonBody`:`birthLunar`、`deathLunar` 的含义是“日期是否农历”的项目字典值,不是农历日期文本;性别和人物状态也都是字典值。导出与桌面 Apifox 只给出示例 `0`,没有 value-label 枚举或字典 options operation,因此不能把输入框、农历日期文本或猜测的 `0/1` 映射留给用户 | 在 operation 详情给出完整 value-label enum,或发布字典 options operation;前端收到确定合同后统一改为选择器,并同步详情页的字典值展示 |
-| B16 | 测试边界,不是接口缺失 | 短信、改密、换绑、注销、退出、删除、审核、支付 | A/M/G/F/R/N 全域 | 当前任务禁止执行这些敏感动作 | 仅在用户另行授权、测试账号与可回收数据齐备后执行真实写入 |
-| B17 | 导出与实际校验冲突 | `POST /genealogy/app/files/resumable/init`(并影响 complete) | F02/F06/F07/F09/G03/G11/R04/R07/R08/R10/T04/M02 | 2026-07-26 真实 H5 上传:省略 `uploadId` 返回“上传ID不能为空”;以导出字段 `fileSize` 替代 `totalSize` 返回“文件大小不能为空”。实际可用请求为 `uploadId + totalSize`;秒传 `instant:true` 会合法返回 `uploadId:null` 与真实 `ossId` | 在桌面 Apifox 与可导出 OpenAPI 中统一请求/响应 DTO、required、示例及秒传分支;明确普通分片与秒传的 `uploadId` 可空规则 |
-
-## 十四、真实浏览器请求与返回记录(供后端排查)
-
-说明:以下均在测试账号、测试家谱中从 APP 页面发起;未记录账号密码、令牌或完整 `clientid`。所有请求均已携带运行时 `clientid`、测试账号登录态和 `genealogyId=2081191846772518914`。
-
-### 1. B06:首位成员创建
-
-接口:
-
-```text
-POST /genealogy/app/genealogies/2081191846772518914/lineage/persons
-```
-
-最小请求(2026-07-26,页面 T04):
-
-```json
-{
- "name": "首位成员最小请求验证",
- "generation": 1
-}
-```
-
-实际返回:
-
-```text
-HTTP 200
-{"code":500,"msg":"发生未知异常,请联系管理员","data":null}
-```
-
-页面结果:`保存失败 / 首位成员尚未保存 / 发生未知异常,请联系管理员`。
-
-后端称已修复后的复测(2026-07-26,重新登录测试账号后从 T04 提交):
-
-```json
-{
- "name": "后端修复验证首位成员",
- "generation": 1
-}
-```
-
-返回仍为:
-
-```text
-HTTP 200
-{"code":500,"msg":"发生未知异常,请联系管理员","data":null}
-```
-
-因此 B06 仍未解除;本次不是会话过期导致的结论。首次请求得到 `code:401` 后已通过 A01 真实密码登录,重试才得到上述业务 `code:500`。
-
-全字段诊断请求(同一页面、同一测试家谱;用于验证可选字段是否会改变异常,不是字段字典的最终验收):
-
-```json
-{
- "name": "LineageFullBody0726",
- "generation": 1,
- "personNo": "P20260726001",
- "sex": "0",
- "generationName": "FullGen",
- "aliasName": "FullBodyAlias",
- "birthLunar": "1900-01-01",
- "birthPlace": "TestBirthPlace",
- "deathLunar": "2000-01-01",
- "deathPlace": "TestDeathPlace",
- "burialPlace": "TestBurialPlace",
- "biography": "Full body browser submission verification",
- "remark": "test only",
- "personStatus": "0",
- "birthDate": "2026-07-26",
- "deathDate": "2026-07-26",
- "sortOrder": 1
-}
-```
-
-实际返回同样为:
-
-```text
-HTTP 200
-{"code":500,"msg":"发生未知异常,请联系管理员","data":null}
-```
-
-特别说明:该诊断请求暴露出旧页面把 `birthLunar`、`deathLunar` 当作农历日期文本;Apifox 的真实语义是“是否农历”的字典值。不能把这一请求视为正确字典值示例,也不能要求前端据此猜选项。首位成员不应伪填 `fatherId`、`motherId`、`relationName`;`appUserId` 没有同类型候选,`avatarOssId` 被 B08 阻断。
-
-随后读取:
-
-```text
-GET /genealogy/app/genealogies/2081191846772518914/lineage/persons/options
-HTTP 200 / code:200 / data: []
-```
-
-因此 T01 没有成员数据并非前端空白占位:服务端尚未成功写入任何真实成员。
-
-### 2. 初次验证记录(历史结果;以 2.1 的复测结论为准)
-
-| 编号 | 接口与页面 | 实际请求值/返回值 | 结论 |
-| --- | --- | --- | --- |
-| B07 | `GET /genealogy/app/genealogies/{genealogyId}/feeds/page`,F01/F03 | 已按页面分页参数真实读取;HTTP `200`、业务 `code:200`,但响应没有 Apifox `PageResult` 所需的 `data.rows`、`data.total` | 无法安全分页或把空对象伪装为无动态 |
-| B08 | `POST /genealogy/app/files/resumable/init`,F09 等上传页面 | 省略 `uploadId`:返回“上传ID不能为空”;将 `totalSize` 改为导出字段 `fileSize`:返回“文件大小不能为空”;实际可用字段为 `uploadId`、`fileName`、`fileMd5`、`totalSize`、`totalChunks`、`chunkSize`。秒传返回 `{"uploadId":null,"instant":true,"ossId":"2081232520259612673"}` | 文件服务返回 19 位字符串 ID,而业务 DTO 写 `int64` 数字,前端不能无损作为 JSON 数字提交 |
-| B10 | 动态点赞,F03 | 已真实点赞,点赞数量变化;详情/列表未返回 `likedByMe` | 不能据数量推断当前用户是否已点赞,页面已禁用不确定状态下的再次写入 |
-| B11 | `GET /genealogy/app/genealogies/{genealogyId}/article-categories`,F06 | HTTP `200`、业务 `code:200`、`data: []` | 无分类候选可供选择;同时合同没有分类条目字段定义 |
-| B12 | 行政区划 children,G03/G11 | `GET /genealogy/region/children` 已可真实读取;path/search/detail 没有可消费的条目 DTO 和页面交互归属 | 不猜地区回填字段或新增搜索行为 |
-| B17 | 分片上传初始化,F09 等 | 见 B08 的实际请求和返回;导出与服务端校验字段冲突 | Apifox 与导出必须先统一为唯一合同 |
-
-### 2.1 后端称修复后的复测结果(2026-07-26)
-
-| 编号 | 复测结果 | 当前结论 |
-| --- | --- | --- |
-| B06 | 重新登录后,T04 最小 body 仍返回 HTTP `200`、业务 `code:500`、`data:null` | 未修复 |
-| B07 | `GET .../feeds/page?pageNum=1&pageSize=20` 现在返回根级 `total:1` 和 `rows:[...]`,不再是空 envelope | 分页数据已出现;但 `likedByMe` 返回字符串 `"1"`,B10 仍未修复 |
-| B08 | F09 从真实图片文件上传到“已上传”成功;保存照片时前端收到真实 19 位文件 ID 后仍报“超出 APP 安全整数范围”,未发出照片创建请求 | 未修复,需统一字符串 `ossId` 合同 |
-| B09 | 礼仪列表可读取,`GET .../ceremonies/{ceremonyId}/invitations` 与 `GET .../ceremony-invitations/mine` 均返回 `data:[]`;没有可提交的 `inviteeUserIds` 候选 | 未修复,仍缺 `appUserId` 候选/映射 |
-| B11 | 谱文分类仍返回 `HTTP 200 / code:200 / data:[]` | 测试谱没有分类;仍需分类 DTO 与可用测试候选才能验证选择/写入 |
-| B12 | `GET /genealogy/region/path/110101`、`GET /genealogy/region/110101`、`GET /genealogy/region/search?keyword=北京&limit=10` 均返回包含 `value`、`label`、`regionCode`、层级等字段的真实数据 | 后端已补齐可消费条目;待产品确认搜索/回填交互后接入页面 |
-
-### 2.2 世系人物身份认领合同增补(2026-07-27)
-
-后端新增 `bindingMode`,所有 T04/T05 人物新增、修改及父母/子女/兄弟姐妹/配偶关系写入统一使用:
-
-- `NONE`:不绑定账号,禁止提交 `appUserId`。
-- `SELF`:绑定当前登录账号,禁止提交 `appUserId`,后端从 Token 获取。
-- `SPECIFIED`:绑定指定业务用户,必须提交 `appUserId`。
-
-页面已默认 `NONE` 并移除“自动读取 profile.userId 后提交”的旧路径。真实 `POST .../children` 已按 `bindingMode:"NONE"`、无 `appUserId` 发出,但仍收到 HTTP `200` / envelope `code:500` / `发生未知异常,请联系管理员`,人物未落库。B06 在新版合同下仍未闭环;需后端确认新包部署状态并给出该异常的业务原因。
-
-### 3. 未发起写入请求的原因(不是漏测)
-
-| 编号 | 接口/功能 | 未发起的原因 | 后端需要提供 |
-| --- | --- | --- | --- |
-| B01 | 视频 F10 | 仅发布删除接口;没有列表、详情、播放、创建、编辑或上传 owner | 完整资源 operation 与 DTO |
-| B02 | 人生大事 R09 | 没有资源 operation | 明确人物或家谱归属后的列表、详情、写入 DTO |
-| B03 | 通知详情 N02 | 只有列表、标已读;没有按 `notificationId` 读取详情 | 单条详情接口及授权语义 |
-| B05/B16 | 短信、改密、换绑、退出、注销、删除、审核、支付 | 属于本轮明确禁止的敏感动作 | 另行授权、测试账号和可回收数据后再测 |
-| B09/B13 | 礼仪受邀人、成员绑定 | 请求需要 `appUserId`,现有 `memberId`、`personId`、`appUserId` 不能互相替代;没有候选映射 | 同类型候选接口或稳定映射 DTO |
-| B14 | 文件业务引用 | 请求需要 `bizTable`、`bizId`、`bizField`,没有页面可信 owner | 各资源的文件绑定归属合同 |
-| B15 | 性别、人物状态、出生/逝世是否农历等 | 需要选择器,但 Apifox 仅给示例 `0`,没有枚举、中文标签或字典 options 接口 | value-label 枚举或字典 options operation |
-
-
-### 不应误标为阻塞的已完成项
-
-- A01 密码登录、G03 创建家谱、家族动态/评论、谱文、相册、亲友往来、礼仪、成长记录、备忘、功德均已做过真实创建后的列表或详情回读。
-- M03 账号与安全已真实读取当前 profile,并仅展示掩码手机号、账号编号和账号状态;设备与登录记录不在当前页面范围内。
-- 4 条行政区划 operation 都已有 API owner;`children` 已在 G03/G11 页面真实读取,其余三条的阻塞是没有可安全消费 DTO/产品交互,不是路径不存在。
-- 136 条 `method + path` 均可在桌面 Apifox 当前目录找到;数量差异不是“导出漏了 path”,而是页面数、功能入口、DTO 和安全参数来源不同。
diff --git a/docs/家谱项目全量治理实施计划.md b/docs/家谱项目全量治理实施计划.md
deleted file mode 100644
index a155782..0000000
--- a/docs/家谱项目全量治理实施计划.md
+++ /dev/null
@@ -1,1727 +0,0 @@
-# 家谱项目全量治理实施计划
-
-> **执行要求:** 实施时使用 `superpowers:executing-plans` 按任务顺序执行,并在每个批次结束后由主代理和两位只读评审者三人复核;宣称批次或阶段完成前必须使用 `superpowers:verification-before-completion`。步骤使用复选框跟踪。用户已明确授权三人依据证据直接确定技术方案,不再为可从页面、接口和现有合同推出的细节反复请示。
->
-> 日期:2026-07-22
-> 状态:阶段 0、导航任务 1—10、TAC 认证客户端任务 20—22、领域上下文任务 24 与 M07 反馈客户端任务 25 已完成;任务 26—39 已逐域完成工作区、帮助、资料、通知、退出、密码、换绑、G03、普通加入、邀请码直入、G11 设置与 G12 字辈集合的三人审查及 OpenAPI 红灯;任务 40 正在审查 F01/F03 家族动态列表、详情与一级评论读取边界。这些后端门禁和 MuMu 原生矩阵仍明确阻塞,继续后续无依赖业务域接口审查
-
-**目标:** 以测试先行方式消除全项目导航栈歧义,完成可安全上线的认证闭环,并在新后端图窗口合同通过后,把 T01 建成可稳定阅读几十代、几百代且连接线连续的大规模世系图;随后逐域关闭真实接口、领域持久化、无障碍与发布门禁。
-
-**架构:** 导航阶段由 `utils/navigation-routes.js` 持有活动路由语义、`utils/navigation.js` 持有全部 Uni 导航调用。T01 先锁定 Apifox 规范图窗口合同,再按“规范化与校验 → 可见投影 → 布局 → Scene 与空间索引 → 单 Canvas 视口 → 页面交互”实施。认证由场景合同、TAC 浮层、供应商适配器和 HTTP owner 四层组成;所有阶段各有独立硬门禁,外部接口红灯只阻止其消费者上线,不阻止无依赖业务域继续审查。
-
-**技术栈:** UniApp、Vue 3、JavaScript、SCSS、PowerShell、Node.js、OpenAPI 3.0.1、Apifox、MuMu Android、ADB、App-vue renderjs、Canvas 2D。
-
-## 全局约束
-
-- 全程使用中文沟通;当前五份权威文档继续使用中文文件名和中文内容,不新增并行计划入口。
-- 新增或修改的复杂 JavaScript、Vue、SCSS 和测试逻辑必须有详细中文注释,说明当前步骤、输入、状态变化、失败处理与下一步;注释不得掩盖职责混乱的大函数。
-- 代码只实现当前合同需要的最小能力;不得复制路由、参数、图关系、布局或密码规则,不建立“以后也许有用”的抽象。
-- 主代理负责唯一写入;Lagrange 与 Bernoulli 均完整复核页面美观、业务、接口、交互、测试和 MuMu 证据,三人互相补漏,不割裂成三个单项岗位。
-- 不新增第四位代理,不创建新的专家角色。
-- 不执行 Git add、commit、push、restore、checkout、reset 或其他 Git 变更命令。
-- 不改写 `APP.openapi.json` 与 `APP.openapi.yaml`;Apifox 是接口唯一源头,两份本地文件只接受用户重新导出覆盖。
-- 不启动、关闭 MuMu,不调整模拟器窗口缩放比例、设备分辨率、方向或系统字体;只使用当前 `emulator-5554 / 720×1280 / 320dpi`。T01 页面内双指缩放属于必须验证的产品功能,不属于调整模拟器。
-- 浏览器运行时测试可以验证逻辑,但不能替代 MuMu 视觉和真实 Android 返回验收。
-- 每次代码修改后依次运行本任务聚焦合同、`tests/project-responsive-layout-contract.ps1`、`tests/compile-audit.ps1`,再在 MuMu 复核受影响流程;阶段关闭前运行全部 `tests/*.ps1`。
-- 不重新进行响应式迁移,不对单一尺寸写页面补丁,不压缩字号、行高或控件尺寸掩盖问题。
-- 普通内容高度由内容决定;弹窗只允许视口 `max-height` 和内部滚动。
-- G01—G10 只有在本阶段测试或 MuMu 提供明确全局回归证据时才改动,且只改与当前阶段直接相关的行。
-- 用户可见页面提示使用“某某某堂侄”等通用表达;fixture 与 mock 中的姓名不做无关清理。
-- 导航阶段允许只迁移 T01 的现有导航调用;导航门禁通过前,不得实施 T01 新图合同、投影、布局、Scene、Canvas 或新接口接入。导航门禁关闭后,各业务域必须保持独立批次;T01 或认证因后端合同阻塞时,可以继续不依赖该合同的接口审查和客户端批次,但不得伪造服务端成功或混合所有权。
-
-## 阶段硬门禁
-
-1. **导航门禁:** 页面和活动组件直接调用五种 Uni 导航 API 的扫描为零,52 条注册路由精确闭合,导航全量合同通过,MuMu 完成进入、返回、取消、完成和重复进入矩阵。
-2. **T01 接口门禁:** 用户重新导出的 JSON/YAML 同时包含规范 `LineageGraphWindow`、概览和定位接口,图合同测试通过;当前递归合同不得由客户端兼容。
-3. **T01 几何门禁:** 103→106、普通节点 4rpx 间隙和 10×12 多父干线三个已知缺陷先红后绿,十条“连线永不断”不变量全部自动验证。
-4. **阶段隔离:** 任一门禁未通过时只修复本阶段问题,不提前混入下一阶段代码。
-5. **认证后端门禁:** `API-AUTH-TAC-001`—`004` 关闭、同版本 JSON/YAML 通过 `tests/auth-tac-openapi-contract.ps1`、真实 challenge 不再空 500,才允许把 `runtimeConfig.mode` 改为 `remote`。
-6. **认证 Android 发布门禁:** 非拖动等价验证、真实票据原子消费和三人 MuMu/TalkBack/外接键盘证据齐全,`tests/auth-android-accessibility-release-gate.ps1` 才能由 `ANDROID-AUTH-ACCESSIBILITY-RELEASE BLOCKED` 转绿。
-
-## 文件职责图
-
-### 导航阶段新增
-
-- `utils/navigation-routes.js`:52 条活动路由的唯一语义注册表。
-- `utils/navigation.js`:唯一 Uni 导航网关、一次性结果和统一返回优先级。
-- `tests/navigation-routes-contract.ps1`:注册表、`pages.json`、参数和唯一所有权合同。
-- `tests/navigation-gateway-runtime-smoke.js`:在伪造 Uni 栈上验证网关算法。
-- `tests/navigation-source-scan-contract.ps1`:禁止页面和组件直接调用五种 Uni 导航 API。
-- `tests/navigation-flow-contract.ps1`:锁定各页面使用的语义方法与流程终点。
-
-### 导航阶段修改
-
-- `components/AppTabbar.vue`、`components/PageHeader.vue`、G01/F01/M01 三个根页消费者。
-- `pages/auth/*.vue`、`pages/genealogy/*.vue`、`pages/tree/*.vue`、`pages/family/*.vue`、`pages/records/*.vue`、`pages/notification/*.vue`、`pages/profile/*.vue` 中实际包含导航行为的文件。
-- 与上述行为直接对应的现有聚焦合同;旧的 `fallbackUrl`、原始 URL 和直接 Uni 调用断言必须同轮删除。
-
-### T01 阶段新增
-
-- `utils/lineage/normalize.js`:只把新图窗口响应规范化为内部图;不兼容旧递归结构。
-- `utils/lineage/validate.js`:图引用、主入边、版本、边界和 ID 的唯一运行时校验。
-- `utils/lineage/project.js`:从完整规范图生成当前可见真实节点与虚拟聚合节点,不修改源图。
-- `utils/lineage/layout.js`:消费可见投影的确定性 family-unit tidy-tree 世界坐标布局。
-- `utils/lineage/scene.js`:把布局转换为节点、文字、端点和连接器 Scene。
-- `utils/lineage/spatial-index.js`:视口裁剪、命中测试和路径穿越查询。
-- `utils/lineage/camera.js`:相机矩阵、LOD、缩放锚点和边界计算。
-- `components/LineageViewport.vue`:App-vue/H5 renderjs 与 mp-weixin Canvas 适配器;节点与线同画布、同矩阵、同帧。
-- `components/LineageAccessibleList.vue`:消费同一规范图的可搜索线性阅读模式。
-- `tests/lineage-graph-contract-runtime-smoke.js`、`tests/lineage-projection-runtime-smoke.js`、`tests/lineage-layout-runtime-smoke.js`、`tests/lineage-scene-runtime-smoke.js`、`tests/t01-navigation-integration-contract.ps1`、`tests/t01-large-lineage-contract.ps1`。
-
-### T01 阶段修改
-
-- `utils/api.js`、`data/mock.js`、`pages/tree/t01-tree-overview.vue`。
-- `pages/tree/t03-member-profile.vue`、`pages/tree/t04-add-relative.vue`、`pages/tree/t06-edit-relationship.vue`、`pages/tree/t07-member-directory.vue` 只修改新版本和焦点回流所必需的部分。
-- 现有 `tests/t01-*.ps1`、`tests/t01-*.js` 中已经被新图合同替代的断言。
-
-## 每个代码批次的固定验证
-
-```powershell
-powershell -ExecutionPolicy Bypass -File tests/navigation-routes-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/project-responsive-layout-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/compile-audit.ps1
-```
-
-第一行以任务中明确列出的聚焦合同为准;上例是任务 1 的实际命令,其他任务均在各自步骤写出精确文件名。
-
-阶段关闭时运行:
-
-```powershell
-$failed = @()
-Get-ChildItem -LiteralPath tests -File -Filter '*.ps1' | Sort-Object Name | ForEach-Object {
- & powershell -ExecutionPolicy Bypass -File $_.FullName
- if ($LASTEXITCODE -ne 0) { $failed += $_.Name }
-}
-if ($failed.Count -gt 0) { throw "失败合同:$($failed -join ', ')" }
-```
-
----
-
-## 第一阶段:导航栈语义统一
-
-### 任务 1:建立路由语义注册表
-
-**文件:**
-
-- 新建:`utils/navigation-routes.js`
-- 新建:`tests/navigation-routes-contract.ps1`
-- 修改:`tests/interface-page-mapping-contract.ps1`
-
-**接口:**
-
-- 输出:`ROUTES`、`ROOT_ROUTE_KEYS`、`getRoute(routeKey)`、`getRouteKeyByPath(path)`。
-- 路由项:`{ path, kind, parent, parentParamMap, requiredParams, optionalParams, allowedSources, resultOperations }`;所有数组和映射均冻结。
-- 路径统一以 `/pages/...` 表示;ID 参数均为字符串;`sourceKey` 是网关保留参数,不进入页面业务参数数组。
-
-`utils/navigation-routes.js` 已成为 52 个活动页面路由语义的唯一数据所有者;实施计划、页面、测试和映射总表都不得再维护完整父页、参数、来源或结果操作影子表。注册表路径和编号由 `pages.json` 独立交叉,具体字段只在该模块修改。
-
-独立验收只保留不能由错误注册表自证的高风险边界:
-
-- 根语义固定为 A01、G01、F01、M01;A01 是认证根,其余三个是业务根。
-- T03 是唯一单实例页面;人物页回 T01 的行为必须把子页 `personId` 映射为父页 `selectedId`。
-- 所有父链无环并落到四根之一;所有非根页面可从四根沿允许来源到达。
-- ID 和业务参数只接受非空字符串;`sourceKey` 是网关保留参数,旧 URL、快照和领域对象不得进入查询。
-- 目标结果操作只从注册表读取;未声明的操作由运行时立即拒绝。
-
-- [x] **步骤 1:先写失败合同**
-
-`tests/navigation-routes-contract.ps1` 必须读取 `pages.json` 与 `utils/navigation-routes.js`,断言 52 个路径集合和顺序精确相等、四个根语义恰为 A01/G01/F01/M01、父页与来源均存在、参数名不重复、`parentParamMap` 两端字段都合法、`resultOperations` 在目标页内唯一且非空字符串,并禁止 `previous`、`returnUrl`、`fallbackUrl`、`targetUrl`、`state`、`count`、`saveResult`、`step`、`genealogyName` 进入业务参数。
-
-- [x] **步骤 2:确认红灯原因正确**
-
-运行:
-
-```powershell
-powershell -ExecutionPolicy Bypass -File tests/navigation-routes-contract.ps1
-```
-
-首次运行记录:因 `utils/navigation-routes.js` 不存在而按预期失败,不是 PowerShell 语法或编码失败;当前 owner 已实现并转绿。
-
-- [x] **步骤 3:实现最小注册表**
-
-实现只保留一个冻结注册表和两个严格字符串查询函数。四根安全 oracle 固定为:
-
-```js
-export const ROOT_ROUTE_KEYS = Object.freeze(["A01", "G01", "F01", "M01"]);
-```
-
-`defineRoute` 必须冻结路由项、四个数组和 `parentParamMap`;`getRoute` 只接受原始字符串和对象自身键,`getRouteKeyByPath` 只接受原始字符串路径。52 项具体内容以 `utils/navigation-routes.js` 为准,计划不再保存可漂移的代码快照。
-
-- [x] **步骤 4:验证绿灯并检查旧合同迁移**
-
-运行路由合同、接口页面映射合同、全局响应式合同与编译审计。预期全部通过;`tests/interface-page-mapping-contract.ps1` 不再把旧代际父键布局或“阶段 1 尚未开始”作为当前真相。
-
-### 任务 2:建立唯一导航网关
-
-**文件:**
-
-- 新建:`utils/navigation.js`
-- 新建:`tests/navigation-gateway-runtime-smoke.js`
-
-**接口:**
-
-- 消费:任务 1 的 `ROOT_ROUTE_KEYS`、`getRoute()`、`getRouteKeyByPath()`;具体路由数据只经注册表查询函数读取。
-- 输出:`buildRouteUrl`、`openPage`、`goBack`、`returnTo`、`finishPage`、`goRoot`、`consumeNavigationResult`、`resolveBackAction`、`runBackGuard`、`handleBackPress`。
-- 一次性结果唯一形状:`{ operation, entityId?, refresh }`;字段集合必须精确,`operation` 必须属于目标路由 `resultOperations`,多余字段立即抛错。
-- `buildRouteUrl`、`consumeNavigationResult`、`resolveBackAction` 与 `handleBackPress` 同步返回;`openPage`、`goBack`、`returnTo`、`finishPage`、`goRoot` 与 `runBackGuard` 始终返回 `Promise`,并通过同一个转场锁保证一次只调用一个 Uni 导航 API,校验失败也只使用 Promise 拒绝这一种错误通道。
-
-- [x] **步骤 1:先写伪栈运行时测试**
-
-`tests/navigation-gateway-runtime-smoke.js` 以独立 ESM 实例注入伪 `uni` 与 `getCurrentPages`,至少验证:
-
-```js
-assert.equal(buildRouteUrl("T03", { genealogyId: "9007199254740993", personId: "p/1" }, "T01"),
- "/pages/tree/t03-member-profile?genealogyId=9007199254740993&personId=p%2F1&sourceKey=T01");
-assert.throws(() => buildRouteUrl("T03", { genealogyId: "1", personId: 2 }, "T01"), /personId/);
-assert.throws(() => buildRouteUrl("T03", { genealogyId: "1", personId: "2", targetUrl: "/x" }, "T01"), /targetUrl/);
-const firstOpen = openPage("T03", { genealogyId: "1", personId: "2" }, "T01");
-const repeatedOpen = openPage("T03", { genealogyId: "1", personId: "2" }, "T01");
-assert.equal(firstOpen, repeatedOpen); // 同一 tick 复用在途 Promise,只发生一次 navigateTo
-assert.deepEqual(consumeNavigationResult("TEST_RESULT_LIST"), { operation: "fixture-created", entityId: "a9", refresh: true });
-assert.equal(consumeNavigationResult("TEST_RESULT_LIST"), null); // 只消费一次;该中性路由只存在于测试内存源码
-```
-
-同时构造目标在栈内、目标不在栈内、栈深 1、根页切换、非法来源、提交中和未保存确认六组场景,并补齐以下反例:当前真实页 G01 伪报 `sourceKey=T07` 必须失败;外部直接链接即使带合法 `sourceKey` 也只能按规范父页回退;同一 tick 两次打开同一目标只调用一次 `navigateTo`;`operation="anything"`、空 `entityId`、非布尔 `refresh` 和额外字段都失败。
-
-- [x] **步骤 2:运行并确认红灯**
-
-首次运行记录:`node tests/navigation-gateway-runtime-smoke.js` 因 `utils/navigation.js` 不存在而按预期失败;当前 owner 已实现,严格运行时反例已转绿。
-
-- [x] **步骤 3:实现 URL 和参数校验**
-
-参数与结果校验只由 `utils/navigation.js` 的同一数据记录快照器拥有,计划不复制可漂移实现。运行时合同固定为:
-
-- 只接受原型为 `Object.prototype/null` 的普通对象;只读取 own enumerable data properties,拒绝 Symbol、访问器、不可枚举字段和继承字段;校验、编码、比较与结果写入始终消费同一冻结快照。
-- 注册表声明的必填与可选参数只要实际提供,就必须是非空字符串;额外字段立即失败。栈内目标实例也只投影注册表字段后按完整必填合同校验,不能信任畸形历史页面。
-- `sourceKey=""` 是构造纯目标 URL 时唯一的省略形态;`openPage` 必须提供非空字符串来源。`null/false/0/NaN` 不能借 truthy 判断绕过验证。
-- 查询串只按注册表 `requiredParams` 后 `optionalParams` 的声明顺序逐项 `encodeURIComponent`;调用方插入顺序、字母序和运行环境是否提供 `URLSearchParams` 都不得改变结果。
-- `navigationResults` 和唯一 `navigationInFlight` 锁只存在于网关模块;所有校验错误必须在调用 Uni API 前发生。
-
-`buildRouteUrl` 只负责纯字符串构造;真正执行压栈导航前,`openPage` 必须读取当前栈顶路径,并断言 `sourceKey === getRouteKeyByPath(当前真实页面)`。页面不得通过省略来源或传入另一个合法来源绕过注册表。栈深为 1 时一律忽略当前 URL 查询中的 `sourceKey`,只使用注册表 `parent/parentParamMap`;`sourceKey` 不得成为外部深链的可信合同。
-
-查询串固定按注册表字段顺序逐键 `encodeURIComponent`,不依赖 Uni 运行环境可能缺失的 `URLSearchParams`,不引入依赖、不复制到页面。等价参数对象即使插入顺序不同,也必须生成同一 URL 和同一转场锁键。
-
-转场锁固定为“同一语义键复用同一个 Promise、不同语义在转场结束前以 Promise 返回 `false`”,不能用页面各自的布尔锁。取得新锁、写入结果、调用 Uni、成功目标实例校验、同步异常回滚和异步失败回滚必须属于同一个原子协议;`success/fail` 在 Promise settle 前按独立 flight 身份释放自己的锁,迟到的 `complete` 不得清掉新 flight。成功回调发现实际栈顶不是预定实例/参数时也必须拒绝并先回滚,不能只处理 Uni 的 `fail`。
-
-- [x] **步骤 4:实现五种语义导航**
-
-实现顺序固定为:先把调用方目标参数规范化为快照并完成来源校验,再读取当前真实栈,最后决定唯一 Uni 调用。`openPage` 对普通页只允许压栈,对 single 页先检查完整既有实例;`goRoot` 只接受四根并在路由与规范参数均相同时返回 Promise 化的 `false`。具体实现只由 `utils/navigation.js` 拥有,计划不复制第二份函数源码。
-
-`goBack()` 在栈深大于 1 时只执行受转场锁保护的 `navigateBack({ delta: 1 })`;栈深为 1 且当前是普通页时忽略 URL 中的 `sourceKey`,只按规范父页、同名参数和 `parentParamMap` 构造父页参数。某级父页缺必填参数时继续沿注册表父链向上,直到第一个可合法构造的目标;例如缺 `genealogyId` 的异常 T03 不能伪造 T01/G05,最终回 G01。当前已是 A01/G01/F01/M01 根语义时返回 `false`,由 Android 系统处理退出,不伪造跨 Tab 历史。
-
-当前路由合同没有任何“同流程临时步骤”替换边,原 14 处 `redirectTo` 也都归入根切换、规范返回或父链回退,因此网关不公开无消费者的 `replaceStep`。`redirectTo` 只作为 `goBack/returnTo/finishPage` 的内部实现细节;未来若出现真实替换流程,必须先在唯一注册表增加专用替换边和失败合同,再同轮新增公开语义。
-
-`returnTo(routeKey, targetParams = {})` 从当前页下方按路由键反向寻找最近实例;找到后不再按参数搜索另一个实例,但调用方显式提供的每个字段必须与这个最近实例一致,冲突立即拒绝,空对象仍允许普通返回。只有目标不在栈内时才要求参数包含构造目标所需的全部必填项,并据此调用 `goRoot` 或内部 replace;普通返回不允许携带流程结果。`finishPage(routeKey, targetParams, result)` 是完成并回传结果的唯一公开入口,调用方即使返回栈内目标也必须显式提供目标的全部必填参数;先验证结果字段和目标页 `resultOperations`,再与最近实例核对。若当前来源也是注册路由,来源与目标共同声明且实际存在的上下文字段(如 `genealogyId/albumId/personId`)必须相等,不能由调用方伪造目标参数跨上下文写结果;外部未知来源不冒充业务上下文。
-
-结果写入与转场锁的 started/reused/busy 判定必须原子完成:只有真正取得锁的首个动作写入,目标原生 `onShow` 时已经可见;复用和忙碌调用不得覆盖。页面实例身份只由模块内 `WeakMap` 生成原始值令牌,结果 envelope 不得强引用页面/Vue 实例。栈内结果绑定被反向搜索选中的最近页面令牌和完整规范参数,缺栈结果绑定发起页令牌与待构造目标参数;只有当前真实栈顶命中该目标实例/新建目标且参数一致时才可消费,错页、同路由更远实例和其他业务上下文返回 `null` 且不删除。新完成流程取得锁后淘汰已经错过生命周期的旧结果;Uni 调用失败或同步抛错只删除当前结果,不得复活陈旧结果。
-
-`kind="single"` 的 T03 已在同一 `genealogyId` 栈下方时,`openPage` 不再压栈:网关写入 T03 允许的 `{ operation: "member-open-requested", entityId: personId, refresh: false }`,精确返回已有 T03,由其读取成功后推进页内轨迹;导航失败立即删除结果。测试必须构造 `[T01,T03,其他页]` 后再次打开 T03,断言原生栈中始终只有一个 T03。若既有 T03 的 `genealogyId` 不同,返回明确 `T03_CONTEXT_CONFLICT` 并拒绝压栈;若迁移前遗留栈已包含多个 T03,则返回 `T03_STACK_CONFLICT`,不得选择其中一个后伪称栈已唯一。调用方必须先返回或用根语义清理冲突上下文。
-
-- [x] **步骤 5:实现统一返回优先级**
-
-返回优先级固定为“关闭瞬态层 → 回退页内轨迹 → 阻止提交中离开 → 确认放弃未保存内容 → 普通返回”。该顺序只由 `resolveBackAction` 的运行时实现拥有,计划不复制第二份函数源码;同步公开入口默认接受空对象,并与异步 `runBackGuard` 共用严格普通对象快照和布尔字段校验。
-
-`runBackGuard(context)` 的四个状态字段只要提供就必须是布尔值;只调用上下文中与返回动作同名的一个回调。关闭瞬态层、回退内部轨迹和阻止提交中返回完成后稳定返回 `true`;放弃确认返回 `false` 时必须留在当前页,返回 `true` 才调用 `goBack()`。页面不得另写不同优先级。
-
-需要弹层、内部轨迹或未保存守卫的页面只保留一个 `requestBack` 函数。页头 `@back` 调用它,Android 返回固定委托给同步适配器;网关自己的 `navigateBack` 再次触发钩子时返回 `false` 放行,不能递归消费:
-
-```js
-onBackPress((event) => handleBackPress(event, requestBack));
-```
-
-根页没有浮层时不注册拦截;有浮层的根页只在浮层可见时返回 `true` 并关闭最上层。
-
-- [x] **步骤 6:验证网关**
-
-运行 Node 冒烟、导航路由合同、全局响应式合同和编译审计。预期全部通过,且网关以外暂时仍有直接调用;任务 3 才启用零调用扫描。
-
-### 任务 3:迁移共享页头、底栏并退役通用母版
-
-**文件:**
-
-- 修改:`components/AppTabbar.vue`
-- 修改:`components/PageHeader.vue`
-- 修改:`pages/genealogy/g01-my-genealogies.vue`
-- 修改:`pages/family/f01-family-feed.vue`
-- 修改:`pages/profile/m01-profile-home.vue`
-- 修改:`tests/shared-interaction-accessibility-contract.ps1`
-- 修改:`tests/shared-component-document-flow-contract.ps1`
-- 修改:`tests/root-pages-visual-contract.ps1`
-- 修改:`tests/runtime-assets-contract.ps1`
-- 新建:`tests/navigation-source-scan-contract.ps1`
-- 新建:`tests/retired-module-page-contract.ps1`
-- 删除:退役通用页面组件、临时页面目录及其两个正向死合同
-- 删除:仅由退役通用页面虚构消费的两张 notification frame 资产及其清单项
-
-**接口:**
-
-- `AppTabbar`:保留现有展示键 `genealogy/family/profile`,另给三项加入 `routeKey: G01/F01/M01`;只调用 `goRoot(item.routeKey)`,活动项无操作,删除每项的 `path`。
-- `PageHeader`:普通返回调用 `goBack()`;`customBack` 仍只发出 `back` 事件给需要守卫的页面;删除 `fallbackUrl`。
-- 52 个活动页面均已拥有自己的业务结构;退役通用页面与临时目录必须删除,不保留第二套状态、返回或视觉合同。
-
-- [x] **步骤 1:先改失败断言**
-
-把旧合同中对 `uni.navigateBack()`、`uni.reLaunch()` 和 `fallbackUrl` 的正向断言改成反向断言,要求页头与底栏导入导航网关,并先用失败合同证明无消费者的通用页面旧入口必须整体退役。
-
-- [x] **步骤 2:迁移共享组件并收紧根页消费者**
-
-共享组件只允许出现:
-
-```js
-import { goBack, goRoot } from "@/utils/navigation.js";
-```
-
-`PageHeader` 的返回函数固定为:
-
-```js
-const handleBack = () => {
- if (props.customBack) {
- emit("back");
- return;
- }
- return goBack();
-};
-```
-
-删除所有 `fallbackUrl` 属性、默认值、模板传递和相关测试;不保留兼容属性。
-
-审查同时证明原通用页面和临时页面目录没有活动消费者;本轮已删除旧入口、专属 mixin、正向死合同与两张孤立通知资产。`ModulePageBackground` 仍由活动页面消费,family/profile/records 的同名 frame 仍由专项 mixin 消费,均不得误删。
-
-- [x] **步骤 3:建立最终零调用扫描与精确迁移债务账本**
-
-`tests/navigation-source-scan-contract.ps1` 覆盖根文件与全部生产 `.vue/.js`,按 SFC 的 template/script/style 分段剥离 HTML、JavaScript 与 SCSS 注释,保留字符串以捕获方括号和 Reflect 取值。五种 Uni 导航方法逐项计数,`getCurrentPages` 同步计数;声明式 `navigator`、动态 Uni 属性、Uni 对象逃逸和 `switchTab` 全局禁止。页面和组件的业务 `/pages/...` 路径字符串也进入账本,资产 `/static/...` 不受影响。任务 3 完成时精确剩余 39 个文件,任务 4—9 每迁移一页必须同轮收紧,任务 10 清空账本。
-
-- [ ] **步骤 4:验证共享批次并在 MuMu 复核**
-
-共享聚焦合同、退役入口合同、运行时资产合同、全局响应式合同和编译审计均已通过;MuMu 复核待执行。受“不启动、关闭或调整 MuMu”约束,本轮不以静态绿灯冒充原生视觉通过,后续只在用户现有 MuMu 环境可用时验证 G01/F01/M01 三个自定义 Tab、普通页头返回和带 `customBack` 的弹层返回。
-
-### 任务 4:迁移认证导航
-
-**文件:**
-
-- 修改:`pages/auth/a01-entry.vue`
-- 修改:`pages/auth/a04-register.vue`
-- 修改:`pages/auth/a05-reset-password.vue`
-- 修改:`pages/auth/a06-auth-status.vue`
-- 修改:`tests/a04-registration-contract.ps1`
-- 修改:`tests/a05-reset-password-contract.ps1`
-- 修改:`tests/a06-auth-status-contract.ps1`
-- 修改:`tests/a01-a02-ui-contract.ps1`
-- 新增并作为后续导航批次唯一流程合同:`tests/navigation-flow-contract.ps1`
-- 修改:`tests/navigation-source-scan-contract.ps1`
-
-**流程合同:**
-
-| 操作 | 唯一语义 |
-| --- | --- |
-| A01 打开注册 | `openPage("A04", {}, "A01")` |
-| A01 打开重设密码 | `openPage("A05", {}, "A01")` |
-| A01 Android 返回 | 行为验证浮层打开时 `requestBack → runBackGuard` 只关闭浮层;无浮层时同步返回 `false`,交还 Android 退出根页 |
-| A04 页头、Android 返回或“已有账号” | 同一 `requestBack → runBackGuard → goBack()`,正常栈弹回 A01,深链按规范父页建立 A01 |
-| A05 未成功时的页头、Android 返回、“想起密码”或取消 | 同一 `requestBack → runBackGuard → goBack()`,不写结果 |
-| A05 本地视觉成功终态的按钮或 Android 返回 | 共用唯一 `leaveResetSuccess → returnTo("A01", {})`,不关闭终态后重新暴露已提交表单,不写结果 |
-| A05 未来真实重设接口成功 | `finishPage("A01", {}, { operation: "password-reset", refresh: false })` |
-| A01 真实登录成功 | `goRoot("G01")` |
-| A06 封存页返回 | 恢复浮层打开时只关闭浮层,否则 `goRoot("A01")` |
-
-当前 A01/A04 的行为验证仍是明确的接口占位,导航批次不得把“知道了”伪装成登录或注册成功。2026-07-22 新线上 OpenAPI 已证明 `/genealogy/app/auth/register` 的 `200` 响应为 `RAppLoginVo → AppLoginVo.access_token`;真实注册接入时必须只读取当前字段、保存有效会话后调用 `goRoot("G01")`,不能先回 A01 再让用户重复登录,也不保留旧响应字段兼容分支。
-
-- [x] **步骤 1:让认证导航合同先失败**
-
-已先建立 `tests/navigation-flow-contract.ps1` 并移除旧直接导航正向断言;第一次执行明确失败在 A01 的 `uni.navigateTo`,证明红灯来自旧实现而非测试语法。合同锁定四页无原生导航/路径旁路、Android 同步适配、完整返回 context、A04/A05 单例延迟确认和 A05 本地成功终态不得生成 `password-reset` 结果。
-
-- [x] **步骤 2:只迁移现有真实导航动作**
-
-页面已统一导入所需语义函数;A01 的安全验证占位、A04 的接口占位和 A05 的本地成功弹窗保持当前事实。A05 本地成功终态的按钮与 Android 返回共用唯一无结果 `returnTo`,只有后续真实重设接口成功才允许生成并消费一次性结果;不新增假接口、不写未调用完成函数。A01 只在行为验证浮层打开时消费系统返回;A04/A05 的脏表单用项目 `AppDialog` 和单例延迟 Promise 确认,重复返回先关闭确认框,卸载必定释放等待者。当前没有真实异步提交,未虚构 `submitting` 状态。A06 只从 `onLoad(options)` 解析状态,已删除浏览器地址与 `getCurrentPages` 旁路。
-
-- [x] **步骤 3:完成认证批次静态验证**
-
-认证导航流程、四页聚焦合同、导航源扫描、响应式合同和编译审计均已通过;源扫描债务由 39 个文件收紧到 35 个文件。任务 4 完成当时的导航网关 Node 冒烟与 PowerShell `121/121` 是该批历史快照;项目当前全量证据以总览登记的任务 5 收口结果为准。
-
-- [ ] **步骤 4:在 MuMu 复核认证流程**
-
-在 MuMu 验证 A01→A04→页头返回、A01→A04→已有账号、A01→A05→取消、A05 本地成功→返回登录,各流程连续执行 3 次;返回后只能有一个 A01,表单取消不得显示成功。受“不启动、关闭或调整 MuMu”约束,本轮保持待验,不能把静态绿灯写成原生交互或视觉已通过。
-
-### 任务 5:迁移 G 系列导航
-
-**文件:**
-
-- 修改:`pages/genealogy/g01-my-genealogies.vue`
-- 修改:`pages/genealogy/g03-create-genealogy.vue`
-- 修改:`pages/genealogy/g05-genealogy-overview.vue`
-- 修改:`pages/genealogy/g06-search-genealogies.vue`
-- 修改:`pages/genealogy/g08-join-application.vue`
-- 修改:`pages/genealogy/g09-my-applications.vue`
-- 修改:`pages/genealogy/g10-application-review.vue`
-- 修改:`pages/genealogy/g11-genealogy-settings.vue`
-- 修改:`pages/genealogy/g12-generation-poems.vue`
-- 修改:`data/mock.js`
-- 修改:`utils/api.js`
-- 修改:`utils/genealogy-contracts.js`
-- 新增:`utils/generation-poem.js`
-- 修改:`utils/navigation-routes.js`
-- 修改:G01、G03、G05、G06、G08—G12 的聚焦合同与运行时冒烟
-- 修改:`tests/navigation-flow-contract.ps1`
-- 修改:`tests/navigation-gateway-runtime-smoke.js`
-- 修改:`tests/navigation-source-scan-contract.ps1`
-- 新增:`tests/genealogy-fixture-runtime-smoke.js`
-- 新增:`tests/generation-poem-runtime-smoke.js`
-- 新增:`tests/g-series-openapi-contract.ps1`
-
-**流程合同:**
-
-- G01 卡片和快捷入口只使用 `openPage`;路径对象改为路由键对象,不能继续保存 `/pages/...` 字符串。
-- G03 内部从创建步骤切换到始祖步骤使用本页状态,不接收 `step` 或 `genealogyId`;当前只建立可撤销的本地预览,完成后用 `returnTo("G05", { genealogyId })` 进入明确预览态,不生成 `genealogy-created` 业务结果。真实接口形成创建与始祖闭环后,才能按服务端事实新增完成结果。
-- G05 返回 `returnTo("G01", {})`,进入 F01 使用 `goRoot("F01", { genealogyId })`,其余入口使用 `openPage`。G05/G08 不再接收 `genealogyName`,页面按 `genealogyId` 从现有 fixture 或领域数据取名称。
-- G06 已加入或我创建的结果 `goRoot("G01", { genealogyId })`;公开预览进入 G05;搜索申请进入 G08;审核中或被拒绝进入 G09。
-- G08 当前搜索与邀请码都只完成本地表单校验:搜索来源无结果进入 G09 预览,邀请码来源无结果回 G01,均不得新增审核记录、选中家谱或声称加入成功。产品终点仍是“邀请码直接加入且不生成审核记录”,但必须等后端提供邀请码解析与直接加入合同后一次性替换本地预览;M08 的审核旧文案已在任务 9 删除,不写双分支兼容。
-- G09 通过记录进入 G05,被拒绝记录进入 G08,搜索入口进入 G06;返回保留列表现场。
-- G10/G11/G12 只更新当前页面的本地审核、设置或字辈预览,不向实际来源回传成功结果;取消按统一返回守卫处理。只有真实接口成功且来源页确实需要失效刷新时,才允许在同一合同变更中注册并消费一次性结果。
-
-- [x] **步骤 1:逐页写失败断言**
-
-`tests/navigation-flow-contract.ps1` 已对上表每类流程检查路由键、`sourceKey`、无伪成功结果和终点;G 系列聚焦合同已移除直接 Uni API 正向断言。失败基线明确来自旧导航调用、伪结果和页面私有合同,而不是测试语法。
-
-- [x] **步骤 2:迁移 G01、G03、G05**
-
-根页、创建流程和总览已迁移。G03 在同一原生页面维护两步状态,并通过唯一临时预览 owner 生成词法字符串 ID;放弃删除本轮临时预览,完成只进入 G05 本地预览。G05 的名称、访问规则、来源、权限入口和公开字段由共享 fixture 与访问解析器投影,不信任路由伪造角色。
-
-- [x] **步骤 3:迁移 G06、G08、G09**
-
-三页已只传字符串 ID 与业务枚举;`previous` 原始来源参数已经删除,来源只由真实栈与受注册表约束的 `sourceKey` 表达。共享可见性与申请资格失败关闭;邀请码与搜索申请保留不同本地终点,G09 撤回只使用 `LOCAL_WITHDRAWN`,不冒充服务端状态。
-
-- [x] **步骤 4:迁移 G10、G11、G12**
-
-三页已删除伪后端成功结果并明确标注本地预览;G10 保留拒绝原因聚焦与无障碍关系,G11 的访问预设由 `utils/genealogy-contracts.js` 唯一拥有且未知值失败关闭。G12 按 OpenAPI 离线导出的 26000 字符、单代 50 字符、最多 500 代、状态 `0/1` 与历史保留约束实现 Unicode 安全解析、完整 ACTIVE 序列检查和每批 50 行渲染;服务端未定义批次首代前不发送本地合并结果。G01 弹层、G09 撤回确认及 G03/G08/G10/G11/G12 表单均已接入同一返回守卫。
-
-- [ ] **步骤 5:完成 G 系列 MuMu 矩阵**
-
-静态合同、纯 Node 冒烟、响应式合同和编译审计已经通过,源码导航债务收紧到 29 个文件。仍须在用户现有 MuMu 中验证 G01→G03→取消/完成、G01→G06→G08→G09、G05→G10/G11/G12→取消/本地完成、直接进入 G11/G12 后返回,以及每条流程重复进入;检查旧页面不残留、当前家谱 ID 不串、取消不刷新、本地预览不伪造服务端成功。受当前约束不得启动、关闭或调整模拟器,本步骤保持未勾选。
-
-### 任务 6:迁移 T 系列并实现 T03 单实例轨迹
-
-**文件:**
-
-- 修改:`pages/tree/t01-tree-overview.vue`
-- 修改:`pages/tree/t03-member-profile.vue`
-- 修改:`pages/tree/t04-add-relative.vue`
-- 修改:`pages/tree/t05-edit-member.vue`
-- 修改:`pages/tree/t06-edit-relationship.vue`
-- 修改:`pages/tree/t07-member-directory.vue`
-- 修改:`pages/tree/t08-member-states.vue`
-- 修改:`data/mock.js`
-- 修改:`utils/api.js`
-- 修改:`tests/t03-t08-member-flow-contract.ps1`
-- 修改:`tests/t03-t08-member-flow-runtime-smoke.js`
-- 修改:`tests/t03-t08-business-specialization-contract.ps1`
-- 修改:`tests/t03-t08-business-specialization-runtime-smoke.js`
-- 修改:`tests/t07-module-baseline-contract.ps1`
-- 修改:`tests/t07-module-baseline-runtime-smoke.js`
-- 修改:`tests/navigation-flow-contract.ps1`
-- 新建:`tests/tree-member-fixture-runtime-smoke.js`
-
-**接口:**
-
-- T03 新增页内状态:`memberTrail: string[]`、`trailIndex: number`、`loadMember(personId): Promise`、`initializeMemberTrail(initialPersonId)`、`openRelative(personId)`、`popMemberTrail()`。
-- 原生页面仍只有一个 T03;亲属点击只在 `loadMember` 成功后追加字符串 `personId`,失败不改轨迹、不清空当前成员。
-- T03 初始 URL 的 `personId` 是不可变宿主页路由身份,页内活动成员随轨迹变化但不改 URL;当前 T03 只消费“打开成员”请求,不消费任何写成功结果。
-- T04/T05/T06 当前都只生成明确写着“尚未提交服务器”的本地预览,提交动作留在本页且不产生导航结果;真实写接口、版本冲突和完成回流统一留到任务 18 原子启用。
-- `data/mock.js::treeMembers` 是当前唯一可变成员夹具 owner,`utils/api.js` 是唯一写入口;页面只使用 `listTreeMemberFixtures(genealogyId)`、`findTreeMemberFixture(genealogyId, personId)` 的深拷贝快照。错误家谱、未知成员与缺失必填路由身份全部失败关闭,只有 T04 明确首位成员模式允许没有 `personId`。
-
-- [x] **步骤 1:先锁定重复 T03 缺陷**
-
-合同先断言初始读取失败时轨迹仍为空、初始成功后轨迹恰为 `[A]`,再构造 T01→T03(A)→亲属 B→亲属 C→返回→返回→来源,锁定 URL 始终为宿主 A、页内活动成员依次 A/B/C/B/A、最终才离开 T03;历史 B 失效时删除 B 后继续回 A。导航网关 Node 冒烟另构造伪栈 `[T01,T03,其他页]` 再打开同一家谱 T03,已证明回到既有实例且原生栈始终只有一个 T03;T03 浏览器运行时脚本已同步这些断言并通过语法检查,但因没有 `127.0.0.1:9222` 调试页而未执行。
-
-- [x] **步骤 2:实现 T03 页内轨迹**
-
-初始成员成功读取后必须先执行:
-
-```js
-memberTrail.splice(0, memberTrail.length, initialPersonId);
-trailIndex.value = 0;
-```
-
-随后亲属切换按以下顺序实现,并写明中文步骤注释:
-
-```js
-const openRelative = async (nextPersonId) => {
- if (nextPersonId === personId.value) return;
- const loaded = await loadMember(nextPersonId);
- if (!loaded) return;
- memberTrail.splice(trailIndex.value + 1);
- memberTrail.push(nextPersonId);
- trailIndex.value = memberTrail.length - 1;
-};
-```
-
-`popMemberTrail()` 先递减索引再加载历史成员;历史成员失效时移除该项并继续向前,不能生成新 T03 页面。页头与 `onBackPress` 必须构造同一 context,通过 `runBackGuard` 先消费内部轨迹;T04/T05/T06 等表单也以提交中→脏表单的统一优先级接线。
-
-- [x] **步骤 3:迁移 T01、T04—T08 的终点**
-
-T01 打开 T03/T04/T06/T07 已全部使用路由键;T07 以路由键打开当前单实例 T03;T08 家谱失效使用根语义回 G01,普通状态使用统一返回。六位共享成员 101—106 已能从 T01/T07 一致进入 T03,104 能进入 T05/T08,106 进入 T06 时仍保持 106,不再回退首位成员。T04/T06 的本地预览由用户确认放弃后无结果回 T01;T05 的活动成员可能不同于宿主页路由身份,所以确认放弃预览后必须使用 `goBack()`:有历史时精确退回原 T03(A) 并保留活动成员 B 与轨迹,深链单页时才按当前参数构造规范父页。不得以活动成员 B 强行返回 T03(B),也不得把本地预览伪造成服务端完成。
-
-- [ ] **步骤 4:完成 T 系列 MuMu 矩阵**
-
-T 聚焦合同、导航网关与成员夹具纯 Node 冒烟、全部 Node 语法检查、响应式合同和编译审计已经通过;最新全量结果为 PowerShell `122/122`、Node 语法 `35/35`、纯 Node `7/7`,源码导航债务收紧到 22 个页面/表单组件文件。成员夹具运行时已验证复合身份、跨谱隔离、父链与状态枚举、列表/单项深拷贝,以及 `createPerson` 写入完整 shape 后的同谱可见与跨谱不可见。依赖 `127.0.0.1:9222` 的浏览器脚本本轮只完成语法检查;仍须在用户现有 MuMu 中验证 T03 A→B→C→B→A→来源、T04/T05/T06 的取消与本地预览放弃、T07 选择、T08 返回和同一流程 20 次重复进入;原生栈不得随亲属浏览增长,三个预览均不得表现为服务端已保存。受当前约束不得启动、关闭或调整模拟器,本步骤保持未勾选。
-
-### 任务 7:迁移 F 系列导航
-
-**文件:**
-
-- 修改:`utils/navigation-routes.js`
-- 修改:`data/mock.js`
-- 修改:`utils/api.js`
-- 修改:`pages/family/f01-family-feed.vue`
-- 修改:`pages/family/f02-publish-feed.vue`
-- 修改:`pages/family/f03-feed-detail.vue`
-- 修改:`pages/family/f04-article-list.vue`
-- 修改:`pages/family/f05-article-detail.vue`
-- 修改:`pages/family/f06-article-editor.vue`
-- 修改:`pages/family/f07-album-list.vue`
-- 修改:`pages/family/f08-album-detail.vue`
-- 修改:`pages/family/f09-media-upload.vue`
-- 修改:`pages/family/f10-video-list.vue`
-- 修改:`tests/f-business-flow-contract.ps1`
-- 修改:`tests/f05-expired-state-contract.ps1`
-- 修改:`tests/f06-editor-context-contract.ps1`
-- 修改:`tests/f08-album-detail-contract.ps1`
-- 修改:`tests/f09-media-upload-contract.ps1`
-- 修改:`tests/f10-video-status-contract.ps1`
-- 新增:`tests/family-fixture-runtime-smoke.js`
-- 修改:`tests/navigation-routes-contract.ps1`
-- 修改:`tests/navigation-source-scan-contract.ps1`
-- 修改:`tests/navigation-flow-contract.ps1`
-
-**流程合同:**
-
-| 流程 | 页面身份 | 取消/返回 | 当前阶段完成语义 |
-| --- | --- | --- | --- |
-| F01→F02 | `genealogyId` | F01 `{ genealogyId }` | 仅生成“尚未提交服务器”的本地预览,不发布、不产出结果 |
-| F01→F03 | `genealogyId + feedId` | F01 `{ genealogyId }` 且恢复现场 | 评论草稿保留在本页,不插入列表、不增加计数、不宣称发送成功 |
-| F01→F04→F05 | F04 为 `genealogyId`;F05 再加 `articleId` | F05 回 F04,F04 回 F01 | 收藏禁用并明确暂未开放 |
-| F04/F05→F06 | `genealogyId + mode`;编辑再加 `articleId` | 新建回 F04,编辑回精确 F05 | 仅生成未保存预览,不产出文章结果 |
-| F01→F07→F08→F09 | F07 为 `genealogyId`;F08/F09 再加 `albumId` | 逐级回实际来源 | 新相册与选图只做独立本地预览,不加入正式列表、不上传、不产出结果 |
-| F01→F10 | `genealogyId` | F01 `{ genealogyId }` | 当前未开放,无伪成功 |
-
-- [x] **步骤 1:先建立身份与伪成功失败合同**
-
-`tests/navigation-routes-contract.ps1` 已把 F02—F10 的 `genealogyId`、F03/F05/F08/F09 的复合实体身份、F06 的模式参数及 F01/F04/F05/F08 的零结果能力写成精确合同;`tests/family-fixture-runtime-smoke.js` 已把跨谱拒绝、缺参拒绝、词法字符串 ID 和列表/详情深拷贝写成运行时合同。旧实现分别因 `feed-created` 预注册和缺少共享查询 owner 正确红灯,证明失败来自待迁合同而非测试环境。
-
-- [x] **步骤 2:收口唯一身份与只读内容 owner**
-
-F01 可从全局上下文解析家谱,但在开放任何内容和入口前必须用 `goRoot("F01", { genealogyId })` 把根页 URL 规范化;无有效成员家谱时失败关闭。F02—F10 全部必填 `genealogyId`,实体页按复合身份精确查询,缺参、未知实体和跨谱 ID 均不得回退首条数据。F01 的 R01/R03/R05/R10/R11 入口同轮把 `genealogyId` 交给注册表,R 页面内部迁移仍留在任务 8。
-
-`data/mock.js` 是 F 系列只读 feed/article/album 夹具的唯一 owner,只公开按家谱列表和按复合身份详情的深拷贝查询函数;页面与 `utils/api.js` 不得读取或写入裸数组。`createFeed` 只允许真实远端配置下 POST;mock 模式必须以 `WRITE_UNAVAILABLE` 失败关闭。
-
-- [x] **步骤 3:迁移动态与谱文流程**
-
-F01—F06 全部只使用导航网关。F02、F03、F06 的页头、Android 返回和显式取消统一处理脏草稿及校验中状态;F03 失效回 F01,F05 失效回 F04,F06 按 `mode=create/edit` 精确回 F04/F05。删除“动态已发布”“评论已发送”“谱文已保存”和收藏二态,任何页面不得调用 `finishPage`。
-
-- [x] **步骤 4:迁移相册与未开放视频**
-
-F07 新建相册只形成独立、明确标注不会保存的本地预览,不插入正式相册列表;弹层与草稿分别按优先级处理。F08 页头和 Android 返回都先关闭照片预览,再回 F07;F09 的选择、批量说明与逐图说明均计入脏状态,校验中阻止离开,本地预览后无结果回同一 `genealogyId + albumId` 的 F08。F10 使用 `returnTo("F01", { genealogyId })`。旧 `/genealogy/app/files/upload` 不得进入运行时;真实上传必须在后续接口批次按线上 resumable init/chunk/complete 取得 `ossId` 后再创建相册照片记录。
-
-- [x] **步骤 5:验证 F 系列静态与纯运行时合同**
-
-F 聚焦合同、共享导航合同、家族夹具、响应式合同和编译审计均已通过。生产 F01—F10 的 `resultOperations` 精确为空,网关运行时逐项证明旧 `feed-created/article-created/article-updated/media-uploaded` 在任何导航发生前被拒绝且不残留结果;泛型完成结果算法改用只存在于测试内存模块的 `TEST_*` 中性路由,不把旧 F 语义伪装成夹具。`data/mock.js` 的列表/详情深拷贝、词法字符串 ID、未知实体与跨谱隔离已由 `tests/family-fixture-runtime-smoke.js` 验证,mock 写动态以 `WRITE_UNAVAILABLE` 失败关闭。
-
-最新文件 fresh 全量结果为 PowerShell `122/122`、Node 语法 `36/36`、纯 Node `8/8`;源码扫描为 `MIGRATION-DEBT=13`,剩余 `13 个页面/表单组件文件`,计数为 `navigateTo 17`、`navigateBack 1`、`redirectTo 3`、`reLaunch 1`、`getCurrentPages 1`、业务页面路径字面量 `27`。依赖 `127.0.0.1:9222` 的浏览器脚本没有可连接调试页,本批只完成 `36/36` 语法检查,未冒充浏览器或原生通过。
-
-- [ ] **步骤 6:完成 F 系列 MuMu 矩阵**
-
-在 MuMu 逐条验证表中流程的进入、返回、取消、本地预览和重复进入,重点检查 F01/F04/F07 不重复、F08 预览优先关闭、F09 始终不显示上传成功。受当前约束不得启动、关闭或调整 MuMu,静态与纯运行时绿灯不能冒充原生视觉通过。
-
-### 任务 8:迁移 R 系列导航
-
-**文件:**
-
-- 修改:`utils/navigation-routes.js`
-- 修改:`data/mock.js`
-- 修改:`utils/api.js`
-- 修改:`pages/tree/t03-member-profile.vue`
-- 修改:`pages/records/r01-people-list.vue`
-- 修改:`pages/records/r02-person-detail.vue`
-- 修改:`pages/records/r03-gift-list.vue`
-- 修改:`pages/records/r04-gift-editor.vue`
-- 修改:`pages/records/r05-ritual-list.vue`
-- 修改:`pages/records/r06-ritual-detail.vue`
-- 修改:`pages/records/r07-ritual-editor.vue`
-- 修改:`pages/records/r08-growth-journal.vue`
-- 修改:`pages/records/r09-life-events.vue`
-- 修改:`pages/records/r10-memo-list.vue`
-- 修改:`pages/records/r11-merit-records.vue`
-- 修改:`tests/r-business-flow-contract.ps1`
-- 修改:`tests/r01-r02-person-flow-contract.ps1`
-- 修改:`tests/r02-person-detail-contract.ps1`
-- 修改:`tests/r02-person-detail-runtime-smoke.js`
-- 新建:`tests/records-fixture-runtime-smoke.js`
-- 修改:`tests/navigation-routes-contract.ps1`
-- 修改:`tests/navigation-gateway-runtime-smoke.js`
-- 修改:`tests/navigation-flow-contract.ps1`
-- 修改:`tests/navigation-source-scan-contract.ps1`
-- 修改:`docs/接口与页面映射总表.md`
-- 修改:`docs/项目当前总览.md`
-
-**三方审查结论与流程合同:**
-
-- R01/R02 归属线上 `lineage/persons`;R03/R04 归属 `relative-records`,不是依赖礼仪 ID 的 ceremony gifts,`giftId` 全量退役为 `relativeId`;R05—R07 归属 `ceremonies`,`ritualId` 全量退役为 `ceremonyId`。R08 只可在同一家谱内按 `lineagePersonId` 过滤 `growth-records`;R10/R11 分别归属 `memos` 与 `merit-records`。
-- R09 必须保持硬关闭:线上没有独立人生事件接口,`growth-records.recordType` 也没有可引用枚举或类型说明;后端给出独立端点或正式字典前,不得自行发明 `LIFE_EVENT`、不得读取或写入成长记录冒充人生事。
-- R01/R03/R05/R10/R11 必填 `genealogyId`;R02 必填 `genealogyId + mode`、可选 `personId`,create 禁止 ID、view 必须有精确 ID;R04 同理使用 `relativeId`;R06 必填 `genealogyId + ceremonyId`;R07 必填 `genealogyId + mode`、可选 `ceremonyId`,create/edit 条件互斥;R08/R09 必填 `genealogyId + personId`。所有 ID 保持词法字符串,未知实体、缺参和跨谱都失败关闭。
-- 当前只允许只读正式列表与独立草稿;所有保存动作只能形成明确的“本地预览,尚未提交服务器”,不得插入正式列表、修改完成状态、增加汇总、生成实体 ID 或宣称删除。生产 R01—R11 的 `resultOperations` 精确为空,真实 API 成功接入前不得调用 `finishPage`。
-- 权限模型只说明需要登录,没有 `canCreate/canEdit/canDelete`;本地成员角色、`sponsorUserId` 和页面 fixture 都不得冒充服务端权限。无效上下文必须隐藏预览入口;本地预览入口不能写成“已保存”或“已删除”。
-- R02/R04/R07/R08/R10/R11 的页头、弹层取消按钮与 `onBackPress` 共享返回守卫;浮层优先关闭、提交中阻止离开、脏草稿确认放弃。R09 只有不可用说明与安全返回。R07 create 预览回 R05,edit 预览回原 R06;R08 返回实际 R02 或 T03 来源。
-
-- [x] **步骤 1:先写旧参数、复合身份、零结果与假成功失败合同**
-
-反转当前保护 `saveResult`、`personName`、`giftId`、`ritualId`、直接 Uni 路径、本地 `unshift`、完成状态切换和成功文案的旧测试;网关运行时必须证明旧 person/gift/ritual 结果在导航前被拒绝且无残留。源码扫描的 R01—R07 债务同轮清零。
-
-- [x] **步骤 2:收紧注册表与精确身份**
-
-先只改注册表和导航消费者:所有子页携带 `genealogyId`,实体页携带精确实体 ID,create/view/edit 条件由页面失败关闭;删除 R 生产结果能力和全部原始 Uni 导航。此步不接真实写接口。
-
-- [x] **步骤 3:建立只读复合身份 owner**
-
-R01/R02 复用树成员深拷贝选择器;relative、ceremony、growth、memo、merit 建立唯一只读复合身份 owner,并由 `tests/records-fixture-runtime-smoke.js` 锁定深拷贝、词法 ID、未知实体和跨谱隔离。`utils/api.js` 的 ceremony/growth mock 只能消费该 owner,不能继续返回未隔离的 `familyContent`。
-
-- [x] **步骤 4:按领域独立迁移页面**
-
-依次完成 R01/R02 人物、R03/R04 人情往来、R05—R07 礼仪,再完成 R08/R10/R11 的同页预览;每一域分别运行聚焦合同后才进入下一域。字段使用真实 Body 语义:人物 `name`,往来 `relativeName`,礼仪 `ceremonyTitle/ceremonyType`,成长 `recordTitle`,备忘 `memoTitle`,功德 `donorName/meritTitle`。不明确的枚举不制作选择器。
-
-- [x] **步骤 5:关闭 R09 并同步接口缺口**
-
-R09 不显示 fixture 时间轴、不开放新增,只说明后端缺少独立接口或正式 `recordType` 字典并安全返回;将接口问题写入总表,不能以页面隐藏替代后端问题单。
-
-- [x] **步骤 6:执行静态与纯运行时验证**
-
-运行 R 聚焦合同、导航注册表/网关/源码扫描、记录夹具 Node 冒烟、编译审计、全部 PowerShell 合同和全部 Node 语法检查;同步最新物理计数、迁移债务与明确未执行的环境验证。
-
-R01—R11 已按复合家谱身份、受控成员展示投影、只读正式记录和独立本地预览完成静态迁移;R09 因线上没有独立端点或正式 `recordType` 字典保持硬关闭。三方复核未发现 P0/P1,受限成员的私密字段在数据 owner 即被删除,礼仪邀请只以 `inviteeUserId` 与同谱成员受控联接;编辑和弃稿弹层均禁止遮罩误关。最新文件 fresh 全量结果为 PowerShell `122/122`、Node 语法 `37/37`、纯 Node `9/9`;源码扫描为 `MIGRATION-DEBT=6`,剩余 `6 个页面/表单组件文件`,计数为 `navigateTo 8`、`navigateBack 1`、`redirectTo 0`、`reLaunch 0`、`getCurrentPages 1`、业务页面路径字面量 `14`。依赖 `127.0.0.1:9222` 的浏览器脚本只完成语法检查;受当前约束未触碰 MuMu,不能把静态结果冒充原生视觉验收。
-
-- [ ] **步骤 7:完成 R 系列 MuMu 矩阵**
-
-MuMu 分别验证复合身份、跨谱失败、列表滚动、搜索现场、预览不入正式列表、弹层优先关闭、脏草稿确认、连续重复进入与 R09 硬关闭。当前明确禁止启动、关闭或调整 MuMu,因此此项保持未完成,静态绿灯不得冒充原生视觉通过。
-
-### 任务 9:迁移 N/M 系列与安全通知目标
-
-**文件:**
-
-- 修改:`utils/navigation-routes.js`
-- 修改:`utils/navigation.js`
-- 修改:`pages/notification/n01-message-center.vue`
-- 修改:`pages/notification/n02-message-detail.vue`
-- 修改:`pages/profile/m01-profile-home.vue`
-- 修改:`pages/profile/m02-edit-profile.vue`
-- 修改:`pages/profile/m03-security-settings.vue`
-- 修改:`pages/profile/m04-change-password.vue`
-- 修改:`pages/profile/m05-change-phone.vue`
-- 修改:`pages/profile/m06-help-center.vue`
-- 修改:`pages/profile/m07-feedback.vue`
-- 修改:`pages/profile/m08-promotion.vue`
-- 修改:`pages/profile/m09-vip-orders.vue`
-- 修改:`pages/profile/m10-about-settings.vue`
-- 修改:`tests/nm-page-business-contract.ps1`
-- 修改:`tests/nm-business-runtime-smoke.js`
-- 修改:`tests/root-pages-runtime-smoke.js`
-- 修改:`tests/navigation-flow-contract.ps1`
-
-**接口:**
-
-`utils/navigation-routes.js` 同轮增加唯一通知目标表:
-
-```js
-export const NOTICE_TARGETS = Object.freeze({
- GENEALOGY_REVIEW: Object.freeze({ routeKey: "G10", params: ["genealogyId"] }),
- GENEALOGY_HOME: Object.freeze({ routeKey: "G01", params: ["genealogyId"] }),
-});
-```
-
-`utils/navigation.js` 新增 `openNoticeTarget(targetType, params, sourceKey = "N02")`:未知类型、缺字段、多字段、非字符串 ID 和原始 URL 一律拒绝;G01 使用 `goRoot`,G10 使用 `openPage`。
-
-- [x] **步骤 1:先锁定原始 URL 漏洞**
-
-合同要求 N01/N02 数据只含 `targetType` 与 `targetParams`,源码不得出现 `noticeDetail.value.target` 或 `/pages/...` 目标字符串。旧 N02 因持有 `target` 并直接 `navigateTo` 而失败。
-
-- [x] **步骤 2:迁移 N01/N02**
-
-N01 打开 N02 固定使用 `openPage("N02", { id }, "N01")`;N02 默认回 N01。目标无权限、过期、字段不足或类型未知时留在 N02 明确说明,不猜测、不回落空页面。
-
-- [x] **步骤 3:迁移 M 页面、邀请语义与退出**
-
-M01 菜单由路由字符串改成路由键;M03/M06 使用 `openPage`;M08 删除“邀请码加入后需要管理员审核”及其并行分支,只保留已经定案的“邀请码直接加入且不生成审核记录”,聚焦合同同时断言旧文案不存在。M10 确认退出时按顺序执行 `session.clear()`、关闭确认层、`goRoot("A01")`,退出取消只关闭弹窗。M02/M04/M05/M07 的表单、M08/M09 的分享或说明弹层、M10 的协议和退出确认都让页头与 `onBackPress` 共用同一 `requestBack/runBackGuard`;提交中优先于脏表单,弹层优先于页面返回。
-
-- [x] **步骤 4:完成 N/M 静态验证**
-
-N01/N02 现在只消费 `data/mock.js` 的词法消息 ID、`targetType/targetParams` 与 `unread` 字段;安全目标由 `NOTICE_TARGETS` 白名单映射,未知、缺参、多参、原始 URL 和越权目标均失败关闭。M02/M03/M05 统一消费当前用户 owner,M02/M04/M05 仅做明确未提交服务器的本地校验;M07 已在后续独立任务 25 接入真实反馈客户端。M08/M09 在缺少可实施合同时硬关闭伪邀请码和伪订单;M10 从 `manifest.json` 读取版本,并按 `session.clear()`、关闭确认层、`goRoot("A01")` 的顺序退出,账号令牌和当前家谱上下文同时清理。
-
-Task9 最新静态结果为 PowerShell `122/122`、Node 语法 `39/39`、纯 Node `11/11`;导航扫描为 `MIGRATION-DEBT=1`,唯一剩余项是零生产消费者 `components/tree/TreeMemberForm.vue`,交由任务 10 原子删除。两份浏览器运行时合同已更新但因 `5173/9222` 均无可用页面只完成语法检查,未冒充浏览器通过。
-
-- [ ] **步骤 5:完成 N/M 系列 MuMu 矩阵**
-
-MuMu 验证 G01/M01→N01→N02→业务目标、目标失效、返回、重复进入,以及 M01→M10→取消/确认退出。确认退出后原栈被清理且只有 A01。当前明确禁止启动、关闭或调整 MuMu,因此本项保持未完成。
-
-### 任务 10:关闭导航阶段
-
-**文件:**
-
-- 修改:`tests/navigation-source-scan-contract.ps1`
-- 修改:`tests/navigation-flow-contract.ps1`
-- 删除:`components/tree/TreeMemberForm.vue`
-- 删除:`tests/tree-member-form-document-flow-contract.ps1`
-- 修改:`tests/t03-t06-all-states-visual-contract.ps1`
-- 修改:`tests/responsive-layout-coverage.json`
-- 修改:`docs/家谱项目全量治理设计.md`
-- 修改:`docs/家谱项目全量治理实施计划.md`
-- 修改:`docs/项目当前总览.md`
-- 修改:`docs/接口与页面映射总表.md`
-
-- [x] **步骤 1:执行零调用与闭合合同**
-
-`TreeMemberForm.vue` 已经三人确认零生产消费者并删除;旧专属合同同步删除,T04/T05/T06 活动页面接替字体、布局与文档流覆盖,响应式清单和导航债务账本同轮收紧。`tests/navigation-source-scan-contract.ps1` 证明 pages、components、utils 中网关外的五种 Uni 导航调用和 `getCurrentPages` 数量均为 `0`,唯一允许位置是 `utils/navigation.js`,`switchTab` 全项目为 `0`;路由注册表与 `pages.json` 为 `52/52`,结果为 `MIGRATION-DEBT=0`。
-
-- [x] **步骤 2:运行全量合同**
-
-运行本计划“每个代码批次的固定验证”中的全量 PowerShell 循环,再运行:
-
-```powershell
-node tests/navigation-gateway-runtime-smoke.js
-node tests/password-policy-runtime-smoke.js
-```
-
-最新文件 fresh 结果为 PowerShell `121/121`、Node 语法 `39/39`、纯 Node `11/11`,编译审计和响应式合同包含在全量绿灯中。合同数量从 122 变为 121 的唯一原因是删除了只保护已退役孤儿组件的专属测试,其有效视觉断言已经迁到 T04/T05/T06 现页合同;没有删除或放宽任何活动业务失败条件。
-
-- [ ] **步骤 3:执行 NAV-MUMU-01 至 NAV-MUMU-08**
-
-1. 认证注册与重设返回;
-2. G03 创建取消/完成;
-3. G06/G08/G09 加入流程;
-4. T03 A→B→C→B→A→来源;
-5. F02/F03/F04/F05/F06 回流;
-6. F07/F08/F09 与预览优先级;
-7. R01—R07 列表/详情/编辑;
-8. N01/N02 业务目标与 M10 退出。
-
-每组都验证进入、返回、取消、完成、直接进入和重复进入。记录实际行为与栈结果;忽略“3D研究室”等系统水印,不调整 MuMu。
-
-- [ ] **步骤 4:三人终审并更新状态**
-
-三人分别检查业务正确性、全局一致性、回归风险、维护成本和 MuMu 可验证性;任何一人提出有证据的问题即继续修复。只有所有导航门禁均通过,才把总览改为“导航栈语义统一已完成”,并开启第二阶段接口门禁。
-
----
-
-## 第二阶段:T01 大规模世系树
-
-### 任务 11:向后端提交规范图合同并建立接口门禁
-
-**文件:**
-
-- 新建:`tests/lineage-openapi-contract.ps1`
-- 修改:`docs/接口与页面映射总表.md`
-- 修改:`docs/家谱项目全量治理设计.md`
-
-**当前已证实缺口:**
-
-- 现有 `GET /genealogy/app/genealogies/{genealogyId}/lineage/tree` 只有 `genealogyId`,响应是递归 `LineagePersonTreeView[]`。
-- 当前接口没有 `/lineage/tree/overview` 和 `/lineage/persons/{personId}/locator`。
-- 当前世系 ID 大量使用 `integer/int64`,JavaScript 无法保证超过安全整数后的精确性。
-- 当前递归 `children/spouses` 无法精确表达多个家庭联合点、收养/继亲/监护、主入边、未加载边界和图版本。
-- T06 所需的关系修改接口缺失;现有新增父母、子女、兄弟姐妹和配偶接口没有统一的 `If-Match` 树版本并发合同。
-
-**新读合同:**
-
-```http
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/tree
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/tree/overview
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/persons/{personId}/locator
-PATCH /genealogy/app/v2/genealogies/{genealogyId}/lineage/relationships/{relationshipId}
-```
-
-`/lineage/tree` 查询参数固定为 `mode,focusPersonId,ancestorDepth,descendantDepth,boundaryId,cursor,limit,treeVersion`,不接受 `branchId/generation`。两个模式严格互斥:
-
-- `mode=FOCUS`:`focusPersonId` 可选且只能是调用者可见的稳定人物 ID,REDACTED opaque ID 不得作为焦点;缺省时服务端按当前账号绑定成员、主始祖的顺序确定,并返回实际焦点。不可见、过期或不存在的焦点统一返回 HTTP `404 LINEAGE_FOCUS_NOT_AVAILABLE`,不泄漏成员是否存在。`ancestorDepth/descendantDepth` 是 0—20 的整数、可选且默认 2;`boundaryId/cursor/treeVersion` 必须缺席。
-- `mode=BOUNDARY`:`boundaryId/cursor/treeVersion` 三项必填;`focusPersonId/ancestorDepth/descendantDepth` 必须缺席。
-- `limit` 最小 1、默认 200、最大 500;混合、缺项、多余或越界组合返回 HTTP `422` 和稳定业务码 `LINEAGE_QUERY_INVALID`。OpenAPI 同时声明 `400/401/403/404/422/429/5xx`。
-
-响应 `data` 必须是:
-
-```json
-{
- "version": { "schemaVersion": "2.0", "treeVersion": "t-20260722-1", "generatedAt": "2026-07-22T10:00:00+08:00" },
- "state": "EMPTY",
- "genealogyId": "1001",
- "nodes": [],
- "familyUnits": [],
- "edges": [],
- "window": {
- "focusPersonId": null,
- "entryPersonIds": [],
- "scope": { "ancestorDepth": 2, "descendantDepth": 2 },
- "generationRange": null,
- "returnedNodeCount": 0,
- "boundaries": []
- }
-}
-```
-
-这是合法的 `state=EMPTY` 空谱,不是合同错误。下面是 `state=POPULATED` 响应中的可见人物、匿名人物、家庭和边片段;完整 POPULATED 根必须有非空 nodes、有效焦点、至少一个窗口入口以及非空代际范围。
-
-节点、家庭和边的精确形状:
-
-```json
-{
- "node": {
- "id": "p103",
- "generation": 18,
- "displayName": "某某某",
- "sex": "MALE",
- "avatarOssId": null,
- "branchId": "b-main",
- "branchPath": ["b-root", "b-main"],
- "order": 1,
- "visibility": "VISIBLE",
- "entryReason": null
- },
- "redactedNode": {
- "id": "redacted:t-20260722-1:17",
- "generation": 18,
- "displayName": "隐私成员",
- "order": 2,
- "visibility": "REDACTED",
- "entryReason": null
- },
- "familyUnit": {
- "id": "fu-103-1",
- "anchorPersonId": "p103",
- "partnerRelationship": {
- "relationshipId": "rel-partner-103-104",
- "relationshipKind": "PARTNER",
- "relationType": "MARRIAGE",
- "status": "ACTIVE"
- },
- "partners": [
- { "personId": "p103", "partnerRole": "ANCHOR", "order": 1 },
- { "personId": "p104", "partnerRole": "PARTNER", "order": 2 }
- ],
- "order": 1
- },
- "edge": {
- "id": "e-103-106",
- "familyUnitId": "fu-103-1",
- "childId": "p106",
- "lineageParentId": "p103",
- "parentRelations": [
- { "relationshipId": "rel-parent-103-106", "relationshipKind": "PARENT_CHILD", "personId": "p103", "parentRole": "FATHER", "relationType": "BIOLOGICAL" },
- { "relationshipId": "rel-parent-104-106", "relationshipKind": "PARENT_CHILD", "personId": "p104", "parentRole": "MOTHER", "relationType": "BIOLOGICAL" }
- ],
- "primary": true,
- "order": 1
- }
-}
-```
-
-`LineageGraphWindow` 以根字段 `state` 为 discriminator 使用 `oneOf`,枚举只允许 `EMPTY/POPULATED`。EMPTY 分支精确要求 `nodes/familyUnits/edges=[]`,且窗口内 `focusPersonId=null、entryPersonIds=[]、generationRange=null、returnedNodeCount=0、boundaries=[]`;POPULATED 分支要求 nodes 非空、`focusPersonId` 引用其中一个 VISIBLE 节点、`entryPersonIds` 非空且全部引用当前 nodes、`generationRange` 非空,并满足 `returnedNodeCount === nodes.length`。
-
-非空 `generationRange` 固定为 `{ minGeneration, maxGeneration }`,两项均为大于等于 1 的整数且关闭额外字段;大小顺序由运行时 validator 验证。四条 v2 操作统一声明 `200/400/401/403/404/422/429/5XX`,tree、overview、relationship PATCH 另声明 `409`。错误响应根层必填字符串字段固定为 `businessCode`;每个稳定业务码必须落在对应响应 `oneOf` 分支的单值 enum(OpenAPI 3.1 可用 `const`)中,不能从 description、example 或无关 metadata 搜索得出。
-
-`entryPersonIds` 精确等于当前返回窗口中没有 primary 入边的节点集合,不代表全谱始祖;secondary 入边不取消入口身份。入口节点 `entryReason` 只允许 `GENEALOGY_ROOT/WINDOW_CUT/DISCONNECTED_COMPONENT`,非入口固定为 `null`。每个入口在当前窗口恰有零条 primary 入边,每个非入口恰有一条 primary 入边;`GENEALOGY_ROOT` 表示全谱主森林根,`WINDOW_CUT` 表示 canonical primary 父边在窗口外,`DISCONNECTED_COMPONENT` 表示没有可达全谱根的 canonical primary 链。全谱根只由 overview 的可见根/隐私根计数和 locator 的根可见性分支表达。
-
-人物以 `visibility` 为 discriminator 使用 `oneOf`,枚举只允许 `VISIBLE/REDACTED`。`VisibleLineagePerson` 精确包含 `id,generation,displayName,sex,avatarOssId,branchId,branchPath,order,visibility=VISIBLE,entryReason`,其 ID 是可用于 FOCUS、locator、搜索和写接口且不得以 `redacted:` 开头的稳定人物 ID,`sex` 只允许 `MALE/FEMALE/UNKNOWN`;`RedactedLineagePerson` 只允许 `id,generation,displayName,order,visibility=REDACTED,entryReason`,`displayName` 固定为“隐私成员”,opaque ID 精确使用 `redacted:{treeVersion}:{token}` 并仅能在该 `treeVersion` 内作当前图内部引用,不得用于 FOCUS、locator、搜索或写接口,也不得进入任何 `focusPersonId/targetPersonId`,并且不得返回 `sex/avatarOssId/branchId/branchPath` 或其他可推断身份字段。两类人物的 `generation` 都是大于等于 1 的整数,`order` 是非负整数;可见人物的 `avatarOssId` 只允许非空字符串或 `null`,其他实体、关系和引用 ID 必须是非空字符串。
-
-双人家庭的 `partnerRelationship` 必含稳定 `relationshipId、relationshipKind=PARTNER、relationType、status`;`relationType` 为 `MARRIAGE/PARTNERSHIP/UNKNOWN`,`status` 为 `ACTIVE/ENDED/UNKNOWN`。单亲家庭该对象固定为 `null` 且 `partners` 只有一个 ANCHOR;`partnerRole` 只允许 `ANCHOR/PARTNER`,多配偶为每段伴侣关系建立不同 FamilyUnit。父子关系固定 `relationshipKind=PARENT_CHILD`。`lineageParentId` 必须同时出现在该 edge 的 `parentRelations` 和对应家庭成员中,子女不得同时属于该家庭成员;primary 入边与 `entryPersonIds` 必须满足上一段的零条/恰一条森林不变量,所有父子关系都检查自环和有向循环。
-
-边界固定形状为 `{ id, anchorType, anchorId, direction, reason, hiddenCount, cursor }`。PERSON/FAMILY_UNIT 的 `anchorId` 引用对应实体,WINDOW 的 `anchorId=null`;`hiddenCount` 只能是非负整数或 `null`;cursor 仅在 `reason=UNLOADED` 时为非空字符串,MISSING/REDACTED 时固定为 `null`。窗口内匿名人物使用 `Node.visibility=REDACTED`,窗口外隐藏拓扑使用 `boundary.reason=REDACTED`,同一隐藏对象不得在一个响应中重复表达。
-
-`/lineage/tree/overview` 只接受必填查询参数 `treeVersion` 并返回同一快照;版本已变化时返回 `409 TREE_VERSION_CHANGED`。`LineageOverview` 精确包含同一 `{ schemaVersion, treeVersion, generatedAt }` 以及 `state、genealogyId、genealogyPersonCount、genealogyRootPersonIds、redactedGenealogyRootCount、generationRange、buckets`,以 `state=EMPTY/POPULATED` 使用 `oneOf`。EMPTY 精确要求 `genealogyPersonCount=0、genealogyRootPersonIds=[]、redactedGenealogyRootCount=0、generationRange=null、buckets=[]`。POPULATED 要求 `genealogyPersonCount>0`、非空 generationRange 和 buckets,且 `genealogyRootPersonIds.length + redactedGenealogyRootCount >= 1`;每个 bucket 固定包含 `id、branchId、generation、visibleCount、redactedCount、unloadedCount、focusPersonId`,三种 count 都是非负整数且全部 buckets 的三类计数总和等于 `genealogyPersonCount`。
-
-`genealogyRootPersonIds` 只包含调用者可见、可用于 FOCUS 的稳定人物 ID,隐私根只计入 `redactedGenealogyRootCount`,绝不返回 opaque ID。bucket 的 `focusPersonId` 只能是该 bucket 内可见稳定人物 ID,没有可见目标时固定为 `null`。
-
-`/locator` 返回 `{ treeVersion, genealogyId, personId, rootVisibility, rootPersonId, pathCompleteness, ancestorPathSegments, generation, branchId }`。根可见性与路径完整性独立校验:`rootVisibility=VISIBLE` 要求可见稳定 `rootPersonId`,`rootVisibility=REDACTED` 要求 `rootPersonId=null`;`pathCompleteness=COMPLETE` 表示没有隐私缺口,`pathCompleteness=REDACTED_GAPS` 表示存在一个或多个隐私段,四种组合中除 `REDACTED + COMPLETE` 因根本身隐私而非法外,其余三种均可出现。
-
-`ancestorPathSegments` 以 `kind` 使用 `oneOf`。VISIBLE 段精确为 `{ kind: "VISIBLE", personIds: [...] }`,personIds 非空且只含可见稳定 ID;REDACTED 段精确为 `{ kind: "REDACTED", hiddenCount }`,hiddenCount 为正整数或不披露时为 `null`,不得含人物 ID。相邻段必须交替,末个 VISIBLE 段以目标结束;可见根时首个 VISIBLE 段从 rootPersonId 开始,隐私根时首段为 REDACTED;COMPLETE 恰好没有 REDACTED 段,REDACTED_GAPS 至少一段。不得返回客户端路由或任何隐私 opaque ID。
-
-所有世系写接口携带 `If-Match: `;成功返回 `{ treeVersion, affectedPersonIds, affectedFamilyUnitIds, affectedRelationshipIds }`。关系 PATCH 由 `relationshipId` 唯一寻址,并以不可变 `relationshipKind` 为 discriminator 使用 `oneOf`:PARTNER 分支只允许 `relationType/status`,PARENT_CHILD 分支只允许 `relationType/parentRole`;每个分支除 `relationshipKind` 外至少提交一个可修改字段,未提交的可修改字段保持原值,空更新返回 HTTP `422` 和稳定业务码 `RELATIONSHIP_PATCH_EMPTY`。kind 必须与服务端既有关系一致,参与人不可偷换。版本变化返回 HTTP `409` 和稳定业务码 `TREE_VERSION_CHANGED`。旧 v1 树接口保持原合同;当前 App 只消费固定的四条 `/genealogy/app/v2/...` 新路径,不做双读或运行时探测。
-
-```json
-{
- "oneOf": [
- { "relationshipKind": "PARTNER", "relationType": "MARRIAGE", "status": "ACTIVE" },
- { "relationshipKind": "PARENT_CHILD", "relationType": "BIOLOGICAL", "parentRole": "FATHER" }
- ]
-}
-```
-
-两个请求分支都设置 `additionalProperties: false`,并以 `minProperties` 或等价 `anyOf(required)` 约束至少一个可修改字段;`relationshipKind` 必填且只作判别与一致性校验,不能通过 PATCH 改值。测试必须覆盖单字段更新、双字段更新、未提交字段保持原值,以及只有 `relationshipKind` 的空更新稳定失败为 `422 RELATIONSHIP_PATCH_EMPTY`。
-
-- [x] **步骤 1:先写严格接口合同并确认当前红灯**
-
-`tests/lineage-openapi-contract.ps1` 已读取受保护双导出并先聚合前置缺口,再在前置项齐全时逐项断言上述四条固定 `/genealogy/app/v2/...` 路径、参数全集、overview 必填 `treeVersion`、响应 `$ref` 闭包、两个 EMPTY/POPULATED schema、locator 根可见性 `oneOf`、`additionalProperties: false`、关系 `oneOf/discriminator`、完整枚举、稳定关系 ID、字符串 ID、nullable 头像、1/200/500 限制、统一状态矩阵、根层 `businessCode`、409 和 `If-Match`;同时递归证明新 schema 不挂到 v1 树响应,并在限定的 YAML paths/components 块中对齐 operationId 和完整 component 引用闭包。当前结果为预期 `LINEAGE-OPENAPI-CONTRACT BLOCKED`,精确列出 JSON/YAML 各缺四条操作和三个固定根模型。平铺 query parameters 无法由 OpenAPI 静态证明 FOCUS/BOUNDARY 跨字段互斥,因此静态层只锁参数全集、枚举和单字段边界;互斥、条件必填、跨 bucket 计数、根隐私、请求/响应版本一致性、409/422 行为和 PATCH 字段保持由运行时 validator 与部署集成测试负责,不能用 description、example、关键词或 schema 存在冒充。YAML 门禁只证明路径、operationId 和引用闭包一致;双导出到位后仍逐字段人工复核,不能把文本解析夸大为完整 YAML 语义解析。
-
-- [x] **步骤 2:把问题单写入唯一映射总表并交给后端**
-
-在 `docs/接口与页面映射总表.md` 的 T01 专节记录当前值、目标值、受影响页面、请求/响应、错误码、权限、验收步骤和上述 JSON 示例。不得新建第六份 Markdown。
-
-- [ ] **步骤 3:等待用户提供新的双格式导出**
-
-本步骤是硬门禁:只接受用户从后端更新后的 Apifox 重新导出的 `APP.openapi.json` 与 `APP.openapi.yaml`。不手改本地导出、不用 mock 假装接口已完成、不提前实施任务 12。
-
-- [ ] **步骤 4:验证新合同绿灯**
-
-运行 `tests/lineage-openapi-contract.ps1`。预期 `LINEAGE-OPENAPI-CONTRACT PASS`;再核对 JSON/YAML 的接口路径、operationId、参数、响应引用和模型字段一致,三人复核后才开启客户端实现。
-
-### 任务 12:实现新图的规范化与严格校验
-
-**文件:**
-
-- 新建:`utils/lineage/normalize.js`
-- 新建:`utils/lineage/validate.js`
-- 新建:`tests/lineage-graph-contract-runtime-smoke.js`
-- 新建:`tests/lineage-overview-locator-runtime-smoke.js`
-
-**接口:**
-
-- `normalizeLineageGraphWindow(raw): LineageGraphWindow`
-- `normalizeLineageOverview(raw): LineageOverview`
-- `normalizeLineageLocator(raw): LineageLocator`
-- `validateLineageGraph(graph): { valid: boolean, issues: Array<{ code, path, message }> }`
-- `validateLineageOverview(overview, { expectedTreeVersion }): { valid, issues }`
-- `validateLineageLocator(locator, { expectedTreeVersion, expectedPersonId }): { valid, issues }`
-- `assertLineageGraph(graph): LineageGraphWindow`;非法时抛出 `LineageGraphError`,错误对象保留全部 issues。
-- `assertLineageOverview` 与 `assertLineageLocator` 使用同一错误结构,且分别在概览展示与定位回流前强制调用。
-
-- [ ] **步骤 1:先覆盖有效和无效图**
-
-测试至少构造:合法 EMPTY、合法 POPULATED、单亲、多配偶、收养次入边、带 secondary 入边但无 primary 入边的 DISCONNECTED_COMPONENT 入口、WINDOW_CUT 入口、窗口内匿名节点、窗口外隐私边界、未加载边界、WINDOW 空锚点和字符串大 ID。
-
-无效图必须覆盖:EMPTY 仍带焦点或节点、POPULATED 无焦点或无入口;`entryPersonIds` 引用不存在人物、列表内人物 `entryReason=null`、列表外人物 `entryReason!=null`、入口仍有 primary 入边、非入口没有或具有多条 primary 入边;重复 ID、缺引用、自环、任意父子关系循环、反向代际、家庭锚点不等于唯一 ANCHOR、双人家庭缺关系对象或稳定 ID、relationshipKind 与容器不符、非法 state/sex/visibility/entryReason/partnerRole/relationType/status、REDACTED 泄漏身份字段或进入 `focusPersonId/targetPersonId`、父母不在家庭、子女同时在家庭、UNLOADED 无 cursor、非 UNLOADED 带 cursor、版本不匹配、数字 ID、旧 `children/spouses`、旧 `parentId`、旧 `partnerIds`、旧 `rootPersonIds/rootReason` 和旧 `version.schema/version.tree`。
-
-概览运行时冒烟必须覆盖合法 EMPTY、可见根 POPULATED、全隐私根 POPULATED;并拒绝 EMPTY 带根/范围/bucket 或非零总量、POPULATED 零总量/空范围/空 bucket/可见根数加隐私根数为零、bucket 三类计数与 `genealogyPersonCount` 不等、重复 bucket ID、`genealogyRootPersonIds` 或 bucket `focusPersonId` 出现 `redacted:` opaque ID、响应 `treeVersion` 与请求不一致。locator 必须覆盖“可见根+COMPLETE”“可见根+REDACTED_GAPS”“隐私根+REDACTED_GAPS”三种合法组合,并拒绝“隐私根+COMPLETE”、COMPLETE 含隐私段、REDACTED_GAPS 无隐私段、相邻同类段、首段与根可见性不符、可见根路径不从 `rootPersonId` 开始、末段不以目标结束、VISIBLE 段含 `redacted:` ID、REDACTED 段含人物 ID、响应版本或目标人物不匹配。
-
-旧结构必须明确失败:
-
-```js
-assert.throws(
- () => normalizeLineageGraphWindow([{ id: 1, children: [] }]),
- /LINEAGE_GRAPH_SHAPE_UNSUPPORTED/
-);
-```
-
-- [ ] **步骤 2:运行并确认红灯**
-
-运行两个 lineage 合同冒烟。预期因规范化与校验模块尚不存在而失败,且失败分别指向图窗口、概览或 locator,不得只报笼统 shape 错误。
-
-- [ ] **步骤 3:实现无猜测规范化**
-
-规范化只复制新合同字段、统一数组顺序和 `null`,不得出现以下兼容读法:
-
-```text
-person.id || person.personId
-generationNo || generation
-children / spouses 递归展开
-fatherId / motherId 推断 parentId
-缺失 branch 时默认“主支”
-缺失姓名时伪造“族人”
-```
-
-规范化阶段统一复制字段并按 `order`、字符串 `id` 作确定性排序;因此规范化最坏复杂度明确为 `O(N log N + E)`,不冒充线性。相同无序输入经过规范化后必须得到字节级一致的规范图。
-
-- [ ] **步骤 4:实现 O(N+E) 校验**
-
-图窗口先建立人员、家庭、关系 ID、边和 boundary 的 Map,再检查引用;全部父子关系使用颜色 DFS 或 Kahn 拓扑检查有向循环,不允许只检查 primary 或让每个节点重新扫描全图。概览校验器单次遍历 buckets 完成计数、唯一性、根隐私和目标 ID 检查;locator 校验器按 discriminator 验证根、路径完整性、请求版本和目标人物。错误一次收集完整,页面可以显示诊断状态;生成投影前必须调用 `assertLineageGraph`,显示概览或应用定位前必须调用各自 assert。
-
-- [ ] **步骤 5:验证新旧边界**
-
-运行图窗口、概览/locator、OpenAPI、响应式合同和编译审计。预期新合法响应通过,旧递归、数字 ID、隐私 ID 泄漏、跨字段计数错误与版本错配均稳定失败。
-
-### 任务 13:生成可见图投影与聚合节点
-
-**文件:**
-
-- 新建:`utils/lineage/project.js`
-- 新建:`tests/lineage-projection-runtime-smoke.js`
-
-**接口:**
-
-- `projectLineageGraph(graph, { focusPersonId }): LineageProjection`
-- 投影先通过唯一 primary 入边推导 `protectedPathPersonIds/protectedPathFamilyUnitIds`,它们是计算结果而不是第二份输入合同;不得写回规范图。
-- 输出包含可见真实节点、家庭、父子边、边界和稳定虚拟聚合节点;布局与 Scene 只消费该投影,搜索和线性列表继续消费完整规范图。聚合节点固定包含 `direction、hiddenCount、focusable、targetPersonId`:有隐藏可见成员时 `focusable=true` 且 target 是稳定人物 ID,仅含 REDACTED 时 `focusable=false、targetPersonId=null`。
-
-- [ ] **步骤 1:先写 200 子女失败测试**
-
-构造祖父家庭 12 名子女、焦点父亲排第 9、焦点位于下一代的用例,先断言投影必须保留第 9 名父亲以及祖父→父亲→焦点的完整 primary 路径。再构造一个家庭 200 名有序子女,断言任何焦点下都最多保留 5 名真实子女,其余最多形成“前 N 人/后 N 人”两个聚合节点;前后计数之和加真实人数必须等于 200。补充混合可见/隐私区间与全隐私区间:前者 target 必须选择最近可见稳定 ID,后者必须 `focusable=false、targetPersonId=null`,任何 opaque ID 都不能成为跳转目标。聚合 ID 固定由家庭 ID、方向和被折叠 order 区间生成;20 组乱序原始输入必须先经过 `normalizeLineageGraphWindow`,再断言投影结果字节级一致。
-
-- [ ] **步骤 2:实现不修改源图的 O(N+E) 投影**
-
-投影只接受已经规范化且校验通过的图,按家庭一次分组并保持规范图既有顺序,不在投影内再次排序;沿 primary 入边从焦点回溯到窗口入口,得到唯一受保护路径。这样投影阶段保持 `O(N+E)`。路径上的每个家庭以通向焦点的子女为中心选最多 5 人,其他家庭稳定选前 5 人。前后聚合节点必须包含 `direction、hiddenCount、focusable、targetPersonId`;BACK/FRONT 在对应方向选择紧邻窗口的隐藏可见成员作为 target,区间仅含隐私成员时 target 固定为 `null` 且不可点击。点击可聚焦聚合节点后把稳定 `targetPersonId` 作为新焦点请求窗口,并把旧焦点写入最多 20 条的会话历史;不存在页内无限展开、折叠或 `expandedAggregateIds`,因此任意时刻每个家庭的真实子女上限始终为 5。
-
-- [ ] **步骤 3:验证完整图与投影职责**
-
-断言完整规范图仍含 200 名真实子女,线性列表可访问全部成员;投影只含当前可见真实节点和虚拟聚合节点;连续点击 BACK 聚合会按稳定目标推进焦点且每次仍最多 5 人,回到上一焦点恢复原投影;同一输入与焦点得到同一输出。运行投影、图、响应式合同与编译审计。
-
-### 任务 14:实现确定性家庭联合点布局
-
-**文件:**
-
-- 新建:`utils/lineage/layout.js`
-- 新建:`tests/lineage-layout-runtime-smoke.js`
-- 修改:`tests/t01-relation-layout-contract.ps1`
-
-**接口:**
-
-- `layoutLineageProjection(projection, options): LineageLayout`
-- 输出:`nodeRects: Map`、`familyPoints: Map`、`generationBands`、`bounds`、`primaryForest`。
-- 世界坐标常量唯一放在 `layout.js`:`NODE_WIDTH=168`、`NODE_HEIGHT=86`、`PARTNER_GAP=20`、`SIBLING_GAP=36`、`GENERATION_GAP=124`;相机负责适配视口,页面不得转写这些值。
-
-- [ ] **步骤 1:先写三个已知缺陷和压力形状**
-
-布局测试必须精确断言:
-
-```js
-assert.equal(singleChildX("fu-103-1"), familyPointX("fu-103-1"));
-assert.deepEqual(partnerGroupMidpoint("fu-103-1"), familyPoint("fu-103-1"));
-```
-
-并覆盖 6 人、10×12、20×20、5×100、100×3、300×1、单家庭 200 子女投影、缺 12—49 代、乱序输入、单链 500 代纯逻辑和极不平衡树。当前布局必须先失败 103→106 的家庭点错位和宽支系确定性断言;连接器端点与 4rpx 间隙放到下一任务的 Scene 几何合同验证。
-
-- [ ] **步骤 2:实现线性预处理与主森林**
-
-按 `generation` 一次分组;每个孩子只用唯一 `primary` 入边参加主布局,次要收养/继亲/监护关系只参加后续连线。`anchorPersonId` 决定多配偶家庭围绕哪个主世系人物展开,禁止根据数组第一项猜测。
-
-- [ ] **步骤 3:实现自底向上的 tidy-tree**
-
-自底向上计算每个主子树与家庭单元所需宽度,自顶向下分配世界坐标。每个家庭联合点位于实际 partner 节点组中点;单子女严格与联合点同轴,多子女跨度中心严格等于联合点。多家庭单元按 `order,id` 稳定排列,不能复制同一人物节点。
-
-- [ ] **步骤 4:实现代际缺口与边界占位**
-
-代际差大于 1 时生成明确 gap band,而不是把不相邻世代压在相邻行;MISSING/REDACTED/UNLOADED 端点都有实际 Rect 和可连接锚点。
-
-- [ ] **步骤 5:验证复杂度与确定性**
-
-乱序输入 20 次的 `nodeRects/familyPoints/bounds` 必须字节级一致;500 节点布局不得出现嵌套全图扫描。运行布局合同、图合同、响应式合同和编译审计。
-
-### 任务 15:实现 Scene、空间索引和相机
-
-**文件:**
-
-- 新建:`utils/lineage/scene.js`
-- 新建:`utils/lineage/spatial-index.js`
-- 新建:`utils/lineage/camera.js`
-- 新建:`tests/lineage-scene-runtime-smoke.js`
-
-**接口:**
-
-- `buildLineageScene(projection, layout, { fontMetricsVersion }): Scene`
-- Scene 根对象精确为 `{ sceneVersion, treeVersion, focusPersonId, bounds, items }`,不接受缺字段或额外字段。
-- `createSpatialIndex(scene, cellSize = 256)`,输出 `queryRect(rect)` 与 `hitTest(point)`。
-- `createCamera(viewport, worldBounds)`、`panCamera`、`zoomCameraAt`、`fitCameraToIds`、`getLod(previousLod, scale)`。
-
-- [ ] **步骤 1:先写十条几何不变量**
-
-逐边检查路径首尾锚点、相邻折线端点完全相等、DPR 误差不超过 0.5 物理像素、单子女无孤立零长横梁、Scene edge 可反查传输 edge、主关系无穿节点、主关系交叉为零、视口外端点但路径穿视口仍被查询、四类边界有端点、Scene 原子替换不混版本。每个家庭成员连接器 ID 必须是 `family:{familyUnitId}:partner:{personId}`,每条父子边连接器 ID 必须是 `edge:{edgeId}`;`connectorStart(edge)` 必须等于家庭联合点,`connectorEnd(edge)` 必须等于实际子女顶部锚点。选中前后 Rect、布局与锚点完全不变。缺少 `sceneVersion` 必须失败;相同 `sceneVersion` 对应不同序列化 payload 也必须按版本碰撞失败,不能静默覆盖。
-
-- [ ] **步骤 2:实现纯数据 Scene**
-
-`utils/lineage/scene.js` 是 `sceneVersion` 的唯一所有者,按 `treeVersion + projectionSignature + LINEAGE_LAYOUT_VERSION + fontMetricsVersion` 生成确定性摘要;任何其他层不得拼接或递增该版本。Scene 只含世界坐标、稳定 ID、绘制类型、样式令牌和可访问文本,并可由 `JSON.stringify/parse` 无损往返;不得包含 `Map`、函数、空间索引、Vue、DOM、rpx、Canvas context 或平台对象。瞬时 `selectedId` 不属于 Scene payload,也不参与 `sceneVersion`;节点、文字、家庭联合点、连接器、聚合节点和代际标尺属于 Scene,选中光晕由 renderjs 使用独立 `selectedId` 与 Scene 人物 Rect 动态绘制,不改变 Scene payload 或 `sceneVersion`。
-
-- [ ] **步骤 3:实现连接器与空间索引**
-
-Scene 只消费任务 13 已生成的真实节点与聚合节点,不重新截断或重排子女。每个 partner 到联合点各有一条可追踪连接器;单亲联合点与锚点重合时可省略孤立零长度笔画,但保留关系反查。每条 ParentChildEdge 只有一条联合点到子女的连接器。统一网格索引按路径包围盒登记连接器,确保穿越视口的长线不会因端点在外而消失。
-
-- [ ] **步骤 4:实现 LOD 与相机**
-
-缩放范围 `0.30—2.00`;LOD 为 `0.30—0.44 / 0.45—0.74 / 0.75—1.34 / 1.35—2.00`,使用 `0.05` 迟滞。双指以手势中心缩放,搜索定位至少进入 L2;低于 12sp 的次要文字直接隐藏,不压缩到不可读。
-
-- [ ] **步骤 5:验证纯逻辑**
-
-运行 Scene 冒烟 20 次,断言命中、裁剪、LOD、相机锚点、聚合跳转目标和版本替换稳定,再运行固定验证。
-
-### 任务 16:实现视口大小的单 Canvas 组件
-
-**文件:**
-
-- 新建:`components/LineageViewport.vue`
-- 新建:`tests/t01-large-lineage-contract.ps1`
-- 修改:`tests/t01-all-states-visual-contract.ps1`
-
-**接口:**
-
-```js
-props: {
- scene: Object,
- initialCamera: Object,
- selectedId: String,
- bottomInset: Number,
-}
-emits: ["select", "focus", "camera-change", "request-boundary", "performance"]
-```
-
-`scene` 必须携带任务 15 生成的 `scene.sceneVersion`;组件没有第二个可独立传值的版本 prop,避免 payload 与版本漂移。
-
-- [ ] **步骤 1:先写组件边界合同**
-
-要求组件使用普通 Options API、包含 App-vue/H5 `renderjs`、Canvas 物理尺寸等于视口乘 DPR、同一绘制入口处理节点与边,并禁止 DOM 人物节点、DOM 拼线、全世界尺寸 Canvas、选中态改变节点宽高和逐帧跨层传输完整 Scene。合同还必须证明只改变 `selectedId` 时 Scene payload 与 `scene.sceneVersion` 不变,renderjs 仅在同一 Canvas 重绘光晕。
-
-- [ ] **步骤 2:实现 App-vue/H5 renderjs**
-
-renderjs 持有 Scene、空间索引、相机、手势、LOD 和绘制循环;业务层只在完整 `scene.sceneVersion` 变化时传入可 JSON 序列化的新 Scene。视图层先校验版本与 payload,再重建索引,最后一次性交换 Scene、索引和版本;相同版本但不同 payload 必须拒绝并保留旧 Scene。平移、缩放及惯性期间零跨层通信;只在手势结束、焦点改变或确需边界请求时通过 `$ownerInstance.callMethod` 回业务层,不做连续节流快照。
-
-- [ ] **步骤 3:实现绘制与原子替换**
-
-视口、底部 inset 或 DPR 改变时,先 `setTransform(1,0,0,1,0,0)` 重设状态,再把 backing store 设为逻辑视口乘 DPR、CSS 尺寸保持逻辑视口。每帧顺序固定为清屏、设置 DPR、应用相机矩阵、查询可见对象、先画连接器、再画联合点和节点、最后画文字与选中外光晕。字体就绪或回退字体变化后重新测量,生成新的 `fontMetricsVersion` 并请求新 Scene;新 Scene 完整校验并建立新索引后一次替换旧引用,失败继续显示旧 Scene 并上报,不得半图混画。
-
-- [ ] **步骤 4:实现 mp-weixin 适配和降级**
-
-mp-weixin 消费同一 Scene 和相机纯函数,通过平台 Canvas API 绘制;如果窗口超过平台实测能力或连续不达性能门槛,组件发出降级事件,由页面切换线性列表。不得为小程序另写关系规则。
-
-- [ ] **步骤 5:验证组件**
-
-运行大树组件合同、Scene 冒烟、响应式合同和编译审计;浏览器仅检查运行逻辑和 Canvas 尺寸,不作视觉通过结论。
-
-### 任务 17:重建 T01 页面产品结构与无障碍列表
-
-**文件:**
-
-- 新建:`components/LineageAccessibleList.vue`
-- 修改:`pages/tree/t01-tree-overview.vue`
-- 修改:`tests/t01-tree-state-contract.ps1`
-- 修改:`tests/t01-tree-state-runtime-smoke.js`
-- 修改:`tests/t01-sheet-state-document-flow-contract.ps1`
-
-**页面状态:**
-
-- `loading`:保留页面骨架和明确加载反馈。
-- `ready-graph`:Canvas 图模式。
-- `ready-list`:同一规范图的线性列表模式。
-- `empty`:仅由合法 `state=EMPTY` 进入,主操作进入 T04。
-- `error`:合同、权限、网络、版本冲突分别说明;不得混成空态。
-- 资料抽屉仅 `collapsed/half` 两档;完整资料进入 T03。
-
-- [ ] **步骤 1:先把旧全量 DOM/Grid 断言改成新结构**
-
-合同要求 `LineageViewport`、`LineageAccessibleList`、搜索、全谱概览、关系图例、两档抽屉、44dp 控件和四类边界;禁止 `tree-grid`、全量 CSS grid track、多 `` 拼线和页面内运行时 `members`。
-
-- [ ] **步骤 2:实现初始焦点和窗口请求**
-
-客户端提供焦点的顺序固定为路由 `selectedId`、当前账号绑定成员 ID;两者都没有时省略 `focusPersonId`,由后端按主始祖确定并在响应中返回实际焦点。初始 `mode=FOCUS`,`ancestorDepth=2`、`descendantDepth=2`。合法 `state=EMPTY` 直接显示空谱并允许进入 T04;只有 `state=POPULATED` 仍缺少或引用不到有效 `focusPersonId` 时才显示合同错误,客户端不从 nodes 数组猜成员。
-
-- [ ] **步骤 3:实现搜索、聚合跳转和焦点历史**
-
-单击 VISIBLE 人物节点只选择并打开半屏抽屉;双击、居中操作、搜索结果或可聚焦的“前 N 人/后 N 人”聚合节点才改变焦点并请求新窗口。REDACTED 节点只显示通用隐私说明,不允许双击、居中、进入详情或成为焦点;不可聚焦聚合节点也不发请求。`focusPersonId` 与聚合 `targetPersonId` 都只能使用稳定 VISIBLE 人物 ID,不在当前 Scene 追加更多真实子女。会话内保存最多 20 条 `{ focusPersonId, treeVersion, matrix }`,只用于“回到上一焦点”,不写本地存储。
-
-- [ ] **步骤 4:实现独立全谱概览**
-
-概览以当前窗口 `treeVersion` 请求 `/lineage/tree/overview` 的“世代×支系”聚合,不把全家谱所有人物缩成微型图。只有 bucket 提供 VISIBLE 稳定 `focusPersonId` 时才允许点击并请求局部窗口;隐私桶的目标为 `null`。收到 `409 TREE_VERSION_CHANGED` 时保留当前焦点,先刷新窗口,再用新版本重取概览,绝不混合两个快照。
-
-- [ ] **步骤 5:实现抽屉、列表和返回优先级**
-
-抽屉吸附完成后更新 `bottomInset` 并把选中节点移入剩余安全视口。Android 返回依次关闭搜索/概览/抽屉、回退焦点历史、最后 `goBack`。图和列表共享选中人物、焦点、树版本、已加载边界、焦点历史与搜索结果,不维护页内聚合展开状态。
-
-- [ ] **步骤 6:验证页面状态**
-
-运行三个 T01 聚焦合同、两个纯逻辑冒烟、响应式合同和编译审计;检查普通页面内容流、弹层 max-height、内部滚动和触控面积未回归。
-
-### 任务 18:接入新接口、mock 和跨页变更版本
-
-**文件:**
-
-- 修改:`utils/api.js`
-- 修改:`data/mock.js`
-- 修改:`pages/tree/t01-tree-overview.vue`
-- 修改:`pages/tree/t03-member-profile.vue`
-- 修改:`pages/tree/t04-add-relative.vue`
-- 修改:`pages/tree/t05-edit-member.vue`
-- 修改:`pages/tree/t06-edit-relationship.vue`
-- 修改:`pages/tree/t07-member-directory.vue`
-- 修改:`utils/navigation-routes.js`
-- 修改:`tests/navigation-flow-contract.ps1`
-- 修改:`tests/t03-t08-member-flow-contract.ps1`
-- 修改:`tests/lineage-graph-contract-runtime-smoke.js`
-- 新建:`tests/t01-navigation-integration-contract.ps1`
-
-**接口:**
-
-```js
-appApi.getLineageWindow(genealogyId, query)
-appApi.getLineageOverview(genealogyId, treeVersion)
-appApi.locateLineagePerson(genealogyId, personId, treeVersion)
-appApi.searchLineagePeople(genealogyId, keyword, cursor, limit)
-appApi.createRelative(genealogyId, personId, payload, treeVersion)
-appApi.updateLineagePerson(genealogyId, memberId, payload, treeVersion)
-appApi.updateRelationship(genealogyId, relationshipId, payload, treeVersion)
-```
-
-- [ ] **步骤 1:先改 API 合同并确认旧适配失败**
-
-测试禁止 `toTreeNode`、`.map(toTreeNode)`、`treeMembers`、`id || personId`、客户端 `x/y` 和数字 ID;要求七个新方法、窗口与 overview 各自的查询参数白名单、overview 必填 `treeVersion`、所有三个写方法的 `If-Match` 和规范化/校验调用。REDACTED opaque ID 进入 FOCUS、locator、搜索、写接口或聚合 target 必须在客户端边界失败。成员更新还必须以权限能力和当前 `treeVersion` 为前置条件,旧的无版本人物更新接口不能作为兼容回退。
-
-- [ ] **步骤 2:原子替换旧 API 与 mock**
-
-删除 `getTree` 的递归数组返回和旧 `treeMembers`,mock 直接提供合法 `LineageGraphWindow`、overview、locator、人员详情和版本化 mutation result。所有现有消费者同轮迁移,不能保留双读。
-
-- [ ] **步骤 3:实现边界增量与版本冲突**
-
-展开 UNLOADED 只携带当前 boundary cursor 和 treeVersion;新窗口校验成功后原子合并或替换。收到 `409 TREE_VERSION_CHANGED` 时保留当前焦点,提示数据已更新并用 locator 重新定位,不能把新节点配旧边。
-
-- [ ] **步骤 4:实现 T04/T05/T06 完成回流**
-
-写成功结果带新 `treeVersion` 进入领域响应,但导航一次性结果仍只传 `operation/entityId/refresh`;T01 收到新增亲属或关系更新后通过 locator 或新窗口响应定位 `entityId`。取消、写失败、权限失败和版本冲突都不得生成成功导航结果。
-
-T05 的真实更新必须在本步骤一次性拆分宿主页身份 A 与编辑实体 B,不提前留下兼容字段:T03 从自身初始查询保存不可变 `routePersonId=A`,页内活动成员为 `activePersonId=B`;T05 路由必填参数精确改为 `genealogyId/personId/memberId`,其中 `personId=A` 只表达宿主 T03 身份,`memberId=B` 只表达被编辑成员。T03 打开 T05 时传入两者,T05 源码立即别名为 `hostPersonId` 与 `editedMemberId`;API 只能以 `editedMemberId` 写入,完成目标只能以 `hostPersonId` 匹配 T03。删除旧的“T05 `personId` 同时代表编辑对象”合同,禁止 `memberId || personId` 双读,旧 URL 因缺少 `memberId` 必须失败。
-
-真实写成功后,T05 以目标 `{ genealogyId, personId: hostPersonId }` 和一次性成员更新结果返回;结果的 `entityId` 必须是 `editedMemberId`。同轮给 T03 增加对应结果操作:仅当 `entityId` 等于当前活动成员时重新读取该成员,不调用 `openRelative`,不改变 URL、轨迹或索引;实体不匹配时失败关闭。测试必须覆盖 A/B 正常回流只刷新 B、来源宿主 C 到目标 A 被拒绝且零导航/零结果、目标误传 B 被拒绝、API 实参只能是 B、写失败或 409 零结果,以及深链 T05 要求 A 与 B 相同后才能构造 T03(A)。当前 `personId=A/memberId=B` 方案复用导航网关已有同名上下文门禁;`parentParamMap` 仍只负责无历史时构造父页,不能扩张成完成结果身份映射。
-
-`tests/t01-navigation-integration-contract.ps1` 验证 T01 与导航网关之间的焦点回流、取消和版本冲突;`tests/t03-t08-member-flow-contract.ps1` 验证宿主页/编辑实体双身份与 T03 刷新不改轨迹。真实写结果会改变路由允许操作和页面消费者,因此必须在同一合同迁移中同步收紧 `tests/navigation-flow-contract.ps1` 与路由注册表,删除任务 6 的“本地预览无结果”旧断言;不能让运行时接受新合同而校验器仍只允许旧合同。
-
-- [ ] **步骤 5:验证接口与回流**
-
-运行 OpenAPI、图、布局、Scene、导航与 T01 聚焦合同,再运行响应式合同和编译审计。新有效路径通过,旧递归输入和旧字段明确失败。
-
-### 任务 19:完成 T01 MuMu、性能与三人终审
-
-**文件:**
-
-- 修改:`docs/家谱项目全量治理设计.md`
-- 修改:`docs/家谱项目全量治理实施计划.md`
-- 修改:`docs/项目当前总览.md`
-- 修改:`docs/接口与页面映射总表.md`
-
-- [ ] **步骤 1:运行全部自动化验证**
-
-运行全部 `tests/*.ps1`、全部 lineage Node 冒烟、导航 Node 冒烟和密码策略冒烟。预期全部退出码为 `0`,Vue 覆盖仍为 `64/64`,`100% 100% no-repeat` 与 Vue 直接 `border-image-slice` 扫描仍为 `0`。
-
-- [ ] **步骤 2:执行 T01-MUMU-01 至 T01-MUMU-10**
-
-1. 默认焦点上二代/下二代和 103→106 连线;
-2. 单指平移、双指缩放、按钮缩放和四级 LOD;
-3. 搜索或概览定位第 10、50、100、300 代;500 代单链只执行纯逻辑测试;
-4. 200 子女聚合、前后人数、聚合跳转、返回原焦点和祖先主路径连续性;
-5. 多配偶家庭联合点及对应子女归组;
-6. MISSING、REDACTED、UNLOADED、FAILED 四类端点;
-7. collapsed/half 抽屉、图/列表切换和全谱概览;
-8. T03/T04/T06/T07 的进入、返回、取消、完成和重复进入;
-9. 空谱、无权限、网络失败、版本冲突和异常图;
-10. 60 秒连续操作、20 次聚合跳转与搜索、自动几何探针和同场景逐边视觉探针。
-
-所有视觉证据只来自当前 MuMu;忽略系统水印,不调整设备。
-
-- [ ] **步骤 3:验证性能门槛**
-
-- 单窗口不超过 500 人;
-- `dataReady`(规范图校验完成)到 `interactive`(首帧绘制完成且命中索引可用)不超过 800ms;
-- 输入到反馈 p95 不超过 100ms,从视图层触摸时间戳量到下一完成帧;
-- 持续手势帧耗时 p95 不超过 32ms,由 renderjs 的 `requestAnimationFrame` 记录;
-- 不连续出现两帧超过 100ms;
-- 内存先预热 3 轮,再在相同空闲点比较 20 次聚合跳转与返回后的驻留值,相对稳定基线增长不超过 15%。
-
-每项 MuMu 时延至少采样 30 次,并使用 nearest-rank 计算 p95;T01 不单独承担全 App 冷启动门槛。自动几何探针与同一场景逐边视觉探针都必须为零违规。
-
-不达标时优先缩小窗口、减少可见对象或降级到线性列表;不得提高门槛、压缩字号或改成全量巨大 Canvas。
-
-- [ ] **步骤 4:三人独立终审**
-
-三人分别从真实数据、几何连续性、交互、视觉完整性、接口严谨性、无障碍、性能和维护成本反向质询。只有十条几何不变量、全部性能门槛、MuMu 十组矩阵和自动化合同同时通过,才把 T01 标记完成。
-
----
-
-## 第三阶段:认证、TAC 与短信闭环
-
-### 任务 20:建立认证 OpenAPI 硬门禁
-
-- [x] **步骤 1:先写失败合同并汇总后端问题单**
-
-`tests/auth-tac-openapi-contract.ps1` 已对受保护 JSON/YAML 同时检查三个公开认证场景、统一 `SmsCodeSecret`、`validToken`、密码登录票据,以及验证请求的必填字段、关闭额外字段和 provider discriminator。当前精确输出为 `AUTH-TAC-OPENAPI-CONTRACT BLOCKED`:密码登录无票据;`VerificationCheckBody` 缺 provider 分支闭包;TianAi 与系统图片 payload 均未关闭额外字段;生产短信码尚未原子升级为 6 位,公共发码仍错误包含 `APP_PHONE_CHANGE`。真实 `APP_REGISTER` challenge 还返回 HTTP 500 空响应。对应问题固定为 `API-AUTH-TAC-001`—`004` 与 `API-PHONE-001/002`,不得通过放宽测试或修改受保护导出变绿。
-
-### 任务 21:接入受保护 TAC 资产与严格适配器
-
-- [x] **步骤 1:建立唯一场景与票据 owner**
-
-`utils/auth-verification.js` 精确持有 `APP_SMS_LOGIN/APP_REGISTER/APP_FORGOT_PASSWORD`、4 位短信码、require 和 verify 响应边界;`static/tac/js/jiapu-tac-adapter.js` 是 TianAi challenge/proof/verify 的唯一映射层。未知 provider/type、`required=false` 却无票据、空 token、scene 或 subject 漂移全部失败关闭。
-
-- [x] **步骤 2:建立真实 renderjs 浮层**
-
-`components/TacVerification.vue` 加载后端提供且哈希锁定的 CSS/JS/图片,不修改四个供应商文件。浮层以严格 2xx JSON XHR 请求 challenge/verify,覆盖空体、非对象、HTTP 错误、超时、主动 abort、重复成功/取消和迟到 generation 回调;只有服务端 `passed=true + validToken` 才向页面完成。
-
-- [x] **步骤 3:建立壳层无障碍预检**
-
-浮层已补齐 dialog 命名与说明关联、初始聚焦、Tab 圈定、Escape/Android 返回、焦点恢复、原生刷新/关闭、48px 目标和小视口内部滚动。`tests/tac-shell-accessibility-contract.ps1` 与 `tests/auth-accessibility-static-contract.ps1` 只证明静态壳层,不得冒充 TianAi 拖动本身支持 TalkBack。
-
-### 任务 22:接通 A01/A04/A05 的认证客户端
-
-- [x] **步骤 1:短信登录、注册和找回密码测试先行接线**
-
-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:收紧认证传输生命周期**
-
-`utils/api.js` 的 `createRequestController/isRequestCancelled` 是认证与已审查业务请求共用的唯一生命周期入口;严格请求只接受 HTTP 200 和带整数 `code` 的 envelope,超时统一为 15 秒。登录、注册和 challenge 等有实体响应要求 `data`;短信发送与找回密码的 `RVoid` 没有声明 `data` 必填,`requestAuthVoid` 把省略 `data` 与 `data:null` 都归一为 `null`。返回或卸载先拒绝等待 Promise 再 abort RequestTask,迟到 native fail 不得覆盖 `REQUEST_CANCELLED`;旧认证专用公开入口已原子删除,按钮在进行中锁定并显示明确文案,不存在伪成功或本地验证码。
-
-- [x] **步骤 3:完成客户端自动化验证**
-
-认证/TAC 聚焦合同、renderjs/adapter/API/场景纯 Node 冒烟、响应式、文档流和编译审计已通过;后续任务 24—35 纳入后,最新项目总证据为 PowerShell `126/140`、Node 语法 `47/47`、纯 Node `19/19`、活动 Vue 脚本模块 `64/64`。十四项红灯全部是显式发布门禁,不是可删除测试:T01、认证 OpenAPI、家谱工作区 OpenAPI、G03 原子创建 OpenAPI、G03 客户端激活、M06 帮助 OpenAPI、个人资料读取 OpenAPI、个人资料写入 OpenAPI、通知读取 OpenAPI、通知已读写入 OpenAPI、M10 服务端退出 OpenAPI、M04 密码凭证 OpenAPI、M05 手机号换绑 OpenAPI 与 Android 认证无障碍证据。
-
-### 任务 23:关闭认证外部门禁并完成原生发布验收
-
-- [ ] **步骤 1:后端关闭 `API-AUTH-TAC-001`—`004`**
-
-验证码中心成为 provider-neutral 唯一 owner:session 与 challenge 绑定 tenant/client/scene/canonical subject;provider evidence 只由服务端核验;票据绑定 method/assurance/audience。短信端在同一事务中完成 `ISSUED → CONSUMED` 和唯一 outbox,相同幂等键返回原结果,并发或重放最多产生一个发送任务。修复线上空 500,发布同版本 JSON/YAML 后重新运行 OpenAPI 门禁。
-
-- [ ] **步骤 2:实现可访问且不降风控的替代路径**
-
-P0 是同一验证中心和可恢复的文字/中继 `MANUAL_REVIEW`,不是免验证。各 scene 定义独立身份或号码控制证据;案件不可改写原 subject/scene,具备去重、RBAC、限额、审计、服务时段、容量和 SLA,高风险找回/换号双人复核。坐席只提交决定;用户重新进入原流程时,由验证中心激活同一短时单次票据。中国大陆非交互风控供应商限时 POC 达标后才可成为默认自动路径;音频另做可懂度、听障覆盖和 ASR POC,不能单独上线。设备断言只有在同一 subject 的已认证会话绑定私钥、服务端 nonce、RP/App 绑定、`userVerification=required`、检查撤销且防重放时才可独立放行;设备指纹和完整性只能加权。
-
-- [ ] **步骤 3:切换远端并完成 H5/Android 验收**
-
-后端门禁全绿后才把 `runtimeConfig.mode` 从 `mock` 切为 `remote`。验证正式 H5 域名 CORS、真实正常/过期/重放/限流/供应商故障、前后台倒计时恢复和并发幂等;在用户现有 MuMu 中由三人共同完成 A01/A04/A05 默认、错误、取消、重复进入、Android 返回、TalkBack、外接键盘与非拖动替代路径。证据写入 `tests/manual/tac-android-accessibility-evidence.json` 后运行发布门禁;浏览器截图不得替代。
-
-## 第四阶段:领域上下文与独立真实接口
-
-### 任务 24:建立会话与当前家谱上下文基础
-
-- [x] **步骤 1:测试先行收紧词法身份与账号隔离**
-
-`utils/genealogy-context.js` 只接受无边界空白的非空字符串 ID,拒绝可能已经失真的 JavaScript number、重复列表、对象和控制字符;损坏存储立即清理。`utils/session.js` 在损坏令牌、退出和令牌切换时同步清理家谱上下文,同一令牌保存不误清。
-
-- [x] **步骤 2:撤权与显式无权目标失败关闭**
-
-首次没有历史选择和失效标记时才允许建立首个可用上下文。历史选择从调用方给定的新列表消失或显式请求的家谱不可用时,`reconcileCurrentGenealogyId` 清空 ID 并持久写入 tombstone,后续重载继续失败关闭;只有用户显式选择、退出或账号切换才清除标记。G01 显示“当前家谱已不可用”并要求用户明确选择,页面不得用 `currentGenealogy || list[0]` 掩盖失效。真实权限变化的 onShow/事件刷新仍属于后续 workspace,不把纯函数闭环夸大为服务端撤权已实时生效。
-
-### 任务 25:接通 M07 真实反馈客户端
-
-- [x] **步骤 1:锁定 OpenAPI 与 wire payload**
-
-`tests/feedback-openapi-contract.ps1` 同时保护 JSON/YAML 中的 `POST /genealogy/app/feedback`、SaToken 与唯一 `FeedbackBody`。`appApi.submitFeedback` 只接受三个自有普通数据字段;`feedbackContent` trim 后非空,`feedbackType/contactInfo` 为无枚举可选字符串,空值不发送。调用方请求选项只允许 `requestController`,不能关闭认证头。remote 精确要求 HTTP 200 与整数成功 `code`;响应 schema 没有声明 `data` 必填且页面不消费返回实体,因此反馈请求不复制认证接口的 data 必需规则。mock 抛 `WRITE_UNAVAILABLE` 且不发请求。
-
-- [x] **步骤 2:完成防重复、异常与可访问状态机**
-
-M07 以提交前规范快照锁定请求,提交中禁用类型、内容、联系方式和按钮;成功后保留已提交内容并把该快照提升为 baseline,原样禁止重提,编辑后恢复 ready,改回快照恢复成功态。成功与 uncertain 回流都再次比较当前快照,迟到输入不冒充已提交。超时、断网、意外 2xx/3xx、HTTP 408/5xx 和响应无效进入 `uncertain`,锁定同一快照且不提供原样重试;只有确定拒绝进入可重试 error。反馈类型明确选填,原生按钮有 group 名称、`aria-pressed`、44dp 目标和完整 reset,必填失败聚焦内容框;页面状态机已由纯 Node 直接执行验证,不再只有静态 token 断言。unknown 锁不跨重启持久化,避免保存反馈隐私或形成无期限锁;真正跨重启防重交给未来后端幂等合同。
-
-- [ ] **步骤 3:真实服务与 MuMu 验收**
-
-该步骤依赖任务 23 关闭认证远端门禁。切换 remote 后验证真实登录态、成功 envelope、401、业务拒绝、超时未知结果和卸载取消;在 MuMu 检查键盘、TalkBack、长文本、错误回执和系统返回。浏览器或静态合同不得替代。
-
-### 任务 26:建立家谱工作区远端硬门禁
-
-- [x] **步骤 1:三人只读核对 G01/G05、线上 OpenAPI 与部署行为**
-
-唯一读取 owner 固定为 `/genealogy/app/genealogies/mine` 和 `/genealogy/app/genealogies/{genealogyId}/overview`;首批不同时请求语义重复的 `/{genealogyId}`。线上 `RListAppGenealogyVo/RAppGenealogyVo/AppGenealogyVo` 虽已类型化,但均无 `required`;响应 `genealogyId` 为 `integer/int64`,`roleType/status/memberStatus` 无枚举,且没有 `canView`。无令牌只读实测三条接口均为 HTTP 200、JSON `{code:401,msg,data:null}`,与文档声明的 401 string 不一致。缺少 security 注解和媒体声明 `*/*` 作为发布文档质量问题记录,不把它们单独虚报为已发生泄漏。
-
-- [x] **步骤 2:先写失败合同并固定最小闭包**
-
-`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` 用 `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**
-
-新 adapter 只 pick 已声明字段并允许未知额外字段;任何 unsafe number、空 ID/名称、重复 ID、错误 data 形状、未知角色或 capability 缺失都失败关闭。G01 在 `onShow` 或统一失效事件中取消旧请求、严格读取 `/mine` 后才 reconcile;网络/5xx 保留当前现场,明确撤权才写 tombstone。G05 加载 `/overview` 前清空上一家谱数据并取消迟到响应,远端失败不回退 fixture。地点、堂号、人数和简介可选且诚实降级;若产品坚持展示线上未提供的来源、管理者、认证、始祖、支系、更新时间和激活人数,则另立合同,不从 mock 猜值。
-
-- [ ] **步骤 5:真实账号与 MuMu 验收**
-
-用至少两个有效账号验证本人列表、跨账号 ID、撤权、删除、typed 400/401/404/429/500、超时、畸形 JSON、快速切谱与离页取消;再在用户现有 MuMu 中验证加载/空/失败/失效/重选、G01 列表与切换弹层、G05 权限入口和 Android 返回。浏览器和静态合同均不能替代。
-
-### 任务 27:建立 M06 帮助内容远端硬门禁
-
-- [x] **步骤 1:三人只读核对 M06、线上 OpenAPI 与部署行为**
-
-线上列表 `GET /genealogy/app/help-articles` 返回 `RListHelpArticleVo`,每项 `HelpArticleVo` 已同时包含分类、标题与完整正文;详情端点因此不是当前单页手风琴闭环的必要依赖。受保护双导出仍返回通用 `ListResult/RList`,线上 wrapper 与 VO 又全部没有 `required`,正文没有纯文本/富文本语义,也没有只返回已发布内容和响应顺序的保证。匿名实测列表、带分类列表和详情均返回 HTTP 200+业务 `code=401`,与线上文档的 HTTP 401 string 不一致。源码还确认 M06 只有本地问题、筛选空态和 ``,没有加载、错误、取消、重试或完整无障碍语义。
-
-- [x] **步骤 2:反向质询并选定 list-only 最小闭环**
-
-一位评审最初要求字符串 `helpId` 加列表/详情二次读取,另一方案指出列表已带正文,M06 没有深链、写操作或跨刷新实体身份。三人最终一致选择列表唯一 owner:adapter 只投影 `helpCategory/helpTitle/helpContent`,不读取或暴露 `helpId`,因此当前 JSON int64 只作为未来详情债务。分类从列表标签按首次出现顺序派生,“全部”由客户端拥有;每次响应先分配 generation+ordinal 展示键,再做搜索/筛选,变更筛选或刷新前清空展开项,测试即可关闭 index 错绑反例。
-
-- [x] **步骤 3:先写失败合同并固定最小 schema**
-
-`tests/help-center-openapi-contract.ps1` 同时读取受保护 JSON/YAML,要求列表 200 精确引用 `RListHelpArticleVo`、SaToken、required `code/data` 和 `HelpArticleVo[]`;每项 required `helpCategory/helpTitle/helpContent`,三项为非空字符串,正文声明 plain-text。当前输出 `HELP-CENTER-OPENAPI-CONTRACT BLOCKED`;不得手改双导出或用 live-only 字段写 adapter。
-
-- [ ] **步骤 4:后端关闭 `API-M06-001`—`003`**
-
-`001` 提供专用列表响应与 required 最小闭包;`002` 明确分类为可直接展示标签、正文首版为纯文本、用户列表只含已发布文章且数组顺序就是展示顺序;`003` 统一 SaToken、JSON 媒体、HTTP 401 或业务 401 的文档与部署行为。后端从同一 Apifox 版本重新导出 JSON/YAML 并通过门禁;详情 `helpId` 改为字符串仅在未来消费详情时要求,不阻塞当前 M06。
-
-- [ ] **步骤 5:门禁通过后测试先行接入页面**
-
-先写 adapter 和页面状态失败测试:allowlist 投影必须丢弃即使已失真的 `helpId`;过滤不重编号,搜索/分类/刷新先清展开,旧 generation 迟到不替换。随后实现唯一可取消列表请求、加载、服务端空、搜索无结果、失败重试、认证失效、动态分类和纯文本展开;失败不得偷偷回退本地 FAQ。分类与问题使用原生按钮,补齐 `aria-pressed/aria-expanded/aria-controls`、状态播报和 44dp 目标,不接详情、分页、封面、浏览量或富文本。
-
-- [ ] **步骤 6:真实账号与 MuMu 验收**
-
-任务 23 关闭认证门禁后,验证有效/失效令牌、只发布与顺序、空列表、畸形行、5xx、超时、重试、快速刷新和卸载取消;再在 MuMu 检查搜索、分类、长正文、系统字号、TalkBack、焦点、Android 返回和 M06→M07。浏览器与静态合同不能替代。
-
-### 任务 28:建立个人资料读取远端硬门禁
-
-- [x] **步骤 1:三人只读核对 M01/M02/M03、线上 OpenAPI 与部署行为**
-
-唯一读取路径为 `GET /genealogy/app/auth/profile`。受保护双导出仍返回通用 `ObjectResult/RObject`;线上已改为 `RAppProfileVo → AppProfileVo`,但 envelope 与实体没有 required,手机号无 pattern,姓名/邮箱没有长度和格式边界,operation 也缺有效 security/clientid。匿名实测返回 HTTP 200+业务 `code=401`,与文档 HTTP 401 string 冲突。页面仍直接消费 `{name,phone,role}` fixture:M01 把资料错误连带整页入口隐藏并用 query 制造假错误,M02 把昵称冒充真实姓名,M03 在 setup 时固化手机号。
-
-- [x] **步骤 2:反向质询并固定最小隐私投影**
-
-三人先比较“四项 wire 字段全 required”和“仅 phone required”。最终选择后者:合法旧账号可能没有昵称、实名或邮箱,三项未设置时唯一省略;出现则必须是非空规范值。未来 PUT 只提交 dirty fields 和省略保持原值必须由写批次另证,不能用未知写语义反向扩大 GET 门禁。首批完全丢弃 `userId/avatar/status` 等未消费字段,因此 int64 与状态字典不阻塞;M01 家谱级“创建者”删除。原始手机号只在 adapter 局部校验并立即变成掩码与读屏尾号,不能进入页面、缓存、错误、日志或路由。
-
-- [x] **步骤 3:先写失败合同并固定最小 schema**
-
-`tests/profile-openapi-contract.ps1` 同时读取受保护 JSON/YAML,要求 GET 200 精确引用 `RAppProfileVo`、SaToken、required `code/data` 与 `AppProfileVo`;实体只 required canonical 11 位 `phone`,可选 `nickName/realName/email` 出现时分别满足 1—30、1—30、email 且 1—100。当前输出 `PROFILE-OPENAPI-CONTRACT BLOCKED`,不手改双导出或写 live-only adapter。
-
-- [ ] **步骤 4:后端关闭 `API-PROFILE-READ-001`—`003`**
-
-`001` 提供专用响应与最小 required/type/length/format;`002` 把“属性省略”固定为三项可选资料唯一未设置形态,并确认返回 canonical 原始手机号供客户端立即掩码;`003` 统一 required clientid、SaToken/security、JSON 媒体、HTTP 401 或业务 401 的文档与部署行为。后端从同一 Apifox 版本重导 JSON/YAML,门禁通过后才开始代码批次。
-
-- [ ] **步骤 5:门禁通过后测试先行接入 M01/M02/M03**
-
-先写 normalizer 测试,证明 optional 省略变内部空串、出现 null/空白/超长/非法邮箱失败,超大 `userId/avatar` 被丢弃,明文手机号不在输出或异常中;mock/remote 走同一模型,错误 runtime config 失败关闭。再实现严格、可取消 GET:M01 只替换身份卡且移除假 query 状态和 fixture 角色;M02 填表后才设 baseline,保存仍为本地校验;M03 只局部加载手机号。通知数量不得与真实资料混装,M05 的当前号码在 remote 发布前也迁移同一掩码 owner 或隐藏。原子更新禁止 API 的旧测试断言,并补局部错误、重试、取消、迟到响应和原生按钮无障碍。
-
-- [ ] **步骤 6:真实账号与 MuMu 验收**
-
-任务 23 关闭认证门禁后,用有/无可选资料账号验证加载、掩码、认证失效、畸形数据、5xx、超时、重试、账号切换和取消;MuMu 检查长昵称、系统字号、TalkBack 尾号播报、焦点、M02 键盘/错误、Android 返回和 M03→M04/M05。静态审查不能替代。
-
-### 任务 29:建立通知读取远端硬门禁
-
-- [x] **步骤 1:三人只读核对 N01/N02/M01/G01、线上 OpenAPI 与部署行为**
-
-线上提供 `GET /genealogy/app/notifications` 与 `GET /genealogy/app/notifications/unread-count`;受保护双导出只有通用通知列表且缺 unread-count,线上 `RListNotificationVo/NotificationVo/RLong` 又无 required、枚举、长度、完整正文、顺序或容量保证。四个页面当前分别克隆 fixture:N01/N02 的本地已读不能同步,M01/G01 的非响应式未读数也可能长期不一致。匿名 list/count 实测都是 HTTP 200+业务 `code=401`,与线上文档声明的 HTTP 401 string 不一致;operation 只有文字鉴权,没有有效 security/clientid。
-
-- [x] **步骤 2:反向质询并固定无 ID 的完整活动集合**
-
-“只取最新 200 条”和“无分页完整列表”不能并存,否则角标可能指向用户永远看不到的未读项。三人最终固定首版活动集合本身最多 200 条,列表无筛选完整返回且最新优先,未读数精确统计同一集合的 `UNREAD`;跨请求并发变化允许瞬时不等。读取 adapter 只公开完整标题/正文、时间、读状态和 generation+ordinal `snapshotKey`,所有服务端 ID、发送者和业务目标字段全部丢弃。N02 只读当前内存快照;无快照时提示返回消息中心,不虚构服务端过期原因。
-
-- [x] **步骤 3:先写失败合同并固定最小 schema**
-
-`tests/notification-read-openapi-contract.ps1` 要求两条 GET 的 SaToken、required clientid、专用 `RListNotificationVo/RNotificationUnreadCount`,两层 `code/data` required。列表允许空、`maxItems` 为 1—200 之间的明确上限并在语义上保证完整活动集合最多 200;每项 required `noticeTitle/noticeContent/publishTime/readStatus`,标题 1—50、完整纯文本正文 1—1000、带时区 RFC3339、状态枚举 `READ/UNREAD`;计数为 0—200 int32 且与同一活动集合一致。当前输出 `NOTIFICATION-READ-OPENAPI-CONTRACT BLOCKED`。
-
-- [ ] **步骤 4:后端关闭 `API-NOTIFICATION-READ-001`—`003`**
-
-`001` 提供专用响应、最小 required/type/length/enum;`002` 明确活动集合最多 200、完整返回、最新优先、完整纯文本正文和 count/list 同域;`003` 统一 SaToken、required clientid、JSON 媒体、HTTP 401 或业务 401 的文档与部署行为。后端必须从同一 Apifox 版本重新导出 JSON/YAML,不能由客户端手改受保护文件。
-
-- [ ] **步骤 5:门禁通过后测试先行实现读取**
-
-先写 normalizer、内存快照和页面状态负例,证明 unsafe/重复服务端 ID、sender 与 biz 字段不进入页面,筛选不改变 key,旧 generation、重启、退出和账号切换不能别名。再实现严格可取消列表/计数请求:N01 摘要最多 160 字素并支持长词换行,N02 展示完整正文;M01/G01 文案改为“未读消息”,视觉角标为 `99+` 但读屏播报真实数。删除通用 G10/审核 CTA、目标按钮、查询参数假失败、fixture 未读数和所有本地伪已读,不接写端点。
-
-- [ ] **步骤 6:真实账号与 MuMu 验收**
-
-任务 23 关闭认证后验证 0/1/99/100/200 条、最新优先、并发新消息、畸形正文/时间/状态、401、5xx、超时、取消、刷新和账号切换;MuMu 检查系统字号、TalkBack、键盘/焦点、长标题正文、错误重试、N01→N02、Android 返回和 M01/G01 角标。浏览器与源码审查不能替代。
-
-### 任务 30:建立通知已读写入远端硬门禁
-
-- [x] **步骤 1:三人独立核对单条与全部已读的身份和并发语义**
-
-线上两个 POST 都存在,但 `notificationId` 在列表和 path 中仍为 int64,JavaScript 无法保证无损;`RVoid` 没有 required,文档也未定义重复调用、超时结果未知、跨账号、不存在、read-all 截止点和并发新消息。读批次因此不能先留本地 mutation 充数,写批次也不能直接把页面 `snapshotKey` 当服务端 ID。
-
-- [x] **步骤 2:反向质询并固定私有身份迁移**
-
-写入通过后,唯一 notification controller 才从同一列表响应私有保留 `notificationId`,页面、路由、日志和持久缓存仍只接触 `snapshotKey`。ID 固定为 1—128 位 URL-safe opaque string,列表字段与 path 使用同一个 pattern;禁止解析 int64 后 `String()`。单条和全部已读对当前账号幂等;不存在与跨账号单条 ID 统一为 404 `NOTIFICATION_NOT_AVAILABLE`,read-all 只覆盖服务端接收请求时已经存在的活动通知,之后新消息保持未读。
-
-- [x] **步骤 3:先写独立失败合同**
-
-`tests/notification-read-state-openapi-contract.ps1` 要求两个 POST 的 SaToken、required clientid、无 request body、200 精确 `RVoid` 且整数 `code` required;`NotificationVo.notificationId` 与 path ID 同为 required 的 1—128 位 URL-safe string。当前输出 `NOTIFICATION-READ-STATE-OPENAPI-CONTRACT BLOCKED`,与读取红灯互不冒充。
-
-- [ ] **步骤 4:后端关闭 `API-NOTIFICATION-STATE-001`—`003`**
-
-`001` 原子迁移无损 notification ID 与 required `RVoid`;`002` 固定幂等、重复/重试、read-all 截止点、并发/多端收敛;`003` 固定 401、404 `NOTIFICATION_NOT_AVAILABLE`、5xx、超时和 count/list 刷新规则。后端提供同版本双导出并以两个账号证明对象级隔离。
-
-- [ ] **步骤 5:读取批次完成后单独实现写入**
-
-先写 controller 映射、重复点击、迟到响应、超时未知和跨 generation 负例;随后原子删除首版内部丢弃 ID 的实现及 N01/N02 所有 clone mutation。N02 打开后由 controller 标记、N01 提供全部已读;成功或结果未知都重新取得列表与计数收敛,不做本地 `count - 1`。离页取消只停止等待,不宣称服务端未执行;同一 snapshot 防重复提交。
-
-- [ ] **步骤 6:真实账号与 MuMu 验收**
-
-验证单条重复调用、全部重复调用、超时后重读、并发新消息、多端读状态、跨账号 ID、被删除消息、401 和服务异常;MuMu 检查提交中禁用、播报、失败/未知回执、N01/N02/M01/G01 收敛与 Android 返回。没有有效账号和原生证据时保持发布红灯。
-
-### 任务 31:建立 M02 个人资料写入远端硬门禁
-
-- [x] **步骤 1:三人只读核对页面、本地双导出与线上 PUT**
-
-M02 目前把同一个 `currentUser.name` 同时写入 nickName/realName,email 固定空,保存只跑 500ms 定时器;没有真实加载、错误、认证失效、结果未知或并发冲突。受保护 PUT 使用旧 `ProfileUpdateBody`,缺 realName/email 且示例含 schema 外字段,成功为 generic RObject。线上改为 `AppProfileUpdateBody → RAppProfileVo`,却没有 required/minProperties/关闭额外字段/merge/version,200 媒体为 `*/*`,operation 无 security/clientid,只列 200/401。GET profile 门禁仍红,因此 baseline owner 也尚未可用;未调用真实 PUT。
-
-- [x] **步骤 2:交叉反驳并选择唯一 merge PUT**
-
-三人否决“三字段全量 PUT”,因为它会覆盖其他端的未触碰字段,也无法代表 avatar/sex/birthday。PATCH 语义更正统,但在后端能够以 presence-aware DTO 和集成测试证明现有 PUT 为原子字段 merge 时,新增路由是无必要扩张;因此保留 PUT 且不发布 PATCH。省略字段保持,nickName 只允许脏的非空值,realName/email 以请求精确空串清空;null/空白非法,响应把清空字段省略。并发沿用 T01:body 返回唯一 opaque profileVersion,PUT 用 required If-Match,409 稳定码;不在 body 重复 version。
-
-- [x] **步骤 3:先写失败合同锁定最小闭包**
-
-`tests/profile-update-openapi-contract.ps1` 要求唯一 PUT、SaToken、required clientid/If-Match、`application/json` 请求、关闭额外字段且 1—3 脏属性的 `AppProfileMergeUpdateBody`;昵称非空 1—30,实名/邮箱各以 oneOf 表达精确空串 clear 与非空规范值。200 精确 `RAppProfileVo` 并含 required profileVersion,409 精确 `RProfileVersionChanged/PROFILE_VERSION_CHANGED`,同时列 400/401/422/429/500。当前输出 `PROFILE-UPDATE-OPENAPI-CONTRACT BLOCKED`,证明失败来自合同漂移而非测试语法。
-
-- [ ] **步骤 4:后端关闭 `API-PROFILE-UPDATE-001`—`004`**
-
-`001` 固定唯一 merge owner、dirty/omit/clear 和关闭额外字段;`002` 固定 profileVersion、If-Match、当前账号/租户原子 CAS 与 409;`003` 固定 typed canonical response、结构化字段错误、SaToken/clientid、JSON、`Cache-Control: private, no-store` 和正式 H5 CORS 允许 If-Match;`004` 固定重复设置无额外副作用、超时对账与账号隔离语义。后端从同一版本重导 JSON/YAML,不手改保护文件。
-
-- [ ] **步骤 5:GET/PUT 双门禁通过后测试先行实现 M02**
-
-先建立 profile update normalizer、API 和状态机纯运行时负例:clean 不请求,dirty allowlist,clear 命令,非法 nickname/email/null/额外字段,严格 envelope,双击、迟到响应、session generation、canonical 回填、409、确定失败和三分支 outcome reconciliation。随后迁移页面到 loading、ready/dirty、saving、success、error、uncertain、conflict、auth-expired;保存中锁输入与返回,成功更新 baseline,失败保留草稿。原子删除 fixture 双姓名、假 timer、API 禁用旧断言、假头像动作和邮箱送达承诺,不接头像/性别/生日。
-
-- [ ] **步骤 6:真实账号、CORS 与 MuMu 验收**
-
-用两个账号和两个会话验证单字段、多字段、清空、重复、旧 version、同字段冲突、不同字段更新、超时后 GET 对账、401/422/429/500、账号切换和迟到响应;正式 H5 origin 验证 If-Match 预检。MuMu 检查 loading、软键盘、系统字号、TalkBack、字段错误关联/聚焦、saving 返回、unknown/conflict 对话和长姓名邮箱。浏览器与静态合同不能替代。
-
-### 任务 32:建立 M10 当前设备退出远端硬门禁
-
-- [x] **步骤 1:三人只读核对本机退出、双导出和线上 DELETE**
-
-M10 现有 `session.clear → close → goRoot(A01)` 保证本机 token 与家谱上下文被清,取消无副作用,但没有远端撤销、重复保护、epoch 或状态提示。受保护双导出有 DELETE、required clientid/SaToken 和 200 RVoid,却无 scope/幂等/required/错误;线上只有 200 RVoid 与 401 string、媒体 `*/*`,且 operation 无 security/clientid。两份都不能证明当前设备还是全账号退出、旧 token 是否真正失效;未发送真实 DELETE。
-
-- [x] **步骤 2:反向质询并固定本机必退、远端分级**
-
-三人同时否决“网络失败就不退出”和“await 后 finally 清会话并宣称远端成功”。前者把本机隐私交给网络,后者会延迟退出且 A 的迟到 finally 可能清掉新登录 B。唯一结论是 logoutCoordinator 同步捕获 A token/clientid/epoch,立即经 session owner 清理并 bump epoch,再用显式 A 创建不随 M10 卸载取消的请求并立即进入 A01;异步结果永不再 clear。远端 200 才 confirmed,网络/超时/畸形/5xx 为 unconfirmed,拒绝为 not-revoked,全部不恢复 token。
-
-- [x] **步骤 3:先写失败合同锁定唯一服务端语义**
-
-`tests/logout-openapi-contract.ps1` 要求 DELETE 无 body、required SaToken/clientid、200 application/json RVoid 且 integer code required、401 typed `RLogoutRejected`,两者 `private, no-store`,并列 400/429/500。operation 明确只撤销当前 credential family、其他设备不受影响、active/revoked/expired 重复调用同一 200、成功后旧 token 被拒绝。当前输出 `LOGOUT-OPENAPI-CONTRACT BLOCKED`。
-
-- [ ] **步骤 4:后端关闭 `API-LOGOUT-001`—`003`**
-
-`001` 固定当前凭证族、refresh 同步撤销、其他设备隔离和跨鉴权节点传播;`002` 固定 active/revoked/expired 同一幂等 200,非法/client mismatch typed 401;`003` 固定 SaToken/clientid 绑定、JSON、no-store、错误矩阵、正式 H5 CORS 和 bearer 日志脱敏。后端同版本重导 JSON/YAML并用两设备 token A/B 证明 A 失效、重复 A 200、B 仍可用。
-
-- [ ] **步骤 5:门禁通过后测试先行实现 coordinator**
-
-先扩展 session owner 的单调 epoch 与所有已登记账号态清理,再写 logoutCoordinator 纯运行时测试:同步 capture/clear/request/root 顺序、无 token、request 创建抛错、双击、pending/confirmed/unconfirmed/not-revoked、M10 卸载不 abort、A 迟到不清 B、一次性消费、不持久 token。实现严格 logout API 和 A01 非阻断可播报提示;原子替换 M10、导航、NM 旧“页面直接 clear”断言。Mock/错误配置也本机退出且远端未确认。
-
-- [ ] **步骤 6:真实双设备与 MuMu 验收**
-
-验证 active/revoked/expired/invalid/client mismatch、重复调用、跨节点传播、refresh、离线/超时/429/500、快速 B 登录、进程终止与根导航失败;MuMu 检查确认/取消、双击、系统返回、pending 与最终播报、A01 登录可用及不返回受保护页。视觉源码审查或浏览器不能替代原生流程。
-
-### 任务 33:建立 M04 与统一密码凭证远端硬门禁
-
-- [x] **步骤 1:三人只读核对 M03/M04、四条密码 wire 与线上 PUT**
-
-M04 当前只有 500ms 本地校验预览,诚实显示“不提交服务器”;没有 API、MD5 或 session 写入。受保护双导出与线上文档的登录、注册、找回、改密都把 32 个十六进制字符 MD5 当静态密码等价物。线上 M04 只有 200 RVoid/401 string、`*/*`,operation 无 security/clientid;本地虽有 SaToken/clientid,却只列 200、RVoid 无 required,双方都缺策略、错误、会话撤销、缓存和并发语义。未发送真实 PUT、未操作 MuMu。
-
-- [x] **步骤 2:交叉反驳并固定唯一安全方案**
-
-三人否决保留 MD5 fallback、返回新 token 的方案 B 和继续保留旧 bearer 的方案 C。密码 wire 必须由登录、注册、找回、改密同批迁移到 HTTPS raw writeOnly;新密码目标为 NFC 后 15—64 Unicode code point、允许空格和 Unicode、无组成规则,由服务端执行 blocklist、限速和带盐慢哈希。M04 以当前密码重新认证,TAC 不能代替身份。唯一会话方案 A 是 200 前提升 credentialEpoch 并撤销所有设备/所有 client 的旧 access/refresh session,客户端清本机回 A01。
-
-三人同时否决为了本批新增 operation-status 和持久重试 body:strict 200 与网络结果未知都会进入 A01,重新登录已是最小对账路径。但 PUT 发出后进程被杀会留下本机旧 token,因此采用最窄 marker:session owner 在 dispatch 前仅持久化 `{sessionEpoch,startedAt}`;不含 token、密码、摘要或 body,冷启动同 epoch 时在渲染账号缓存前清会话。客户端不自动重试,迟到 A 不能影响 B。
-
-- [x] **步骤 3:测试先行建立共享 wire 与 M04 失败合同**
-
-新增 `tests/password-change-openapi-contract.ps1`。合同要求 `CurrentPasswordSecret/NewPasswordSecret` 分别成为登录/当前值与注册/找回/新值的唯一 schema owner,旧 MD5 不能继续被任何入口接受;M04 body 只含 required oldPassword/newPassword 且关闭额外字段。PUT required SaToken/clientid;200/400/401/409/422/429/500 使用 JSON/no-store,429 有 Retry-After,409/422 只消费四个稳定业务码,200 RVoid 的 integer code required。当前得到预期 `PASSWORD-CHANGE-OPENAPI-CONTRACT BLOCKED`,失败精确来自受保护后端合同缺口。
-
-- [ ] **步骤 4:后端关闭 `API-PASSWORD-001`—`005`**
-
-`001` 原子删除 login/register/reset/change 的 MD5 wire,发布 raw writeOnly 与 15—64/NFC/blocklist/慢哈希合同;`002` 固定 credentialEpoch、ALL access/refresh 跨节点撤销和 200 语义;`003` 固定 typed 400/401/409/422/429/500、并发 CAS 与明确未写边界;`004` 固定 SaToken/clientid、HTTPS server、JSON/no-store、Retry-After、日志/APM 脱敏;`005` 明确无密码账号是进入独立设置流程还是不可进入 M04。后端只接受同一版本重新导出的 JSON/YAML,禁止手改受保护文件。
-
-- [ ] **步骤 5:门禁通过后原子实施四条 wire、session 与 M04**
-
-先用共享密码策略纯函数测试 14/15/64/65 code point、Unicode/NFC、空格、粘贴、无组成规则与 current/new 相同;再一次性移除 `calcMD5` 的四条认证消费者和 8—32 旧规则,收紧 API payload/响应。扩展 session epoch 与 credentialChangeInFlight 冷启动门禁,写 M04 ready/submitting/known-error/unknown/success 状态机;确定未写错误留页,200/401/409/unknown 清秘密和同 epoch 账号态回 A01。原子替换 NM 旧“禁止 API/尚未提交”断言,不能保留 preview/remote 双入口。
-
-- [ ] **步骤 6:两设备、故障注入、无障碍与 MuMu 验收**
-
-验证旧/新密码、同旧密码并发只有一笔成功、所有设备 access/refresh 跨节点失效、wrong-old/policy/rate 明确未写、请求创建失败、落密前后/撤销前后断网与 5xx、进程被杀 marker、快速 B 登录和秘密不进入日志。MuMu 固定环境检查 15—64 文案、密码管理器/粘贴、软键盘、系统字号、44dp 显隐按钮、aria-pressed、字段错误关联/首错聚焦、提交播报、Android 返回及 A01 成功/unknown 持久提示;静态审查不能替代。
-
-### 任务 34:建立 M05 手机号换绑与统一 OTP 远端硬门禁
-
-- [x] **步骤 1:三人只读核对 M03/M05、全活动短信码、本地双导出与线上接口**
-
-M05 现有页面只消费脱敏 fixture,以 500ms 定时器校验新手机号和 4 位码,明确显示“当前未发送/尚未提交服务器”;没有 currentPassword、TAC consumer、API、session 或结果未知状态。本地 PUT body 为 `clientId/phone/smsCode`,线上为 `phone/smsCode`,两者均为 4 位码且缺 existing-factor、唯一约束、会话撤销和 typed 错误;线上返回完整 profile并把共享发码标为忽略权限。未发送 POST/PUT 或短信,未操作 MuMu。
-
-- [x] **步骤 2:交叉反驳并固定身份、发码和会话唯一方案**
-
-三人否决 bearer+新号 OTP:被盗 session 加攻击者自有号码即可接管。唯一身份闭环是活动 session+最终 PUT 内 raw currentPassword 再认证+新号 `APP_PHONE_CHANGE` TAC/OTP;不强制旧号 OTP,成功事务改为持久旧号通知 outbox。无密码账号 `STEP_UP_UNAVAILABLE`,不得降级。最终 PUT 不带 challengeId:同一复合键只有一个 active OTP generation,重发废止旧码即可消歧。
-
-三人先讨论复用公共 `/auth/sms/code` 加条件鉴权,随后否决:标准 OpenAPI 无法把 body scene 与 operation security 联动,optional security、文字或 vendor extension 仍让通用 validator 允许匿名,违反 validator/runtime 同步。最终采用专用 `POST /genealogy/app/auth/phone/sms/code`,SaToken required、scene 服务端固定、body 只含 phone/validToken;公共 scene enum 删除 APP_PHONE_CHANGE。底层 OTP 服务仍是单一 owner,不复制实现。
-
-- [x] **步骤 3:原子固定全活动六位短信码目标**
-
-四位码不可上线。新增唯一 `SmsCodeSecret`:CSPRNG 生成恰好 6 位 ASCII 数字、允许前导零、writeOnly、无示例;5 分钟 TTL、60 秒重发、最多 5 次失败、单次消费,重发废止旧 generation且不重置累计失败次数。登录、注册、找回、换绑、注销及同源服务端生成器/模板、双 OpenAPI、validator、页面和测试必须同版切换,禁止 4/6 兼容窗口。当前客户端继续保持四位诚实预览,不能在后端前单边改成无法登录的六位。
-
-- [x] **步骤 4:测试先行建立专用发码和最终换绑失败合同**
-
-新增 `tests/phone-change-openapi-contract.ps1` 并同步收紧 `tests/auth-tac-openapi-contract.ps1`。门禁要求专用 POST 与最终 PUT 都 required SaToken/clientid;`PhoneChangeSmsCodeBody` 只含 phone/validToken,`PhoneChangeBody` 只含 currentPassword/phone/smsCode;密码、新号和短信码分别引用唯一 schema。公共发码移除 APP_PHONE_CHANGE;POST/PUT 均有 JSON/no-store 错误矩阵、429 Retry-After,严格 200 RVoid,409/422/429 使用稳定 `RPhoneChangeRejected`。当前精确输出 `PHONE-CHANGE-OPENAPI-CONTRACT BLOCKED`,且认证门禁继续标准化输出自身红灯。
-
-- [ ] **步骤 5:后端关闭 `API-PHONE-001`—`005`**
-
-`001` 提供专用鉴权发码、固定 scene、公开/受保护反例与共享 OTP owner;`002` 原子升级全活动消费者为六位并固定 TTL/重发/尝试/单次消费;`003` 提供 raw currentPassword existing-factor、闭合 PUT 与无密码账号语义;`004` 把密码/OTP、号码唯一、CAS 换绑、credentialEpoch、ALL session 撤销和旧号 outbox 放进同一事务;`005` 固定 typed 业务码、HTTPS、JSON/no-store、Retry-After、CORS、PII/秘密日志脱敏与结果未知边界。只接受同一版本重导的双文件,不手改受保护源。
-
-- [ ] **步骤 6:前置门禁通过后原子实施客户端与 MuMu/两设备验收**
-
-先同步迁移共享六位 validator、认证页面与测试,再新增带 bearer 的 phone-change TAC/发码 API、最终 PUT strict adapter和共享 credential marker,最后实现 M05 ready/tac/sending/code-sent/submitting/known-error/unknown 状态机;同轮删除四位、preview 和禁止 API 的旧断言,不保留双入口。验证匿名专用发码、错 scene/TAC 重放、前导零、过期/重发/限流、号码枚举与唯一、两设备并发、全部 access/refresh 撤销、outbox、请求各事务点 fault injection 和进程终止。MuMu 检查软键盘、自动填充/粘贴、系统字号、TalkBack 非拖动 TAC、原生 44dp 按钮、错误关联/首错聚焦、倒计时、Android 返回及跨根 unknown 提示。
-
-### 任务 35:建立 G03 家谱与始祖原子创建远端硬门禁
-
-- [x] **步骤 1:三人只读核对 G03、上下文、现有测试、本地双导出与线上接口**
-
-G03 当前同页两步只写内存预览,第一步缺可信 regionCode,始祖默认男性、日期限制 1800 年以后且把“一世”放进 generationName;最终 `local-created-*` 进入 fixture G05,不安装真实 context。受保护双导出和线上 `/genealogies` 都只建谱,通用 `/lineage/persons` 另建人物;创建响应、地区项和线上 App 模型均缺 required/词法 ID/错误闭包,当前 `appApi.createGenealogy` 又会在 mock 中直接篡改 fixture。审查只读获取线上 `/v3/api-docs`,未发 POST/PUT、未触碰 MuMu、Git 或受保护 OpenAPI。
-
-- [x] **步骤 2:交叉反驳并固定 atomic bootstrap、访问预设和地区唯一方案**
-
-三人先完整设计 `ROOT_REQUIRED` 两写,再质询其必要性。当前没有跨库证据或“保存空谱以后补根”的产品需求;第一步本来也应零写,因此两写只会新增半成品 quota/ACL/搜索隐藏/过期/取消、G01 pending 卡、版本并发和第二次结果未知。最终选定现有 POST 原子创建家谱、OWNER、唯一一世始祖、READY 和幂等回执,任一失败全回滚;通用人物 POST 只服务 READY 后普通人物。
-
-`GenealogyAccessPreset=MEMBER_ONLY/PUBLIC_APPLY` 是 APP 读、建、改唯一 wire,而非 G03 私有第三字段;目标版本删除 visibility/joinMode 和旧 create/update DTO。所在地只消费 required SaToken/clientid 的 `GET /genealogy/app/region/search` 所返回的 required `regionCode/label/selectable`,同版删除旧公共 `/genealogy/region/search`;不从自由文本反推 code,也不把 leaf 猜成可选或强制某行政层级。根人物 sex 使用 MALE/FEMALE/UNKNOWN且默认 UNKNOWN,生日为 date,无 1800 下限;generation=1 由服务端固定。G11 在本任务中只迁移共享字段形状,其 If-Match、版本/CAS 与结果未知另立设置写入门禁,不能借 G03 宣称可上线。
-
-- [x] **步骤 3:选择无 PII 崩溃恢复并测试先行建立失败合同**
-
-三人比较“本地持久化 exact body 同 key 重放”和“authenticated operation-status”。前者端点更少,却会把始祖姓名、生日、生平放进普通 UniApp storage,扩大退出、换号、备份和崩溃清理面;最终选择后者。客户端只持久 `{sessionEpoch,operationKey,startedAt}`;进程内可用相同 key+冻结 snapshot 重放,冷启动查询 `PENDING/SUCCEEDED/FAILED_NO_COMMIT`,不从 `/mine` 猜同名记录。key 固定为 13 位 issuedAt+22—43 位 base64url CSPRNG,`acceptUntil=issuedAt+10 分钟`,以 server time 判定且未来超过 5 分钟为 400 `OPERATION_KEY_INVALID`;上述公式以 600/300 秒 extension 机器锁定。首次 POST 先以短控制事务唯一认领 PENDING/digest/fencing/resolveBy,`resolveBy<=claimedAt+2 分钟`并以 120 秒 extension 锁定,再由业务事务原子写 quota、谱、OWNER、唯一根、READY 和 SUCCEEDED。业务回滚后或 watchdog 超时只能用 fencing CAS 终结 FAILED_NO_COMMIT,旧 worker 不得提交;GET 只允许 operationKey/clientid、无 body且始终纯读,不能靠查询制造墓碑。
-
-新增后端双导出门禁 `tests/g03-bootstrap-openapi-contract.ps1`,当前精确输出 `G03-BOOTSTRAP-OPENAPI-CONTRACT BLOCKED`;其前置 `tests/openapi-yaml-json-parity-runtime-smoke.js` 不依赖第三方包,以无损任意精度数字、合法 mapping 分隔符和完整对象结构深比较 JSON/YAML,JSON 检查因此等价覆盖 YAML 而不依赖缩进、引号或 JavaScript Number 舍入。另建客户端激活门禁 `tests/g03-bootstrap-client-release-gate.ps1`,当前精确输出 `G03-BOOTSTRAP-CLIENT-RELEASE BLOCKED`;它只保留公共 owner/旧入口删除的静态断言,并实际执行依赖注入状态机测试,以 exact marker 和 request/storage/cache/context/navigation spies 验证分支及成功顺序,不再靠 helper 的 IndexOf 或测试标题误判。已有 fixture/G11 等聚焦守卫由全量测试共同证明,不冒充为该脚本单独覆盖。后端合同转绿不能自动开放页面,客户端绿灯也不能绕过后端;G03 两门禁、家谱工作区读取门禁和 MuMu 发布验收必须共同通过。同轮把 `tests/g-series-openapi-contract.ps1` 中会永久锁死旧 `GenealogyCreateBody/GenealogyUpdateBody/visibility/joinMode` 的断言移交给新唯一 owner,既有 G-series 合同仍独立通过。
-
-- [ ] **步骤 4:后端关闭 `API-G03-001`—`005`**
-
-`001` 以 `AppGenealogyBootstrapBody` 原子替换旧 create,在业务事务内处理 quota、家谱、OWNER、根、READY 和 SUCCEEDED 回执;`002` 提供 issuedAt+至少 128 位随机量的 Idempotency-Key、server-time 10 分钟接受窗口、5 分钟未来偏差、同 key/body 同回执、不同 digest 409、过期空 key 409 与长期成功防重记录;`003` 以短控制事务/fencing/watchdog 发布受鉴权 operation-status,GET 参数/body/响应集闭合且纯读,PENDING 为 `resolveBy/retryAfterSeconds` 并最迟 claimedAt 后 2 分钟收敛,结构化转换只允许 `ABSENT→PENDING→SUCCEEDED/FAILED_NO_COMMIT` 且两个终态不可变,FAILED 机器保证零领域写与零 quota,截止前 404 带 acceptUntil/Retry-After,截止后无记录按 key 计算 FAILED 而不写墓碑;`004` 让 APP 读/建/改统一 accessPreset并递归拒绝组合 schema 中的旧 pair/DTO;`005` 将地区 owner 固定为 `/genealogy/app/region/search` 并删除公共旧路由,固定词法 ID、SaToken/clientid、状态专属 error code/businessCode、private no-store、对象隔离和事务 fault injection。通用人物 collection POST、人物 PUT/DELETE 和 parents mutation 同版以数据库 bootstrap-root 标记保护根身份:根 PUT 可编辑白名单精确只有 `name/sex/birthDate/biography`,其余字段全部 typed 422,根不可删,typed 409/422覆盖全部绕过入口。只接受同一版本重导 JSON/YAML,禁止手改当前源文件。
-
-- [ ] **步骤 5:门禁通过后测试先行实现唯一 coordinator 与页面闭环**
-
-先写 canonicalizer、严格响应 normalizer、operation marker/status 状态机和 context 安装的纯 Node 测试,再实现唯一 G03 coordinator。第一步 CTA 改“下一步:录入首代”且零请求;最终按钮冻结全表单后才写 marker/POST。本地校验或可证明零发出的 request-build 失败不留 marker;服务端在 claim 前返回的 400/401/403 清 marker,401 同时清会话。IDEMPOTENCY_KEY_REUSED 进入 fatal/quarantined,禁止查装 status或自动换 key,只有用户看到警告后显式放弃才清;确定未提交的 limit/expired/422 可清。429 保持同 key/body并先查 status;500/network/timeout/408/发出后取消/意外 2xx/3xx/畸形成功均按 unknown 保持。status 截止前 404 保持,400 清损坏 marker,401 走会话失效,429/500/network/cancel/unexpected/malformed 保持退避,FAILED_NO_COMMIT 才允许新 key。SUCCEEDED 唯一次序是 committed receipt → 失效或定点更新 `/mine` → 安装词法 context → 进入远端 G05;context/导航失败只重试本地闭环,不重发创建。原子删除 `createLocalGenealogyPreview`、会修改 fixture 的 mock create、禁止 appApi 的旧断言及 `local-created-*` 成功路径,不保留 preview/remote 双 owner;G01 onShow 和 G05 overview 必须与工作区门禁同一真实 ID 收敛。
-
-- [ ] **步骤 6:表单无障碍、事务反例和 MuMu 发布验收**
-
-地区选择覆盖加载/搜索/无结果/失败/迟到/失效;输入具有 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、个人资料读写、通知、服务端退出和密码凭证当前都被外部合同红灯阻塞,不在本地空等。其余阶段仍逐个重新执行三人只读审查、方案比较、失败测试和最小实施;不得把两个业务域混入同一批:
-
-1. 家谱工作区:任务 26 已完成三人审查和 OpenAPI 红灯;线上 JSON `int64` 响应身份、模型 required、可访问能力与错误语义未关闭前禁止猜测实现。门禁通过后才处理远端列表现场、权限刷新和账号隔离;写后失效属于后续写接口批次。
-2. M06:任务 27 已完成 list-only 三人审查和 OpenAPI 红灯;门禁通过后才写严格 adapter、异步状态和无障碍手风琴,不接详情 ID。
-3. 个人资料读取:任务 28 已完成 M01/M02/M03 三人审查和 OpenAPI 红灯;门禁通过后才接掩码 adapter,PUT 保存、头像和换绑仍各自独立。
-4. 通知:任务 29/30 已把读取和已读写入拆开建立红灯;读取通过后先实现无 ID 内存快照,写入再私有迁移字符串 ID,未知业务目标始终内容态。
-5. M02 写入:任务 31 已建立唯一 merge PUT 红灯;GET/PUT 双门禁通过后才实现 dirty command、版本 CAS、结果未知对账与账号隔离,头像保持独立。
-6. M10 退出:任务 32 已建立当前凭证族与幂等撤销红灯;通过后才实现 session epoch、logoutCoordinator 和 A01 提示,本机清理始终优先。
-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. 普通加入与邀请码直入:任务 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 原子创建、普通加入、邀请码直入、G11 设置、G12 字辈集合、F01/F03 家族动态读取、M06 帮助、个人资料读写、通知读写、M10 服务端退出、M04 密码凭证与 M05 手机号换绑的所有者、旧路径删除条件、测试、MuMu 矩阵和后端接口缺口均已精确写明。
-- 导航任务 1—10 已按测试先行完成两个共享所有者、共享组件、退役入口、认证、G、T、F、R、N/M 系列静态迁移与零债务门禁;没有手工改写 OpenAPI 导出,MuMu 原生矩阵仍按明确边界待执行。
-- 三人对业务正确性、全局一致性、回归风险、维护成本和 MuMu 可验证性形成一致结论。
-- 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 完成对抗门禁和三人终审后立即转向下一个独立业务域,不把两个阶段混在同一变更中。
diff --git a/docs/家谱项目全量治理设计.md b/docs/家谱项目全量治理设计.md
deleted file mode 100644
index 4a6d235..0000000
--- a/docs/家谱项目全量治理设计.md
+++ /dev/null
@@ -1,1130 +0,0 @@
-# 家谱项目全量治理设计
-
-> 日期:2026-07-22
-> 状态:阶段 0 已完成;导航任务 1—10 的静态实施和零债务门禁已经完成;A01/A04/A05 TAC 客户端与 M07 反馈客户端已经完成;MuMu 原生矩阵待执行;T01、认证、家谱工作区、M06 帮助、个人资料读写、通知读写、M10 服务端退出、M04 密码凭证与 M05 手机号换绑后端合同均处于硬门禁红灯
-> 适用范围:当前 UniApp 家谱项目、根目录 OpenAPI 文档、全部活动页面、共享组件、测试、正式资产与后续真实接口接入
-
-## 一、背景
-
-项目第一轮国风视觉与响应式适配已经完成,并形成了可继续工作的页面基线。但此前验收包含用户抽查和代理逐页审核,不能据此认定所有页面、所有真实数据和所有跨页流程都已经最终正确。
-
-当前根目录已经取得由 Apifox 导出的两份接口文档:
-
-- `APP.openapi.json`
-- `APP.openapi.yaml`
-
-两份文件来自同一个 Apifox 项目,只是表示格式不同。接口由后端根据此前思维导图设计,并非根据当前页面逐项编写,因此可能混入 PC 接口,也可能存在 App 接口缺失、字段不足、状态不完整或页面与接口目标不一致等问题。
-
-后续工作不能简单地让页面迁就现有接口,也不能默认现有页面天然正确。必须从真实业务目标出发,对页面、接口、功能、交互、导航、视觉和数据状态进行联合治理。
-
-## 二、治理目标
-
-本轮治理需要同时达到以下目标:
-
-1. 清理失效、重复、冲突或确实无用的文档、测试、资产和生成物,使工作区只保留当前有效内容。
-2. 区分 App 接口、PC 接口、可共用接口和缺失接口,严格分析 OpenAPI 合同。
-3. 建立页面、用户操作、业务状态、接口和数据结果之间的精确映射。
-4. 重新评估全部活动页面的视觉完整性与美观性,不把“没有溢出”当成视觉完成。
-5. 检查功能、权限、交互、导航、失败处理、重复操作和跨页数据一致性。
-6. 按业务域向后端持续提交可直接修改 Apifox 的完整接口问题单。
-7. 采用测试先行和小批次实施,每批均在 MuMu Android 中完成真实流程和视觉验收。
-8. 建立中文文档、中文进度和详细中文代码注释规范,使后续接手者能够明确知道当前做到哪一步、每一步在做什么。
-
-## 三、明确不做的事情
-
-- 不重新推翻已经建立的国风设计方向。
-- 不因为旧页面曾经通过就忽略新发现的可复现问题。
-- 不因为现有接口已经写好就强迫页面接受错误业务。
-- 不因为现有页面已经完成就无条件要求后端照搬。
-- 不一次混合实施多个业务域。
-- 不用浏览器截图代替 MuMu 视觉验收。
-- 不制造临时假接口、双读取兼容路径或伪持久化成功。
-- 不通过删除失败测试来制造全量通过。
-- 不执行 Git add、commit、push、restore、checkout 或 reset 等 Git 变更操作。
-
-## 四、权威顺序与唯一所有者
-
-发生冲突时,采用以下权威顺序:
-
-1. 用户确认的真实业务目标。
-2. 三人共同推演并验证的完整用户流程。
-3. 后端在 Apifox 中确认的接口合同。
-4. 页面、共享组件和运行时代码。
-5. 自动化测试与 MuMu 当前轮验收证据。
-6. 当前 OpenAPI 导出、现有 mock 和历史资料。
-
-关键合同的唯一所有者如下:
-
-- 接口源头:后端维护的 Apifox 项目。
-- 自动分析格式:`APP.openapi.json`。
-- 人工阅读与跨工具格式:`APP.openapi.yaml`。
-- 九宫格切片与可变高度装饰面:`styles/adaptive-frame-profiles.scss`。
-- 密码策略:`utils/validation.js`。
-- 响应式覆盖范围:`tests/responsive-layout-coverage.json`。
-- 固定尺寸例外:`tests/responsive-layout-allowlist.json`。
-- 项目当前状态入口:`docs/项目当前总览.md`。
-- 页面与接口关系:`docs/接口与页面映射总表.md`。
-
-`APP.openapi.json` 与 `APP.openapi.yaml` 不是两个独立接口所有者,而是同一次 Apifox 导出的两个产物。两份文件不得分别手工维护,必须通过自动合同验证语义一致。
-
-## 五、三人联合治理机制
-
-### 5.1 人员组成
-
-总共三人:主代理和两位评审者。三个人都必须完整审查同一个业务域,不能把页面、接口和交互割裂分工,也不能出现“该问题不属于我”的责任边界。
-
-三个人均需覆盖:
-
-- 页面美观与样式完整性;
-- 功能和业务严谨性;
-- App、PC 接口分类与合同完整性;
-- 交互、导航、页面状态和跨页数据;
-- 真实数据进入后的布局、反馈与业务结果。
-
-### 5.2 四轮互补流程
-
-第一轮为独立首审。三个人在不查看另外两人初步结论的前提下,分别阅读页面源码、测试、OpenAPI 和业务说明,并审查同一组 MuMu 证据,独立形成完整判断,避免首个意见造成锚定。
-
-第二轮为交叉补漏。三份结果公开后,每个人逐条检查另外两份结论,判断是否漏掉页面状态、接口边界、视觉问题、业务风险或连锁影响。
-
-第三轮为反向质询。合并后的结论重新交给三个人,每个人主动尝试证明结论可能错误,包括检查接口是否真的缺失、页面问题是否由测试数据造成、视觉方案在边界状态下是否仍成立,以及导航和数据刷新是否在重复进入后仍然正确。
-
-第四轮为共同收敛。每个问题必须带有页面、状态、接口、代码位置、MuMu 证据、影响等级和处理建议。不能只记录“感觉不好看”“接口可能有问题”等不可验证意见。
-
-三人意见不能简单少数服从多数。任意一人提出有证据的疑点时,必须继续调查;只有证据充分后才能形成共同结论。
-
-### 5.3 共享工作区规则
-
-- 审查阶段三个人只读,不边看边改。
-- MuMu 由主代理统一导航、切换状态和采集截图,避免多人同时操作造成状态干扰。
-- 两位评审者审查同一份已经打开确认的 MuMu 截图。
-- 评审者可以要求补拍状态,主代理补充证据后三人重新判断。
-- 实施阶段由主代理统一修改工作区,两位评审者负责复核方案、变更、测试与 MuMu 证据。
-
-## 六、联合评审模型
-
-每个页面使用统一中文评审结构,至少记录:
-
-- 页面编号、页面路由和业务目标;
-- 用户身份、角色、权限和前置条件;
-- 进入来源、返回目标和流程终点;
-- 页面全部适用状态;
-- 页面全部用户操作;
-- 每个操作成功、失败、取消后的页面和数据结果;
-- 对应 App 接口和关联 PC 接口;
-- 缺失、冲突或不完整的接口;
-- 样式、美观、功能、交互和导航问题;
-- 真实数据和边界数据风险;
-- MuMu、源码和 OpenAPI 证据;
-- 三人初审、补漏、质询和最终结论。
-
-每个用户功能都按以下顺序推演:
-
-```text
-进入
-→ 输入或选择
-→ 本地校验
-→ 提交锁定
-→ 发起请求
-→ 成功或失败
-→ 页面反馈
-→ 数据刷新
-→ 返回或流程结束
-→ 再次进入
-```
-
-同时检查取消、Android 返回键、重复点击、网络失败、权限变化、目标数据过期和跨页状态一致性。
-
-## 七、视觉与美观验收标准
-
-第一轮样式审核是继续工作的基线,不是永远不能重开的封印。包括 G01—G10 在内,只要三人通过页面、接口、流程或 MuMu 证据发现明确且可复现的问题,就允许重新打开处理。
-
-视觉验收不能只检查溢出、遮挡和响应式,还必须检查:
-
-- 页面整体是否有协调的视觉中心和信息层级;
-- 标题、正文、辅助信息、错误提示和操作区是否层级清楚;
-- 字号、字重、颜色、间距、对齐、留白和视觉重心是否协调;
-- 卡片、输入框、按钮、弹窗、列表项、图标、背景、边框和装饰是否完整;
-- 默认、按下、选中、禁用、加载、空、错误和成功状态是否都有正式设计;
-- 素材是否缺失、模糊、变形、错误裁切或风格不一致;
-- 页面是否过空、过密、装饰不足或装饰堆叠;
-- 同一模块与跨模块是否保持统一国风语言;
-- 真实长短数据、键盘、弹窗和滚动状态下是否仍然美观。
-
-缺少皮肤、页面明显失衡、视觉层级混乱、素材错误或半成品表现不能统一降级为低优先级体验问题。
-
-现有国风设计体系是新增或修复样式的基础:
-
-1. 优先复用现有共享组件和正式资产。
-2. 能通过共享规则解决时,不在单页复制样式或素材。
-3. 需要扩展时,优先扩展现有视觉体系。
-4. 确实没有合适素材时,按真实槽位尺寸、色彩、纹理和透明要求制作正式资产。
-5. 如果现有页面结构经真实流程与 MuMu 证据证明明显不合理,可以重新设计该页面,但必须保持产品信息与交互合同、复用现有设计语言,并先更新设计和测试,不能写单设备补丁。
-6. 不用 emoji、文字符号、临时 SVG、CSS 拼图或占位框冒充正式资产。
-7. 新资产必须在 MuMu 中验证清晰度、比例、裁切和状态完整性。
-
-## 八、接口治理与后端协作
-
-### 8.1 接口分类
-
-每个接口标记为以下一种类型:
-
-- App 可直接使用;
-- PC 专用,不进入 App;
-- PC 与 App 可能共用,需要后端确认;
-- App 接口存在但合同不完整;
-- 页面需要但 App 接口缺失;
-- 接口存在但当前页面没有合理用途;
-- 接口与页面都需要重新定义。
-
-接口审查至少覆盖鉴权、请求参数、响应字段、字段可空性、枚举、分页、错误码、权限、幂等、上传、删除、审核和状态转换。
-
-### 8.2 接口问题单
-
-每条接口问题必须包含:
-
-- 问题编号、业务域、优先级和状态;
-- 页面、路由、触发操作、用户身份和前置条件;
-- 业务目标和完整使用场景;
-- 现有接口路径、方法、请求、响应与当前问题;
-- 建议新增或修改的接口能力;
-- 鉴权、参数、字段类型、必填性、约束和成功响应;
-- 分页、错误码、权限、幂等和数据副作用;
-- 页面成功、失败、取消、返回和数据刷新表现;
-- 验收步骤和三人共同结论。
-
-不能只向后端提交“缺接口”或“字段不够”等模糊描述。
-
-### 8.3 后端更新闭环
-
-```text
-三人形成接口问题单
-→ 用户确认少数业务决策
-→ 后端修改 Apifox
-→ 用户重新导出 JSON 和 YAML
-→ 验证双格式语义一致
-→ 检查本次接口差异
-→ 运行接口合同测试
-→ 页面接入真实接口
-→ MuMu 验证完整状态
-→ 三人共同复核
-→ 问题关闭
-```
-
-后端提出替代方案时,三个人重新评估它是否满足业务和页面,不因接口已经完成就自动接受。
-
-## 九、问题等级与暂停条件
-
-### 9.1 问题等级
-
-- 阻断级:权限越权、隐私泄露、数据丢失、重复写入、关键流程无法完成或接口无法支撑业务。立即暂停当前批次。
-- 高优先级:业务流程错误、返回目标错误、状态结果不一致、关键错误无反馈、主要页面缺少样式或呈现半成品。当前业务域不得带问题完成。
-- 中优先级:局部状态样式、交互反馈、文案层级或边界数据存在问题。必须在该业务域闭环前解决。
-- 体验优化:不影响理解和任务完成的细节打磨,可在本批后段处理。
-
-### 9.2 必须暂停的情况
-
-- 真实业务目的无法确定;
-- 页面和接口表达不同状态模型;
-- 缺少关键 App 接口;
-- 后端字段、权限或错误码不足以安全实现;
-- 三人对业务正确性仍有实质分歧;
-- 共享合同的唯一所有者尚未确定;
-- 没有有效 MuMu 证据;
-- 测试无法先复现问题;
-- 同一问题连续三个实现假设失败。
-
-等待后端时,将当前批次标记为“待后端处理”,转向下一个没有依赖关系的业务域,不制作临时兼容路径。
-
-## 十、阶段 0:项目基线清理
-
-### 10.1 清理原则
-
-旧内容不归档。确认已失效、已替代或确实无用后,直接从工作目录删除。Git 历史承担追溯作用,但本轮不执行 Git 变更命令。
-
-清理候选无需用户逐项确认,但必须由三个人共同复核:
-
-- 三人一致确认无用:由主代理统一删除。
-- 任意一人提出有效疑点:继续调查,暂不删除。
-- 审查人员不同时修改或删除文件。
-
-### 10.2 文档清理
-
-文档只有在内容被当前权威文档完整覆盖、没有独有有效决策、且不会继续作为执行入口时,才能删除。删除旧文档时必须同时清理所有指向旧入口的引用。
-
-### 10.3 测试清理
-
-每个测试需要记录保护的页面或功能、具体合同、当前有效性、重复关系和失败价值,并归类为保留、合并、重写或删除。
-
-- 测试失败不是删除理由。
-- 对应功能删除或合同被新唯一测试完整覆盖时,才能删除旧测试。
-- 只断言旧文档文字、旧素材路径或无业务价值内部实现的测试应重写或删除。
-- 截图采集工具不计入合同测试总数。
-- 浏览器测试可以保留独立逻辑价值,但不能作为视觉验收。
-- 生成物依赖先判断生成流程是否仍为正式能力。
-
-### 10.4 资产清理
-
-资产引用扫描必须覆盖 Vue、JavaScript、SCSS、JSON、配置、设计清单、构建脚本、CSS 变量和动态路径。
-
-资产分为正式运行时资产、共享视觉资产、设计母版、构建输入、可再生成产物、临时 MuMu 证据、重复资产、被替代资产和已删除功能专用资产。
-
-重复素材需要比较文件哈希、像素尺寸、透明区域、压缩质量和交互状态用途。确认合并后只保留一个公共所有者,更新全部引用后删除副本。
-
-### 10.5 清理顺序与验证
-
-```text
-确认当前权威资料
-→ 删除失效文档
-→ 清理重复或失效测试
-→ 建立完整资产引用关系
-→ 清理无用资产和生成物
-→ 删除残留引用
-→ 运行聚焦与全量验证
-→ MuMu 检查代表流程
-```
-
-阶段 0 只清理已经能证明无效的内容,不顺便重构业务代码,也不开始接口接入。
-
-## 十一、文档体系与生命周期
-
-### 11.1 核心当前文档
-
-- `docs/项目当前总览.md`:项目唯一入口和当前进度。
-- `docs/家谱项目全量治理设计.md`:长期有效的治理规则。
-- `docs/家谱项目全量治理实施计划.md`:当前执行批次与验证要求;整体完成后将长期内容合并到总览并删除。
-- `docs/接口与页面映射总表.md`:页面、功能、状态与接口关系的唯一总表。
-
-### 11.2 临时文档
-
-- `docs/项目基线清理清单.md`:阶段 0 使用,清理完成并合并有效信息后删除。
-- `docs/评审/<业务域>联合评审.md`:业务域审查期间使用,完成并合并长期结论后删除。
-- `docs/待后端处理接口问题.md`:只保留尚未解决的问题;后端合同通过验证后删除对应条目。
-
-### 11.3 生命周期
-
-```text
-草稿
-→ 三人评审
-→ 当前有效
-→ 内容进入唯一所有者
-→ 过程文档删除
-```
-
-不保留“旧版”“最终版2”“备份”或历史归档。任何规则只能有一个当前所有者。
-
-## 十二、测试策略
-
-测试体系按以下层级组织:
-
-1. 项目基础合同:页面清单、路由、共享组件、唯一所有者、响应式、编译和 OpenAPI 双格式一致性。
-2. 接口合同测试:路径、方法、参数、鉴权、响应字段、错误码、分页和状态枚举。
-3. 业务状态测试:校验、权限、状态转换、防重复提交、失败重试、过期和数据刷新。
-4. 导航流程测试:进入、返回、取消、完成和重复进入后的栈与数据状态。
-5. 纯函数运行测试:密码、验证码、字段归一化和状态机等纯逻辑。
-6. MuMu 验收:视觉、美观、键盘、安全区、手势和 Android 返回键。
-
-每个确认问题必须测试先行:
-
-```text
-第一步:写出能够复现问题的失败测试
-第二步:运行并确认测试因目标问题失败
-第三步:实施最小修改
-第四步:运行聚焦测试
-第五步:运行全局响应式合同和编译审计
-第六步:运行全量合同
-第七步:在 MuMu 验证完整流程和视觉状态
-```
-
-全量测试数量可以因清理和新增真实合同发生变化,不以保持原有数量为目标。
-
-## 十三、中文文档与代码注释规范
-
-- 新建规格、计划、报告和问题单使用中文文件名和中文内容。
-- 接口路径、字段名、函数名等技术标识保留原文,并提供中文解释。
-- Vue、JavaScript、SCSS 和测试脚本继续使用英文技术文件名,避免工具兼容问题。
-- 测试代码同样使用中文注释说明准备条件、执行步骤、预期结果和合同目的。
-- 复杂业务函数必须使用详细中文注释说明每一步的业务目的、执行顺序、状态变化、失败处理和设计原因。
-- 简单赋值不堆叠无意义注释,但不能让复杂流程只能依赖阅读实现细节才能理解。
-
-复杂流程注释采用明确步骤形式,例如:
-
-```js
-// 第一步:校验页面必填字段,阻止无效请求进入后端。
-// 第二步:锁定提交状态,防止连续点击产生重复记录。
-// 第三步:调用业务接口,并根据明确的后端状态更新页面。
-// 第四步:成功后刷新来源数据,再结束当前流程。
-// 第五步:失败时保留用户输入,并提供可理解的重试入口。
-```
-
-## 十四、精准代码与复杂度控制
-
-所有新增或修改代码都必须以最小、精准、可验证为标准。代码行数少不是唯一目标,但每一行都必须能够追溯到当前确认的问题、业务合同或验证要求。
-
-- 一个模块、函数或状态对象只承担一个清晰职责。
-- 业务规则必须有唯一所有者,页面、组件、工具和测试不得复制同一判断。
-- 改变合同后同步删除旧字段、旧入口、旧分支和旧注释,不保留“以防万一”的兼容读取。
-- 不为单次使用创建抽象层,也不为了未来可能需求增加配置、参数或扩展点。
-- 不把多个互不相关的业务流程塞进同一个大函数;复杂流程按明确业务步骤拆分,并保持输入、输出和副作用可见。
-- 优先使用清晰命名、早返回和直接数据流,避免深层嵌套、隐式全局状态和难以追踪的副作用。
-- 只有两个以上真实消费者需要同一规则时才提取共享能力,不能为了“看起来高级”制造工具层。
-- 不新增没有必要的依赖,不用大范围重构解决局部问题。
-- 中文注释解释“为什么、当前步骤和业务边界”,不能逐字翻译语法,也不能用大量注释掩盖混乱实现。
-- 测试验证对外业务合同和关键状态,不把内部实现细节固化成脆弱断言。
-- 每次实施只处理一个可独立验证的批次;相邻但无关的问题只记录,不顺手修改。
-
-每个代码批次完成前,三个人必须共同检查:
-
-1. 是否存在重复规则、重复请求或重复状态。
-2. 是否引入不必要的抽象、依赖、参数或兼容分支。
-3. 函数和文件是否具有清晰单一职责。
-4. 旧路径、孤立变量、失效注释和无用导入是否由本批产生。
-5. 是否可以用更直接、更少副作用的方式表达同一业务。
-6. 每个修改是否都有对应失败测试、业务证据和 MuMu 验证。
-
-任意评审者能够用证据指出代码复杂、重复或所有权不清时,该批次不能进入完成状态。
-
-## 十五、项目阶段顺序
-
-### 阶段 0:项目基线清理
-
-清理失效文档、测试、资产和生成物,建立可信验证基线。
-
-### 阶段 1:全项目共享合同
-
-建立 OpenAPI 一致性、App/PC 分类、登录态、权限、统一错误、分页、上传、防重复提交和导航栈语义。
-
-导航栈先形成统一设计和测试合同,具体修改随业务域逐页验证,不机械批量替换。
-
-### 阶段 2:认证与账户
-
-覆盖 A 系列,并同时审查 M03—M05 依赖的账户安全合同,包括注册、登录、短信验证码、找回密码、登录态失效、修改密码、换绑手机号和注销。
-
-### 阶段 3:家谱主体与申请
-
-覆盖 G 系列,包括列表、创建、概览、搜索、加入申请、审核、角色、权限、设置、字辈谱和家谱上下文。
-
-### 阶段 4:世系与成员
-
-覆盖 T 系列,包括树图、成员选择、详情、添加、编辑、关系、目录、隐私、权限和保存后的跨页一致性。
-
-### 阶段 5:家族圈与内容媒体
-
-覆盖 F 系列,包括动态、文章、评论、相册、照片、视频、上传、分页、草稿、发布、编辑和删除。
-
-### 阶段 6:人物与族务记录
-
-覆盖 R 系列,包括人物档案、礼物、祭祀、成长、人生事件、备忘、功德、时间线和汇总。
-
-### 阶段 7:消息通知
-
-覆盖 N 系列,包括未读、已读、全部已读、消息目标、过期、权限失效和业务结果一致性。
-
-### 阶段 8:个人中心与设置
-
-覆盖剩余 M 系列,包括资料、帮助、反馈、推广、会员订单、协议、退出登录和账户状态。
-
-### 阶段 9:跨模块最终闭环
-
-使用真实接口完整验证认证、创建或加入家谱、管理成员、发布内容、新增记录、接收消息、返回个人中心、退出和重新进入。
-
-## 十六、每个业务域的固定执行流程
-
-```text
-三人独立首审
-→ 交叉补漏
-→ 反向质询
-→ 共同结论
-→ 后端接口问题单
-→ Apifox 修改与双格式导出
-→ 五方案比较与批次设计
-→ 失败测试
-→ 最小实施
-→ 聚焦、全局和编译验证
-→ MuMu 完整流程与视觉验收
-→ 删除旧合同和无用内容
-→ 业务域完成
-```
-
-每个确认问题提出五个可行方案,从业务正确性、全局一致性、回归风险、维护成本和 MuMu 可验证性选择最优方案。
-
-## 十七、进度与用户沟通
-
-每个业务域只使用以下中文状态:
-
-```text
-未开始
-基线清理中
-独立首审中
-交叉复核中
-待业务确认
-待后端修改
-待实施
-实施中
-MuMu 验证中
-回归验证中
-已完成
-```
-
-开始批次时报告当前阶段、业务域、目标、页面、接口、状态、后端依赖和明确不处理范围。
-
-执行过程中只报告有实际价值的进展,包括已完成内容、三人发现、当前检查、阻断问题和下一步,不向用户倾倒无关工具日志。
-
-只有三个人无法根据证据安全决定的真实业务问题才打断用户,例如角色权限、永久删除、重新申请、费用权益、隐私范围或会改变产品含义的流程分歧。
-
-提问时一次只问一个业务问题,并说明发生位置、当前冲突、已排除方案、推荐方案、影响和阻塞范围。
-
-## 十八、业务域完成定义
-
-一个业务域只有同时满足以下条件才能标记完成:
-
-- 三人完成独立首审、交叉补漏和反向质询;
-- 每个页面的全部适用状态都有本轮 MuMu 证据;
-- 页面视觉达到完整、统一、美观的正式成品标准;
-- 所有页面操作都有明确业务结果;
-- 进入、返回、取消、完成、失败和重复进入均通过验证;
-- 每个页面数据需求都映射到明确 App 接口;
-- 若当前批次存在接口缺口,后端已在 Apifox 完成相应修复;
-- JSON 与 YAML 来自同次导出且语义一致;
-- 聚焦测试、全局响应式合同、编译审计和全量合同通过;
-- 真实接口数据下再次完成 MuMu 验收;
-- 没有遗留旧路径、旧字段、废弃测试或无用资产;
-- 阻断级和高优先级问题为零;
-- 其他未解决事项有明确负责人和状态。
-- 本批代码通过三人复杂度审查,不存在新增重复规则、无意义抽象、旧兼容路径或职责混乱的大函数。
-
-## 十九、当前实施前置条件
-
-阶段 0 已经完成。后续实施必须满足:
-
-1. 当前业务域已经由三个人完成独立首审、交叉补漏、反向质询和最终收敛。
-2. 设计结论已经进入本文件,实施步骤已经进入唯一实施计划。
-3. 需要后端变更时,先形成可直接修改 Apifox 的问题单;新导出通过双格式和接口差异合同后才能接入。
-4. 每个批次先写失败测试,再实施最小代码;不得同时混合导航、短信、持久化和全局无障碍等多个阶段。
-5. 业务代码变更后必须运行聚焦合同、全局响应式合同、编译审计和全量合同,并在当前 MuMu 复核完整流程。
-
-用户已经授权三位审查者自行裁决有充分项目证据的专业方案。只有角色权限、隐私范围、永久删除、收费权益、法律责任或确实无法从现有业务判断的产品含义才再次询问用户。
-
-## 二十、导航栈语义统一设计
-
-### 20.1 当前证据
-
-任务 3 实施前的只读扫描得到以下统一口径:
-
-- 52 个活动页面中共有 `navigateTo 59`、`navigateBack 11`、`redirectTo 14`、`reLaunch 7`,合计 91 次直接调用。
-- 活动共享组件另有 `navigateBack 2`、`reLaunch 2`,活动页面与组件共 95 次。
-- 封存的 A06 另有 2 次,完整页面与组件源码共 97 次;项目没有 `switchTab` 调用。
-- MuMu 已复现 F01→F03→“返回家族圈”后留下两个 F01,A01→A04→“登录”后留下两个 A01,T03 可连续叠出三个同路由页面。
-- 栈深为 1 时直接进入 F03,当前 `PageHeader` 会回到固定 G01,而不是业务父页 F01。
-
-任务 3 已把共享页头和自定义底栏的直接调用清零,并删除无活动消费者的通用页面旧入口;任务 4—8 依次迁移认证、G、T、F、R,任务 9 完成 N/M、安全通知目标、账号表单返回守卫与退出会话清理,任务 10 删除最后一个零生产消费者的 `TreeMemberForm.vue` 及其旧专属合同。当前 SFC 分段词法扫描的迁移债务已经清零:pages/components 中 `navigateTo`、`navigateBack`、`redirectTo`、`reLaunch`、`getCurrentPages` 与业务页面路径字面量均为零,声明式 navigator、动态 Uni 属性、Uni 对象逃逸与 `switchTab` 也为零;验证结果为 `MIGRATION-DEBT=0`。路由与页面栈合同分别只由 `utils/navigation-routes.js` 和 `utils/navigation.js` 持有,后续业务批次不得恢复页面私有路径或栈判断。
-
-因此问题不是某几个按钮写错,而是项目没有统一表达“打开页面、替换步骤、返回来源、完成流程、切换根页和直接进入回退”的语义合同。
-
-### 20.2 八类问题的五方案终选
-
-以下评分依次为“业务正确性/全局一致性/回归安全/维护成本/MuMu 可验证性”,5 分最好。每类只保留最终选中方案,其他方案不得作为兼容路径残留。
-
-| 问题类型 | 方案一 | 方案二 | 方案三 | 方案四 | 方案五与终选 |
-| --- | --- | --- | --- | --- | --- |
-| 导航所有权 | 各页继续直接调用 `2/1/5/1/2` | 只封装页头 `2/2/4/3/3` | 无注册表的字符串工具 `3/3/4/3/4` | 只有注册表、页面仍直调 `4/4/3/3/4` | **路由注册表+唯一导航网关 `5/5/3/4/5`** |
-| 三个根页 | 改原生 TabBar `4/2/2/2/4` | `navigateTo` `1/1/4/3/3` | `redirectTo` `2/2/3/3/4` | 页面各自混用 `2/1/4/2/2` | **保留自定义 Tabbar,统一 `goRoot` `5/5/4/5/5`** |
-| 返回与直接进入 | 固定 `navigateBack` `1/1/4/4/2` | 页头保存 fallback URL `2/2/4/2/3` | 一律回根页 `2/3/3/4/4` | 查询参数传原始 return URL `3/2/2/2/3` | **栈感知返回+规范父页+类型化来源 `5/5/3/4/5`** |
-| 列表/详情/编辑完成 | `redirectTo` 列表 `2/2/3/3/4` | `reLaunch` 列表 `1/2/2/4/4` | 固定 `navigateBack(delta)` `3/2/2/2/3` | 页面全局存整对象 `3/2/2/1/2` | **`returnTo/finishPage`+一次性结果 `5/5/3/4/5`** |
-| T03 连续看亲属 | 重复 `navigateTo` `3/2/4/3/3` | 每次 `redirectTo` `2/2/3/3/4` | 每次 `reLaunch` `1/2/2/4/4` | 原生栈设上限 `3/2/3/2/3` | **单个 T03+页内成员轨迹 `5/5/3/4/5`** |
-| 认证流程终点 | 保持混用 `2/1/4/2/3` | 全部 `navigateBack` `2/2/3/4/3` | 全部 `redirectTo` `3/2/3/3/4` | 全部 `reLaunch` `2/3/2/4/4` | **按进入、取消、完成和会话终止分别处理 `5/5/4/4/5`** |
-| 通知与外部目标 | 后端下发原始 URL `1/1/2/3/2` | N02 自己匹配字符串 `2/2/3/2/3` | 任意 URL 白名单正则 `3/3/2/2/3` | 每个消息类型写独立跳转 `4/3/3/2/4` | **`targetType+业务 ID` 本地注册表映射 `5/5/4/4/5`** |
-| Android 返回与未保存 | 只处理页头 `2/2/4/3/2` | 只处理 Android 键 `2/2/4/3/2` | 每页自由实现 `3/2/3/2/3` | 所有页面总是确认 `2/3/2/3/4` | **统一优先级状态机 `5/5/3/4/5`** |
-
-### 20.3 唯一所有者
-
-- `utils/navigation-routes.js` 是 52 个活动路由的唯一语义注册表,拥有路由键、路径、页面类型、规范父页、父页参数映射、根页、必填参数、可选参数、允许来源和目标页允许消费的结果操作枚举。
-- `utils/navigation.js` 是项目唯一允许调用 `uni.navigateTo`、`uni.redirectTo`、`uni.reLaunch` 和 `uni.navigateBack` 的业务模块;项目没有原生 tabBar,`uni.switchTab` 在该模块内外都禁止。
-- 页面和组件只调用语义方法,不拼接页面路径,不保存 fallback URL,不接收后端原始跳转 URL。
-- 注册表中的路径集合必须与 `pages.json` 的 52 个活动路由精确相等;缺失、重复和陈旧条目均使合同失败。
-
-路由参数只能使用注册表声明的标量值。ID 统一按字符串处理并逐项编码,不允许把对象、完整来源 URL、页面快照或领域数据塞进查询参数。
-
-### 20.4 语义方法
-
-```text
-openPage(routeKey, params, sourceKey)
- 打开普通子页;sourceKey 必须等于当前真实页面。当前已经是同一路由且关键参数相同则不重复入栈。
-
-goBack()
- 栈内有上一页时 navigateBack;没有时按当前路由的规范父页逐级回退。
-
-returnTo(routeKey, targetParams = {})
- 按路由键寻找最近实例并精确返回;显式 targetParams 必须与最近实例一致,目标不在栈内时才用于构造合法回退 URL;普通返回不产生流程结果。
-
-finishPage(routeKey, targetParams, result)
- 是完成并回传结果的唯一公开入口;调用方必须显式提供目标全部必填参数,当前来源页与目标页共同声明且实际存在的上下文字段必须相等;校验参数和类型化结果后精确返回,结果只能包含 operation、entityId 和 refresh。
-
-goRoot(routeKey, params)
- 只接受 A01、G01、F01、M01 四个根语义;使用 reLaunch 清理旧流程。
-
-handleBackPress(event, requestBack)
- 同步适配 UniApp 的 onBackPress:网关自己的 navigateBack 回调来源返回 false 放行,其余来源同步返回 true,并异步执行页面唯一 requestBack,避免递归拦截。
-```
-
-五个公开导航语义方法都返回 `Promise`,并共享一个在途转场锁:相同参数和相同结果语义的重复调用复用同一个 Promise,其他并发转场明确返回忙碌结果。一次性结果写入必须与“取得新锁”原子发生;复用或忙碌调用不得改写结果,导航失败必须回滚。每次转场用独立 flight 身份释放锁,`success/fail` 必须在 Promise settle 前释放自己的 flight;迟到的 `complete` 只能清理原 flight,不能清掉已经开始的新转场。所有调用方导航参数、流程结果和返回守卫上下文只接受普通对象的 own enumerable data properties;Symbol、访问器、不可枚举字段和原型继承字段一律拒绝,校验后只使用同一次读取形成的冻结快照,禁止重复 getter 读取或校验后别名篡改。`redirectTo` 只允许由网关内部的规范父链回退和目标缺栈返回使用;当前没有可公开授权的“替换步骤”边,因此不暴露无消费者的替换方法。
-
-一次性结果只存在于当前 JavaScript 进程。网关用模块内 `WeakMap` 为页面实例分配原始值身份令牌,结果 envelope 只保存令牌,不强引用或保存页面/Vue 实例。栈内返回时结果绑定反向搜索选中的最近目标令牌和该实例的规范业务参数;缺栈重建时绑定发起页令牌与完整目标参数。只有当前真实栈顶正是目标实例(或缺栈重建出的非发起页)且业务参数完全一致时才能消费,错页、同路由的更远实例和其他家谱上下文只能得到 `null`,也不得删除正确结果。结果必须在原生目标页 `onShow` 发生前随取得转场锁原子写入,消费一次后立即删除;新完成流程取得锁时淘汰已经错过目标生命周期的未消费旧结果,失败时不复活陈旧结果。字段键精确为 `operation、entityId(可选)、refresh`;`operation` 必须属于目标路由注册的 `resultOperations`,`entityId` 若存在必须为非空字符串,`refresh` 必须是布尔值。它不是领域数据持久化,不允许加入 `treeVersion、genealogyId、focusId、payload`,也不允许保存完整对象、表单内容、列表快照或接口响应。
-
-`sourceKey` 只证明当前 JavaScript 进程内的一次真实导航:`openPage` 必须核对它与 `getCurrentPages()` 的当前真实路由一致。栈深为 1 或外部直接进入时,查询串里的 `sourceKey` 一律视为不可信并忽略,只按注册表的 `parent/parentParamMap` 建立回退目标;外部链接不能伪造来源合同。
-
-### 20.5 根页与页头
-
-- G01、F01、M01 继续使用自定义 `AppTabbar`;切换根页统一 `goRoot`,点击当前项不做任何跳转。
-- A01 是认证根页;登录、注册完成取得有效会话后统一 `goRoot(G01)`。
-- G01、F01、M01 不显示普通返回箭头。左侧品牌只有绑定明确动作时才可点击,否则为非交互品牌标识。
-- 根页右侧分别保留 G01 消息、F01 发布、M01 资料操作。
-- 普通 `PageHeader` 删除 `fallbackUrl` 和直接路由判断;普通返回统一进入导航网关,未保存页面使用同一个返回守卫。
-- 根页没有弹层时,Android 返回交给系统;有弹层时先关闭弹层。
-
-### 20.6 返回、取消与完成
-
-返回优先级固定为:
-
-```text
-关闭最上层预览、弹窗、搜索或抽屉
-→ 消费 T03 等页面内部轨迹
-→ 页面正在提交时阻止离开并给出状态
-→ 有未保存输入时显示放弃确认
-→ 执行普通 goBack
-```
-
-页头返回、页面取消按钮和 Android 返回键必须进入同一状态机,不能出现三个不同结果。
-
-关键流程终点:
-
-- A04 取消或“已有账号”返回 A01;注册并建立会话后 `goRoot(G01)`。
-- A05 取消返回 A01;只有未来真实重设接口成功才写入 `password-reset` 结果并回 A01。本地 `state=success`、计时器或视觉占位成功态只能普通返回,不得生成业务成功结果。
-- A01 登录成功 `goRoot(G01)`;会话失效和退出成功也只允许 `goRoot(A01)`。
-- 当前 F02、F06、F07、F09 只形成明确标注“尚未提交服务器”的独立本地预览;F03 评论草稿不插入评论列表、不清空、不增加计数,F05 收藏明确禁用,F10 明确未开放。F01—F10 均不产生写成功结果;F02/F03 返回精确 F01,F06 新建回 F04、编辑回精确 F05,F09 无结果回同一 `genealogyId + albumId` 的 F08。真实写接口返回服务器 ID 后才能同轮启用完成结果。
-- `data/mock.js` 是 F 系列 feed/article/album 只读夹具的唯一 owner,只公开按 `genealogyId` 列表和按复合身份详情的深拷贝查询;跨谱、未知实体或缺失身份失败关闭。`utils/api.js::createFeed` 在 mock 模式以 `WRITE_UNAVAILABLE` 拒绝,不得修改列表冒充发布成功。
-- R02 回 R01;R04 回 R03;R06、R07 回 R05。
-- 当前 T04/T05/T06 只生成“尚未提交服务器”的本地预览,不产生写成功结果;用户确认放弃预览后,T04/T06 无结果回 T01,T05 使用 `goBack()` 精确回原 T03 实例,T08 普通返回 T03,T07 可进入 T03。新增亲属、编辑成员和编辑关系的完成定位只能在真实版本化写接口同轮启用。
-- 当前阶段 `data/mock.js::treeMembers` 是唯一可变成员夹具 owner,`utils/api.js` 是唯一写入口;T01/T03—T08 只能通过 `listTreeMemberFixtures(genealogyId)`、`findTreeMemberFixture(genealogyId, personId)` 取得含亲属数组深拷贝的快照。成员身份必须由家谱与成员复合定位,缺失、未知或跨家谱身份失败关闭;只有 T04 的明确首位成员模式允许没有 `personId`。Task 18 接入真实新图合同后必须原子删除该临时 owner、选择器和旧 `id/parentId` 模型,不保留双读适配层。
-- N02 默认回 N01;通知业务目标失效、无权限或字段不足时留在 N02 的明确状态,不猜测页面。
-
-2026-07-22 新线上 OpenAPI 已确认密码登录、短信登录和注册统一返回 `RAppLoginVo`,其 `data` 引用 `AppLoginVo`,唯一会话字段为 `access_token`。因此 A04 的正式终点不是“注册后再登录”,而是保存有效会话后直接 `goRoot(G01)`;受保护旧快照的响应形状不再作为兼容读取路径,在真实注册与行为验证尚未接入前也不得把当前占位反馈冒充注册完成。
-
-### 20.7 T03 单实例成员轨迹
-
-- T03 原生页面实例只保留一个。初始路由 `personId` 是不可变的宿主页路由身份,初始成员成功读取后先把轨迹初始化为恰好 `[initialPersonId]`;初始读取失败不建立轨迹。点击亲属只更新页面内活动成员 `personId` 和成员轨迹,不改 URL,也不再 `navigateTo` 同一路由。
-- 新成员资料成功读取后才写入轨迹;读取失败保留原成员和原轨迹。
-- 返回先逐项弹出成员轨迹,轨迹结束后才返回 T01、T07、R02 或实际来源。
-- 当前 T05 本地预览以 `goBack()` 返回并保留原 T03 宿主页身份、活动成员和轨迹,T08 普通返回也不新增 T03。未来真实成员更新结果只允许刷新与 `entityId` 相同的当前活动成员,不得切换轨迹或改写宿主页身份。
-- 如果 T03 已位于原生栈下方,再次打开同一 `genealogyId` 的 T03 时必须回到该实例,并用目标页允许的类型化一次性操作请求加载目标成员;不得创建第二个 T03。若栈中 T03 属于不同 `genealogyId`,网关返回 `T03_CONTEXT_CONFLICT` 并拒绝压栈;若迁移前遗留栈已有多个 T03,则返回 `T03_STACK_CONFLICT`,不得只激活最近实例后宣称栈已唯一。调用方必须先返回或通过根语义清理冲突上下文。
-- 从直接链接进入 T03 且没有来源页时,规范父页为带当前成员定位参数的 T01;缺少 `genealogyId` 时继续回退 G01。
-
-### 20.8 通知和外部进入
-
-- 后端只返回 `targetType` 与该业务所需 ID,不返回客户端路由字符串。
-- `targetType` 必须由本地固定映射转换为路由键,并先验证登录态、权限、目标存在性和必填参数。
-- 外部进入先建立正确根页,再打开目标;目标失效时落入可理解的消息状态,不打开空白页面。
-- 未知 `targetType`、多余参数和原始 URL 必须明确拒绝。
-
-### 20.9 导航完成定义
-
-- 页面和组件中直接调用五种 Uni 导航 API 的扫描结果为零。
-- 路由注册表与 `pages.json` 精确闭合。
-- 所有根页、普通页、直接进入、完成回流和异常回退满足上述不变量。
-- MuMu 对每个受影响流程验证进入、返回、取消、完成和重复进入;T03 验证 A→B→C→B→A→来源且原生栈不增长。
-- 每个迁移批次独立运行聚焦合同、全局响应式合同、编译审计和全量合同,不进行机械一次性替换。
-
-## 二十一、T01 大规模世系树专项设计
-
-### 21.1 已证实的 P0 与当前上限
-
-当前 T01 不是只在“几百代”时才有风险,默认 6 人数据已经确定性断线:
-
-- 布局得到 103 的横坐标为 550,唯一子女 106 的横坐标为 675。
-- 父干线只画在 550,水平支线却只覆盖子女的 `minX..maxX`,唯一子女时只位于约 675—680,两段完全不相交。
-- `NODE_HALF_HEIGHT=47`,普通节点实际半高为 43,只有选中节点半高为 47;普通节点端点天然留下约 4rpx 间隙。
-- 现有 10 代×12 人压力数据中,约 45/54 个父分组会出现相同父干线断开;测试只断言线段数量大于 30,因此稳定漏报。
-- 当前布局每一代都重新过滤全体成员,最坏为 `O(G×N)`,一人一代时接近 `O(N²)`;300 代单链约生成 13233 行 CSS Grid track。
-- 页面、公共 mock 与 OpenAPI 分别使用 `parentId`、无关系字段、递归 `children/spouses+fatherId/motherId`,直接接接口可能只显示根节点或完全没有连线。
-
-### 21.2 五方案终选
-
-评分依次为“业务正确性/全局一致性/回归安全/维护成本/MuMu 可验证性”。
-
-| 方案 | 评分 | 结论 |
-| --- | --- | --- |
-| 修补现有 CSS Grid 与全量 DOM | `2/4/4/4/5` | 可修眼前断线,无法满足百代与宽支系,拒绝。 |
-| 只改为可折叠线性目录 | `4/5/4/4/5` | 作为无障碍和降级模式保留,不能替代图谱。 |
-| 全量 SVG 整洁树 | `3/3/3/3/4` | 几何易测,但数千图元和超大世界尺寸风险高,拒绝。 |
-| Canvas 画线、DOM 叠节点 | `4/4/2/2/3` | App-vue 跟手手势中存在跨层不同帧错位风险,拒绝。 |
-| **渐进图窗口+视口单 Canvas 同画节点和边** | **`5/5/3/3/5`** | **最终方案。** |
-
-DCloud 官方文档明确说明 App-vue 的流畅 Canvas 动画应把绘制放在视图层并避免频繁跨层通信;renderjs 只支持 App-vue/H5,Vue 3 项目不能直接在当前 `script setup` 页面内使用该写法。因此使用普通 Options API 的专用 Canvas 组件承载 renderjs,T01 页面继续负责低频业务编排:
-
--
--
--
-
-### 21.3 产品与页面结构
-
-T01 定位为“以焦点成员为中心的可探索世系窗口”,不是一次性展开整本族谱的手机长图。
-
-- 焦点优先级固定为:路由 `selectedId` → 当前账号绑定成员 → 后端主始祖。合法 `state=EMPTY` 显示空谱并允许录入首位成员;只有 `state=POPULATED` 缺少有效焦点或窗口入口时才显示合同异常,客户端不猜测成员。
-- 初始窗口固定为焦点上两代、下两代;这只是首次窗口,不是最大世代。
-- 主世系是骨架;配偶并排,每段家庭关系具有独立联合点,子女从对应联合点向下。
-- 同一家庭 Scene 在任何状态下最多直接显示 5 名真实子女。投影先沿 primary 入边从焦点反向推导受保护主路径;每个祖先家庭都必须保留通向焦点的那名子女,再用相邻 order 补足最多 5 人,不能把焦点祖先链聚合掉。其余成员形成“前 N 人”“后 N 人”聚合节点;存在隐藏可见成员时点击后以最近的稳定人物 ID 重建窗口,只有隐私成员时聚合节点不可聚焦。原焦点进入会话历史,聚合不在原图无限展开,也不截断后端数据。
-- 顶部继续使用 `PageHeader`,下方为薄上下文工具条;一级操作是搜索和全谱,图谱/列表切换、关系图例、关系维护和阅读帮助进入更多。
-- 左侧大面积代际栏改为 Canvas 内轻量标尺;缺代显示“中间缺 N 代”,不能把第 14 世和第 50 世误画成相邻世代。
-- 右下控制组提供放大、缩小、适合当前支系和回到焦点,点击区域至少 44dp。
-- 资料抽屉只有收起与半屏两档;完整资料进入既有 T03,禁止在 T01 再复制一套全屏人物详情。
-- 抽屉吸附完成后才更新视口底部 inset,并把选中节点移入剩余安全区域;不得覆盖节点。
-
-### 21.4 缩放、定位和概览
-
-缩放范围为 0.30—2.00,默认按当前窗口适配且不自动放大超过 1.0:
-
-| LOD | 缩放 | 内容 |
-| --- | --- | --- |
-| L0 | 0.30—0.44 | 当前已加载窗口的家庭、支系聚合与数量,不显示姓名。 |
-| L1 | 0.45—0.74 | 姓名和隐私、缺失等状态。 |
-| L2 | 0.75—1.34 | 标准人物节点、世代、关系和支系。 |
-| L3 | 1.35—2.00 | 在标准节点上增加生卒摘要。 |
-
-- 阈值使用 0.05 迟滞,避免临界缩放闪烁;Canvas 文字低于 12sp 时隐藏次要信息,不继续压小字号。
-- 双指缩放以手势中心为基点;按钮每次按固定比例缩放;搜索定位后至少进入 L2。
-- 单击只选中并打开抽屉;双击、点击居中或搜索结果才改变焦点并重建上二下二窗口。`REDACTED` 节点只允许显示通用隐私说明,不允许双击、居中、进入详情或成为焦点。
-- 当前会话内保留最多 20 条定位记录;只保存 `focusPersonId、treeVersion、matrix`,不做最近浏览和离线持久化。
-- 全谱是独立的“世代×支系”聚合视图,不是把全部人物缩小。它只展示权限过滤后的密度、根、支系覆盖和待归支统计,点击后再请求局部窗口。
-- 图谱和线性列表消费同一规范图、焦点、树版本、已加载边界和搜索结果;不存在独立的页内聚合展开状态。Canvas 不可用或无障碍需要时,列表仍能搜索、选择可见成员并进入 T03/T04/T06,隐私成员只显示不可跳转的通用说明。
-
-### 21.5 四类端点与异常数据
-
-| 状态 | 后端或客户端事实 | 页面行为 |
-| --- | --- | --- |
-| 未录入 | 后端 boundary `MISSING` | 连到完整占位端点;有权限才显示补录。 |
-| 隐私隐藏 | 后端 boundary `REDACTED` | 连到匿名端点,不返回可推断身份的信息。 |
-| 尚未加载 | 后端 boundary `UNLOADED` | 显示数量和展开动作,必须携带版本绑定 cursor。 |
-| 加载失败 | 客户端 boundary runtime `FAILED` | 保留原图与 cursor,只局部重试。 |
-
-重复 ID、缺引用、自环、主图循环、多条主入边、反向代际和版本错配不能进入正常布局。部分合法数据仍可展示时显示诊断横幅;不允许通过不画线来隐藏错误。
-
-### 21.6 传输合同
-
-Apifox 是接口唯一源头,本地 JSON/YAML 只是同版本只读导出。旧递归 `LineagePersonTreeView` 必须被一个规范窗口原子替换,客户端不保留兼容读取。
-
-```text
-LineageGraphWindow
-├─ version { schemaVersion, treeVersion, generatedAt }
-├─ state EMPTY | POPULATED
-├─ genealogyId
-├─ nodes[]
-├─ familyUnits[]
-├─ edges[]
-└─ window { focusPersonId, entryPersonIds, scope, generationRange, returnedNodeCount, boundaries[] }
-```
-
-关键字段合同:
-
-- 所有人员、家庭、关系和引用 ID 都是非空字符串;非空 `avatarOssId` 也必须是字符串,未设置头像时只允许 `null`。后端 `int64` 不得作为 JSON Number 传给 JavaScript。稳定人物 ID 不得以 `redacted:` 开头;匿名人物 ID 精确使用 `redacted:{treeVersion}:{token}`,客户端可据此阻止它进入 FOCUS、locator、搜索、写接口和 overview 跳转目标。
-- `LineageGraphWindow` 以 `state` 为 discriminator 使用 `oneOf`。EMPTY 只允许 `nodes/familyUnits/edges=[]`,且 `focusPersonId=null、entryPersonIds=[]、generationRange=null、returnedNodeCount=0、boundaries=[]`;这是合法空谱,不是合同错误。POPULATED 必须有非空 nodes、引用其中 VISIBLE 节点的非空 `focusPersonId`、至少一个引用当前 nodes 的 `entryPersonIds`、非空 generationRange,且 `returnedNodeCount === nodes.length`。
-- `entryPersonIds` 精确等于“当前返回窗口中没有 primary 入边的节点集合”,不是全谱始祖列表;secondary 入边不会取消窗口入口身份。每个入口节点的 `entryReason` 为 `GENEALOGY_ROOT/WINDOW_CUT/DISCONNECTED_COMPONENT`,非入口节点为 `null`;每个入口在当前窗口恰有零条 primary 入边,每个非入口恰有一条 primary 入边,因此从任意焦点沿 primary 必然回溯到某个入口。`GENEALOGY_ROOT` 表示全谱主森林根,`WINDOW_CUT` 表示其 canonical primary 父边在窗口外,`DISCONNECTED_COMPONENT` 表示没有可达全谱根的 canonical primary 链;因此第 50 代焦点的上二代窗口不会被伪装成全谱根。全谱根只由 overview 的可见根/隐私根计数和 locator 的根可见性分支表达。
-- 人物节点以 `visibility` 为 discriminator 使用 `oneOf`。`VisibleLineagePerson` 固定包含 `id、generation、displayName、sex、avatarOssId、branchId、branchPath、order、visibility=VISIBLE、entryReason`;其 `id` 是可用于 FOCUS、locator、搜索和写接口的稳定人物 ID,`sex` 只允许 `MALE/FEMALE/UNKNOWN`。`RedactedLineagePerson` 只允许 `id、generation、displayName、order、visibility=REDACTED、entryReason`,其中 displayName 固定为通用“隐私成员”,id 是仅在当前 `treeVersion` 内可作当前图内部引用的不可解析 opaque ID,不得用于 FOCUS、locator、搜索或写接口,也不得进入任何 `focusPersonId/targetPersonId`;不得返回 sex、avatar、branchId、branchPath 或其他身份字段。两类节点的 `generation` 都是大于等于 1 的整数,`order` 是非负整数。
-- `FamilyUnit` 包含稳定 `id、anchorPersonId、partnerRelationship、partners、order`。`partners` 只允许一个单亲成员,或同一伴侣关系中的两人;每项包含 `personId、partnerRole、order`,`partnerRole` 只允许 `ANCHOR/PARTNER`,且恰有一个 ANCHOR 与 `anchorPersonId` 相等。双人家庭的 `partnerRelationship` 必含 `relationshipId、relationshipKind=PARTNER、relationType、status`,其中 `relationType` 为 `MARRIAGE/PARTNERSHIP/UNKNOWN`,`status` 为 `ACTIVE/ENDED/UNKNOWN`;单亲家庭该字段为 `null`。同一人物的不同伴侣关系必须拆成不同家庭单元。
-- `ParentChildEdge` 从家庭单元指向一个子女,包含 `id、familyUnitId、childId、lineageParentId、parentRelations、primary、order`。每个 `parentRelations` 项都包含稳定 `relationshipId、relationshipKind=PARENT_CHILD、personId、parentRole、relationType`;`parentRole` 使用 `FATHER/MOTHER/PARENT/GUARDIAN/UNKNOWN`,`relationType` 使用 `BIOLOGICAL/ADOPTIVE/STEP/GUARDIAN/UNKNOWN`。`lineageParentId` 必须同时出现在该边的父母关系和家庭成员中,子女不得同时是该家庭成员;primary 入边与 `entryPersonIds` 必须满足上一条的零条/恰一条森林不变量,布局不得根据数组顺序猜测主世系父母。
-- 所有父子关系都参加缺引用、自环和有向循环校验,不能只检查 `primary` 主森林;`primary` 只决定布局主干,不降低次要收养、继亲或监护关系的数据正确性要求。
-- boundary 锚点可以是 PERSON、FAMILY_UNIT 或 WINDOW;PERSON/FAMILY_UNIT 的 `anchorId` 必须引用对应实体,WINDOW 的 `anchorId` 固定为 `null`。方向为 ANCESTORS、DESCENDANTS、LATERAL,原因只允许 MISSING、REDACTED、UNLOADED;`hiddenCount` 只能是非负整数或 `null`,cursor 只在 UNLOADED 时为非空字符串,其他原因固定为 `null`。网络 FAILED 是客户端状态。
-- 当前窗口内返回但匿名化的人物使用 `Node.visibility=REDACTED`;窗口之外因权限隐藏的拓扑使用 `boundary.reason=REDACTED`。同一个隐藏对象在同一响应中不得既作为匿名节点又作为隐藏边界,避免重复计数和关系推断。
-- 每个窗口对其返回的边保持引用闭包;服务端 `limit` 绝对上限 500。
-- cursor 与 `genealogyId、treeVersion、boundaryId` 绑定;版本变化返回 `409 TREE_VERSION_CHANGED`。
-- 关系写操作携带 `If-Match`,成功返回新版本和受影响的人员、家庭及关系 ID。
-
-`/lineage/tree` 使用两个互斥查询模式,不能由客户端拼出第三种组合:
-
-- `mode=FOCUS`:`focusPersonId` 可选且只能是调用者可见的稳定人物 ID,REDACTED opaque ID 不得作为焦点;缺省时服务端按“当前账号绑定成员→主始祖”确定并在响应中返回实际焦点。不可见、过期或不存在的焦点统一返回 `404 LINEAGE_FOCUS_NOT_AVAILABLE`,不泄漏成员是否存在;`ancestorDepth/descendantDepth` 是 0—20 的整数、可选且默认 2;`boundaryId/cursor/treeVersion` 必须缺席。
-- `mode=BOUNDARY`:`boundaryId/cursor/treeVersion` 三项必填;`focusPersonId/ancestorDepth/descendantDepth` 必须缺席。
-- 两种模式的 `limit` 都是整数,最小 1、默认 200、最大 500;任何混合、缺项或多余组合返回 HTTP `422` 与 `LINEAGE_QUERY_INVALID`。接口同时明确 `400/401/403/404/422/429/5xx` 响应。
-
-全谱概览不复用窗口的 `returnedNodeCount` 冒充全谱总数。`/lineage/tree/overview` 只接受必填查询参数 `treeVersion`;服务端只返回该快照,版本已变化时返回 `409 TREE_VERSION_CHANGED`,客户端不得把不同版本的概览与窗口并用。
-
-`LineageOverview` 包含同一 `{ schemaVersion, treeVersion, generatedAt }` 以及 `state、genealogyId、genealogyPersonCount、genealogyRootPersonIds、redactedGenealogyRootCount、generationRange、buckets`,并以 `state=EMPTY/POPULATED` 使用 `oneOf`。EMPTY 精确要求 `genealogyPersonCount=0、genealogyRootPersonIds=[]、redactedGenealogyRootCount=0、generationRange=null、buckets=[]`。POPULATED 要求 `genealogyPersonCount>0`、非空 generationRange 和 buckets,且 `genealogyRootPersonIds.length + redactedGenealogyRootCount >= 1`;各 bucket 的 `visibleCount/redactedCount/unloadedCount` 均为非负整数,三类计数在全部 buckets 的总和等于 `genealogyPersonCount`。
-
-`genealogyRootPersonIds` 只包含调用者可见、可用于 FOCUS 的稳定人物 ID;隐私根只计入 `redactedGenealogyRootCount`,绝不返回 opaque ID。bucket 的 `focusPersonId` 只能是该 bucket 内可见稳定人物 ID;没有可见目标时固定为 `null`。
-
-定位接口返回 `{ treeVersion, genealogyId, personId, rootVisibility, rootPersonId, pathCompleteness, ancestorPathSegments, generation, branchId }`。根可见性与路径完整性是两个独立 discriminator:`rootVisibility=VISIBLE` 时 `rootPersonId` 是可见稳定 ID,`rootVisibility=REDACTED` 时 `rootPersonId=null`;`pathCompleteness=COMPLETE` 表示路径没有隐私缺口,`pathCompleteness=REDACTED_GAPS` 表示含一个或多个隐私段,允许“可见根→隐私中间祖先→可见目标”。
-
-`ancestorPathSegments` 以 `kind` 使用 `oneOf`:VISIBLE 段精确为 `{ kind: "VISIBLE", personIds: [...] }`,数组非空且只含可见稳定 ID;REDACTED 段精确为 `{ kind: "REDACTED", hiddenCount }`,`hiddenCount` 为正整数或因权限不披露时为 `null`,不得包含任何人物 ID。相邻段 kind 必须交替,整条路径最后一个 VISIBLE 段必须以目标 `personId` 结束;可见根时第一个 VISIBLE 段必须从 `rootPersonId` 开始,隐私根时第一段必须是 REDACTED。COMPLETE 恰好没有 REDACTED 段,REDACTED_GAPS 至少有一段。任何分支都不得返回客户端路由或隐私 opaque ID。
-
-### 21.7 客户端所有者与处理链
-
-```text
-OpenAPI 响应
-→ normalize
-→ validate
-→ project
-→ 确定性 family-unit tidy-tree layout
-→ Scene 与空间索引
-→ 平台 Canvas 渲染器
-```
-
-- `utils/lineage/` 是规范化、校验、投影、布局和空间索引的唯一客户端所有者。
-- `normalize` 负责按 `order、id` 作一次确定性排序,最坏复杂度为 `O(N log N + E)`;`validate` 通过索引和一次图遍历保持 `O(N+E)`;`project` 只消费已规范化顺序并保持 `O(N+E)`,不得在投影阶段重复全量排序。
-- `project` 只从已校验的完整窗口图生成当前可见投影:先由唯一 primary 入边推导焦点到窗口入口的受保护人员与家庭,再为每个家庭选出包含受保护子女的最多 5 名真实子女;无受保护子女的家庭稳定选择 order 最小的 5 人。其余连续区间生成带 `direction、hiddenCount、focusable、targetPersonId` 的“前 N 人/后 N 人”虚拟聚合节点;存在隐藏可见成员时 `focusable=true` 且 `targetPersonId` 指向最靠近当前可见窗口的稳定人物 ID,仅含隐私成员时 `focusable=false、targetPersonId=null`。点击可聚焦聚合节点后以该成员重新聚焦,不存在 `expandedAggregateIds` 或不断增长的页内展开状态。完整规范图继续供搜索和线性列表使用;布局只消费投影,Scene 不得再次决定聚合规则。
-- 布局按 `order、id` 稳定排序,自底向上计算子树轮廓;家庭联合点必须位于可见子女跨度中心,单子女时严格同轴。
-- Scene 根对象精确为 `{ sceneVersion, treeVersion, focusPersonId, bounds, items }`。`utils/lineage/scene.js` 是 `sceneVersion` 唯一所有者,按 `treeVersion + projectionSignature + LINEAGE_LAYOUT_VERSION + fontMetricsVersion` 生成确定性摘要;Scene 使用世界坐标并只由可 JSON 序列化的数组、对象、字符串、数字和布尔值组成,不得跨 renderjs 边界传递 `Map`、函数、Vue、DOM、rpx、Canvas context、空间索引或平台对象。瞬时 `selectedId` 不属于 Scene payload,也不参与 `sceneVersion`。
-- `components/LineageViewport.vue` 使用普通 Options API;App-vue/H5 的 renderjs 持有 Scene、相机、手势、LOD、裁剪、命中和逐帧绘制。
-- Canvas 物理尺寸始终等于视口,不等于几百代的世界尺寸;只绘制视口加 overscan 内对象。
-- 节点、文字、联合点、关系线、聚合节点、端点、代际标尺和选中光晕全部在同一 Canvas、同一矩阵、同一帧绘制;选中光晕由 renderjs 使用独立 `selectedId` 和 Scene 内稳定人物 Rect 动态绘制,不修改 Scene、布局或版本。
-- DOM 只保留 PageHeader、工具条、两档抽屉、搜索、全谱概览和线性列表。
-- mp-weixin 复用同一 Scene 的 Canvas 适配器;窗口超过能力或持续不达性能门槛时进入线性列表,不另造关系规则。
-- renderjs 读取 `scene.sceneVersion` 后先验证版本与 payload、在视图层重建空间索引,再原子交换 Scene、索引和版本;缺少版本或同一版本对应不同 payload 必须拒绝并保留旧 Scene。平移、缩放与惯性期间零跨层通信;只在手势结束、焦点变化或业务确需边界请求时回传相机状态。
-- 视口、底部 inset 或 DPR 变化时先重设 transform,再把 backing store 设为视口乘 DPR、CSS 尺寸设为逻辑视口;字体就绪或回退字体变化后重新测量文字、生成新的 `fontMetricsVersion` 并生成新 Scene,不能沿用旧测量值。
-
-### 21.8 “连线永不断”不变量
-
-1. 每个家庭成员都恰有一个可追踪的 `family:{familyUnitId}:partner:{personId}` 连接器指向联合点;单亲联合点若与人物锚点重合,可以省略孤立的零长度笔画,但关系对象仍可反查。
-2. 折线相邻段端点在世界坐标中完全相等,DPR 变换后误差不超过 0.5 个物理像素。
-3. 单子女使用连续路径,不创建孤立零长度横梁。
-4. 锚点从实际 Scene Rect 计算,不允许全局半高常量。
-5. 选中态只画外部光晕,不改变节点宽高、布局或锚点。
-6. 每条 `ParentChildEdge` 恰好对应一个 `edge:{edgeId}` 连接器,其起点必须是 `familyPoint(familyUnitId)`,终点必须是实际子女人物锚点;Scene connector 也能反查唯一传输 edge。
-7. 主关系线不得穿过无关人物节点,纯主树的主关系交叉数必须为零。
-8. 视口裁剪依据路径包围盒;即使两个端点都在视口外,只要路径穿过视口就必须绘制。
-9. 未录入、隐私、未加载和聚合关系必须连接到明确端点,不允许悬空或静默消失。
-10. 新窗口通过校验后原子替换旧 Scene;不得用新节点配旧边或新边配旧节点。
-
-### 21.9 后端最小改动
-
-为避免静默破坏既有 v1 消费者,后端新增并固定以下四条 v2 路径:
-
-```http
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/tree
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/tree/overview
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/persons/{personId}/locator
-PATCH /genealogy/app/v2/genealogies/{genealogyId}/lineage/relationships/{relationshipId}
-```
-
-- `/lineage/tree` 查询参数固定为 `mode、focusPersonId、ancestorDepth、descendantDepth、boundaryId、cursor、limit、treeVersion`,按 FOCUS/BOUNDARY 互斥规则校验;不再接受 `branchId、generation`。
-- `/lineage/tree/overview` 必须携带当前 `treeVersion`,只返回同版本的代际与支系聚合桶,并只为存在可见稳定人物 ID 的桶提供 `focusPersonId`;版本变化返回 `409 TREE_VERSION_CHANGED`。
-- `/locator` 返回目标人物、根可见性分支、`ancestorPathSegments` 隐私安全分段祖先路径、代数、支系和树版本;REDACTED 段不得返回人物 ID,任何分支都不得返回 opaque ID。
-- 现有人物搜索只需稳定返回字符串 `personId`;新增人物、编辑人物和编辑关系接口必须加入版本并发合同。当前 OpenAPI 没有 T06 所需的关系修改入口,因此新增上述关系 PATCH。不可变 `relationshipKind` 只允许 `PARTNER/PARENT_CHILD`,必须与服务端既有关系一致;请求使用以该字段为 discriminator 的 `oneOf`:PARTNER 分支只更新 `relationType/status`,PARENT_CHILD 分支只更新 `relationType/parentRole`。每个分支除 `relationshipKind` 外至少包含一个可修改字段,省略字段保持原值;只有 discriminator 的空更新返回 `422 RELATIONSHIP_PATCH_EMPTY`。参与人和 `relationshipKind` 不可在 PATCH 中偷换,也不以客户端删除再新增模拟修改。
-- 旧 v1 `/genealogy/app/genealogies/{genealogyId}/lineage/tree` 保持原合同供既有消费者使用;当前 App 只接入上述四条明确的 `/genealogy/app/v2/...` 路径,不双读、不做运行时版本探测。
-
-四条操作统一声明 `200/400/401/403/404/422/429/5XX`;tree、overview 和 relationship PATCH 还必须声明 `409`。稳定业务码字段唯一固定为错误响应根层必填字符串 `businessCode`,对应 HTTP 响应使用 `oneOf` 分支中的单值 enum;OpenAPI 3.1 也可使用 `const`。description、example 或无关 metadata 中出现同名文本都不构成合同。`generationRange` 固定为关闭额外字段的 `{ minGeneration, maxGeneration }`,两项均为大于等于 1 的整数;`minGeneration <= maxGeneration` 由运行时校验。
-
-接口门禁分为两层,不能互相冒充:`tests/lineage-openapi-contract.ps1` 的静态层只验证 OpenAPI 能结构化表达的路径、参数全集与单字段边界、响应引用闭包、discriminator/oneOf、精确字段集、枚举、字符串 ID、错误响应、`If-Match`、JSON/YAML 引用一致性以及 v1 隔离。平铺 query Parameter Objects 即使在 OpenAPI 3.1 中也不能证明 FOCUS/BOUNDARY 的跨参数互斥;入口集合、引用、环、bucket 总和、隐私根、locator 分段首尾、cursor/version 绑定、409/422 真实行为及 PATCH 省略字段保持原值同样必须由运行时 validator 与部署集成测试验证,禁止用 description、example 或关键词命中制造假绿。支持 schema 的文件名不由客户端另造,固定根模型之外沿真实 `$ref` 闭包验证结构;YAML 静态层只证明限定块内的路径、operationId 和完整 component 引用闭包与 JSON 一致,字段语义仍必须在后端同版本导出后逐项复核。
-
-### 21.10 明确删除的旧路径
-
-同一迁移中删除:页面内置运行时 members、递归 `children/spouses`、单一 `parentId`、`fatherId/motherId` 与 `parentId` 双读、`person.id || person.personId`、API 或 fixture 的 `x/y`、数字 int64 ID、默认“族人/主支”语义兜底、顶层 `.map(toTreeNode)`、全量 CSS Grid track、多 `` 拼线、Canvas 线叠 DOM 节点、选中态改尺寸和全局 `NODE_HALF_HEIGHT`。
-
-### 21.11 测试与 MuMu 门槛
-
-测试先锁定当前 103→106、普通节点 4rpx 和 10×12 大量父干线断开,再依次覆盖:
-
-- 合法单根、单亲、多配偶、多根、收养、隐私、字符串大 ID 和窗口边界。
-- 旧递归结构、`parentId`、数字 ID、重复、缺引用、自环、循环、多主入边和版本错配必须明确失败。
-- 6 人、10×12、20×20、5×100、100×3、300×1、单家庭 200 子女、缺第 2—49 代、乱序输入和极不平衡树;500 代单链只作纯逻辑校验,不作为 MuMu 手工搜索目标。
-- 每条线的锚点、连续段、反查、穿节点、交叉、DPR、视口裁剪和选中前后几何。
-- 搜索定位、聚合跳转与返回焦点、版本冲突、焦点保持、Canvas context 恢复和图谱/列表一致性。
-
-当前 MuMu 不启动、不关闭,不调整模拟器窗口缩放比例、设备分辨率、方向或系统字体;App 内双指缩放属于 T01 功能验证。只在现有 `emulator-5554 / 720×1280 / 320dpi` 配置验证:
-
-- 默认首屏和 103→106;单指平移、双指缩放、按钮缩放及四级 LOD。
-- 10、50、100、300 代搜索或概览定位。
-- 宽支系聚合、前后人数、聚合跳转、回到上一焦点,且受保护祖先链始终连续。
-- 多配偶联合点及子女归组;未录入、隐私、未加载和局部失败端点。
-- 两档抽屉、T03/T04/T06/T07 返回定位、长姓名、同名搜索、空谱、无权限和异常关系。
-- 60 秒连续操作、20 次聚合跳转与搜索,以及自动几何探针和同场景逐边视觉探针;两者都为零违规才通过。
-
-性能门槛:单窗口不超过 500 人;`dataReady` 定义为规范图完成校验的时间点,`interactive` 定义为首帧绘制结束且命中索引可用,二者间隔不超过 800ms;输入到反馈 p95 不超过 100ms;持续手势帧耗时 p95 不超过 32ms;不连续出现两帧超过 100ms;20 次聚合跳转与搜索后驻留内存相对稳定态增长不超过 15%。每项 MuMu 时延指标至少采样 30 次并按 nearest-rank 计算 p95;手势帧由 renderjs 的 `requestAnimationFrame` 记录,输入延迟从视图层触摸时间戳量到下一完成帧;内存先预热 3 轮,再在相同空闲点比较 20 轮。不把全 App 冷启动混进 T01 门槛。未达到门槛时缩小窗口或进入列表,不能提高上限掩盖问题。
-
-## 二十二、认证、TAC 与可访问安全设计
-
-### 22.1 唯一所有者
-
-- `utils/auth-verification.js` 唯一拥有 `APP_SMS_LOGIN/APP_REGISTER/APP_FORGOT_PASSWORD` 三个认证场景、4 位短信码和 require/verify 响应边界。
-- `components/TacVerification.vue` 唯一拥有 TAC 浮层、renderjs 加载、可见生命周期、焦点和返回行为;页面不得直接操作供应商全局对象。
-- `static/tac/js/jiapu-tac-adapter.js` 唯一拥有 TianAi challenge、proof 与 verify payload 映射。后端提供的 `tac.css/tac.min.js/icon.png/dun.jpeg` 保持原字节,由专项哈希合同保护。
-- `utils/api.js` 唯一拥有已审查请求的 HTTP 200 严格 envelope、15 秒超时、RequestTask 中止和错误分类,并拥有认证密码摘要、`validToken` 发码、`AppLoginVo.access_token` 会话写入及反馈 wire payload。页面不复制 header、地址、响应兼容、token 读取或请求控制器。
-
-### 22.2 页面与状态机
-
-A01 默认密码登录并已接入线上密码 wire、`access_token` 持久化和 G01 跳转;默认 mode 保持 mock。remote 联调先展示 static TAC,但登录端点尚未消费 `validToken`,所以这不是安全闭环,`API-AUTH-TAC-001` 仍阻止发布;微信登录也不得以视觉入口冒充已接通。A01/A04/A05 的短信发码顺序固定为:本地字段和协议校验 → `/captcha/require` → 严格 TAC challenge/verify → 取得服务端 `validToken` → `/genealogy/app/auth/sms/code`。验证码精确 4 位,注册或重设提交只消费短信码,不再重复 TAC。手机号或密码变化、刷新 challenge、切换验证方法、返回或卸载都使旧上下文失效;超时、空响应、非 JSON、重复回调和迟到回调失败关闭并保留表单。
-
-短信状态覆盖可发送、验证中、发送中、60 秒倒计时、失败重试、到期、手机号变更和重复点击。客户端倒计时不是服务端限流证据;最终仍须用真实服务验证手机号/IP/设备/租户限流、前后台恢复、过期和并发重放。注册成功只读取 `RAppLoginVo → AppLoginVo.access_token`,保存会话后直接进入 G01;找回成功返回 A01,不自动登录。
-
-### 22.3 后端验证中心合同
-
-`VerificationCenter` 是唯一授权 owner,供应商只提供 evidence,不直接签发或消费短信票据。`/captcha/require` 建立绑定 tenant、client、scene、规范化 subject 和风险策略版本的 `verificationSessionId`;`required=false` 也直接签发供指定 audience 使用的一次性 grant,不能让短信端点出现无票据分支。同一 session 只允许一个活动 challenge;刷新或切换方法使旧 challenge 失效但不清零累计失败。
-
-`/captcha/verify` 的请求以 evidence/provider 为 discriminator 使用 `oneOf`,根和每个 payload 都 `additionalProperties:false`。provider、type、scene 和 subject 以服务端 challenge 记录为真,客户端字段不能改变绑定。只有供应商 evidence 与本地风险策略共同通过才签发 opaque `validToken`;票据绑定 session、tenant、client、scene、subject、challenge、method、assurance、audience 和过期时间。`/sms/code` 在同一事务中完成 `ISSUED → CONSUMED` 与唯一短信 outbox 创建;同一幂等键返回原结果,不同键或并发重放不能产生第二条短信任务。
-
-当前后端门禁固定为:`API-AUTH-TAC-001` 补齐密码登录票据;`API-AUTH-TAC-002` 修复真实 challenge 空 500 与错误 envelope;`API-AUTH-TAC-003` 关闭验证 schema 并建立 discriminator;`API-AUTH-TAC-004` 落实 session、多方法、`required=false` 票据和原子消费。`AUTH-TAC-OPENAPI-CONTRACT BLOCKED` 解除前,`runtimeConfig.mode` 必须保持 `mock`。
-
-### 22.4 不降风控的可访问路径
-
-TianAi 指针滑块不能因外层 dialog 可聚焦就被宣称为 TalkBack 或键盘可完成;不得生成固定键盘轨迹,也不得检测辅助技术后免验证。不存在 `accessibility=true`、`skipCaptcha`、供应商故障放行或客服直接发短信等旁路。
-
-三人交叉质询后的统一 P0 是 provider-neutral 验证中心与可恢复的文字/中继 `MANUAL_REVIEW`。文字渠道只是可访问通信媒介,各 scene 仍有独立身份或号码控制证据。案件继承且不可改写原 session 的 subject/scene,具备去重、RBAC、主体/IP/设备/审核员限额、完整审计、服务时段、容量和 SLA;高风险找回或换号双人复核。坐席只提交决定,验证中心才可签票;异步案件和批准授权在合理期限内可恢复,用户重新进入原流程时才激活短时 token,避免在通知前过期,也不得要求残障证明。
-
-中国大陆非交互风控供应商只进入限时 POC;必须在真实 UniApp Android WebView 中证明 TalkBack、外接键盘、Switch Access、弱网、超时、异常/重放票据、误杀和攻击拦截指标,达标后才可成为默认自动路径,不能预先宣称符合无障碍标准。音频验证码只作为另一个 POC 候选,必须验证可懂度、听障覆盖与 ASR 对抗,不能单独上线或成为唯一替代。设备断言只有在同一 subject 的已认证会话绑定硬件保护私钥、服务端 nonce、RP/App 绑定、`userVerification=required`、短时单次、防重放并检查撤销时才可独立放行;普通设备指纹、完整性或仅 user-presence 只能作为风险信号,注册和未绑定设备不得使用。
-
-客户端现有壳层只完成 dialog 命名、说明关联、初始聚焦、Tab 圈定、Escape/Android 返回、焦点恢复、原生刷新/关闭、48px 目标和小视口滚动。最终必须在 MuMu 用 TalkBack、外接键盘与非拖动路径完成 A01/A04/A05;证据缺失时 `ANDROID-AUTH-ACCESSIBILITY-RELEASE BLOCKED` 必须保持红灯。
-
-## 二十三、领域上下文与反馈提交设计
-
-`utils/genealogy-context.js` 是当前家谱词法 ID 与失效 tombstone 的唯一持久 owner,`utils/session.js` 是账号令牌边界。只在首次且没有历史上下文或失效标记时自动选择首个可用家谱;调用方给定的新列表不再包含历史 ID,或显式目标不可用时,必须清理 ID、写入 tombstone 并让用户明确重选,后续重载不能用列表第一项继续渲染。令牌损坏、退出和账号切换都同步清理 ID 与标记;导航一次性结果不得承担领域持久化。实际后台撤权仍需 workspace 在 onShow 或失效事件中重新取得服务端列表,当前基础不能被表述为实时权限刷新已完成。
-
-M07 的唯一接口 owner 是 `appApi.submitFeedback`。请求只允许 `feedbackContent/feedbackType/contactInfo` 三个普通字符串数据字段;内容必填,类型和联系方式可选且无客户端枚举映射;请求选项不能覆盖认证要求。remote 只接受 `POST /genealogy/app/feedback` 的 HTTP 200 与整数成功 `code`,反馈响应未声明 `data` 必填且页面不消费实体;mock 必须抛 `WRITE_UNAVAILABLE`。页面提交中锁定表单并捕获规范快照;成功和 uncertain 回流都再次核对当前快照,保留回执或未知结果并阻止原样重复写,迟到输入保持为尚未提交的新内容。超时、断网、意外 2xx/3xx、HTTP 408/5xx 或响应失真进入 `uncertain`,只有确定拒绝允许重试。本地不持久保存反馈原文或哈希 tombstone;跨重启 at-most-once 必须由未来服务端幂等键或状态查询合同解决,不能以隐私数据、无期限锁或伪保证替代。
-
-### 23.1 家谱工作区只读合同
-
-家谱工作区第一批唯一选择 `GET /genealogy/app/genealogies/mine`(`appListMyGenealogies`)持有当前账号可访问集合,选择 `GET /genealogy/app/genealogies/{genealogyId}/overview`(`appGetGenealogyOverview`)持有 G05 展示;两个 operationId 全局唯一,路径只开放 GET 且无 request body,语义重复的 `GET /{genealogyId}` 不同时接入。页面不把 fixture 与远端事实混用,也不在两个详情响应之间择优补字段。
-
-线上 `AppGenealogyVo.genealogyId` 当前是 JSON `integer/int64`。最大合法 int64 经 JavaScript JSON 解析后会不可逆失真,事后 `String()` 无法恢复,因此响应身份与 overview path 都必须引用非空、1—128 位 URL-safe 词法 `GenealogyId`;仅拒绝 unsafe number 可以失败关闭,却会使 OpenAPI 合法用户永久不可用,只能用于关闭功能开关的预研,不能作为正式兼容方案。
-
-首批最小实体只消费 `genealogyId/genealogyName/canView/canManage/canEditContent/roleType`。`RListAppGenealogyVo/RAppGenealogyVo` 都是关闭额外字段且精确只有 required `code/data` 的成功 envelope,`code` 固定 200,data 分别为 `AppGenealogyVo[]` 与单个 `AppGenealogyVo`;实体上述字段进入 required,ID 与名称分别引用 `GenealogyId/GenealogyName`,三项 capability 为非 null 布尔值,`roleType` 提供至少两个稳定非空枚举供 G01 分组和标签。`AppGenealogyVo` 其他字段保持可选:地点、堂号、人数、简介等有值才展示,未知额外实体字段允许忽略。若产品坚持保留当前 fixture 的来源、管理者、认证、始祖、上级谱、支系、更新时间和激活人数,则后端必须另补合同;首批不为复刻 mock 强制 22 个字段全部必填。
-
-`canView` 是进入 `availableIds` 的授权投影,不能从 `roleType/status/memberStatus` 猜值;`/mine` 以 `x-current-account-viewable-only=true` 和 `x-revocation-policy=OMIT_ONLY_AFTER_CONFIRMED_ACCESS_LOSS` 机器声明只返回当前账号仍可查看的家谱。G01 仅在新列表成功校验后 reconcile;网络、超时、5xx 和畸形响应保留旧现场并显示错误,成功列表确认消失才写 tombstone。G05 每次加载先清空旧数据、取消迟到请求,只消费 `/overview`;对象无权、撤权与不存在统一 `NON_DISCLOSING_GENEALOGY_NOT_AVAILABLE`,能力缺失按最低权限处理,不回退本地角色。
-
-当前线上 OpenAPI 没有有效 security 声明且媒体写作 `*/*`,但无令牌实测三条读取均被拒绝、实际 Content-Type 为 JSON,因此两项是必须修复的发布文档质量问题,不单独声称已经公开泄漏。生产合同不再允许 HTTP 200 包业务错误:两条读取都 required SaToken 与 1—128 位非空 clientid,只允许 typed `application/json`;`/mine` 精确 200/401/429/500,`/overview` 精确 200/400/401/404/429/500,分别固定 `GENEALOGY_ID_INVALID/AUTH_REQUIRED/GENEALOGY_NOT_AVAILABLE/RATE_LIMITED/GENEALOGY_WORKSPACE_UNAVAILABLE`。每个响应必须包含固定单值 enum `Cache-Control: private, no-store`,429 另有 1—300 秒 Retry-After;只允许 `traceparent/tracestate/x-request-id/x-correlation-id` 四种非语义 tracing header,禁止 ETag 与其他语义 header。component parameter/response/header/schema 解析只接受 exact local `#/components//...` 引用,拒绝外部或错分区 `$ref` 冒充 owner;四种 tracing header 的 component 引用也必须 exact local,内联时只接受 allowed-key 关闭且带非 null 的 string schema 的 Header Object。clientid、成功/错误 code/data/businessCode、实体字段与 role 枚举都用 allowed-key 集拒绝 `nullable`、readOnly/writeOnly、冲突组合或其他未拥有的验证关键字。真正发布门禁还包括有效令牌下的无凭证、跨账号、撤权、删除、typed HTTP、畸形 JSON 与取消反例。
-
-`tests/genealogy-workspace-openapi-contract.ps1` 以结构化 JSON 为判断对象并先要求受保护 JSON/YAML 语义深比较通过,唯一拥有上述 path/method/operationId、SaToken/clientid、词法参数、响应身份、typed envelope、required cache headers、required 与 capability/role 边界;它全局递归扫描 APP GET 的 200 schema 闭包,除 `/overview` 外任何返回 `RAppGenealogyVo/AppGenealogyVo` 或结构等价单谱实体的旁路详情都失败,`/mine` 的数组投影不误算成单谱读取。当前旧双导出与线上文档都不能通过。G11 门禁只消费该门禁的 PASS 结论,不复制 overview 合同。门禁关闭前不建立 G01/G05 专属字段 adapter,不让客户端成为第二份猜测合同。问题固定为 `API-GENEALOGY-WORKSPACE-001` 无损身份与最小 schema 闭包、`API-GENEALOGY-WORKSPACE-002` 可访问集合与能力投影、`API-GENEALOGY-WORKSPACE-003` typed HTTP、缓存与对象级授权行为。
-
-### 23.2 M06 帮助内容只读合同
-
-M06 第一批唯一选择 `GET /genealogy/app/help-articles` 持有完整 FAQ 列表。线上 `HelpArticleVo` 已同时包含 `helpCategory/helpTitle/helpContent`,所以单页手风琴不再调用 `/{helpId}`;详情端点只保留为未来文章深链或其他 surface 的候选,不进入当前页面。这样当前页面不读取、比较、缓存、序列化或回传 `helpId`,线上 JSON `integer/int64` 虽仍是未来详情债务,却不会参与 M06 身份或行为。
-
-成功响应必须由 `RListHelpArticleVo` 唯一拥有,并把 `code/data` 设为 required;`data` 是允许为空的 `HelpArticleVo[]`。每行只要求 required、非空的 `helpCategory/helpTitle/helpContent`:分类是可直接展示的标签,正文首版明确为纯文本,数组只含当前可发布文章且顺序就是展示顺序。分类 enum、详情 ID、封面、浏览量、状态和排序字段都不由客户端消费;“全部”是唯一客户端分类值。富文本、Markdown、图片和文章详情只有在另立格式与内容安全合同时才可进入。
-
-adapter 必须使用 allowlist 投影为 `{category,title,content}`,不得 spread 原对象。每次合法响应先按原始顺序分配仅限当前 generation 的 ordinal 展示键,再进行搜索和分类;筛选后的 index 绝不能成为 key。搜索、分类、刷新或原子替换列表前清空展开项;唯一列表 controller 与 generation 共同拒绝取消后的迟到响应。重复标题或正文不会产生 key 冲突,也不能据此生成持久身份。
-
-页面状态固定为加载、正常、服务端空列表、搜索/筛选无结果、失败可重试和认证失效;失败不得回退成本地五条内容并冒充线上成功。搜索只匹配标题与纯文本正文,分类从返回标签按首次出现顺序动态去重。分类与标题使用原生按钮语义并满足至少 44dp 触控目标;分类补 `aria-pressed`,问题补 `aria-expanded/aria-controls`,加载、计数、失败和展开状态提供适当播报。最终系统字号、TalkBack、焦点和视觉只能在 MuMu 验收。
-
-当前受保护 JSON/YAML 仍把列表写成通用 `ListResult/RList`;线上虽已出现 `RListHelpArticleVo/HelpArticleVo`,两者仍无 `required`,正文格式、仅发布与排序保证也未定义。匿名实测列表、带分类列表和详情均为 HTTP 200+`{code:401,data:null}`,而线上文档声明 HTTP 401 string 且 operation 没有有效 security。后端可以选择规范 HTTP 401 或稳定业务 401,但文档、部署和 validator 必须一致。`tests/help-center-openapi-contract.ps1` 当前输出 `HELP-CENTER-OPENAPI-CONTRACT BLOCKED`;问题固定为 `API-M06-001` 专用响应与最小 required 闭包、`API-M06-002` 纯文本/发布范围/顺序语义、`API-M06-003` 认证与错误承载一致性。门禁通过前不写 live-only adapter。
-
-### 23.3 个人资料只读合同
-
-`GET /genealogy/app/auth/profile` 是 M01 身份卡、M02 表单初值和 M03 绑定手机号展示的唯一 wire owner。首批不消费 `userId/avatar/status/tenantId/userNo/sex/birthday/registerSource/loginIp/loginDate/clientKey/deviceType`;数字 ID 与状态字典因此不构成本批门禁。M01 当前显示的“创建者”是家谱级角色,不属于账号 profile,必须删除而不是向后端索要错误字段。
-
-成功响应固定为 `RAppProfileVo → AppProfileVo`,envelope 的 `code/data` required。wire 实体仅把 `phone` 设为 required,并要求 canonical `^1[3-9]\d{9}$`;`nickName/realName/email` 可选,省略是唯一“未设置”形态,出现则拒绝 null、空串和边界空白,姓名为 1—30 字符,邮箱为有效格式且 1—100 字符。把四项全部 required 会让没有实名或邮箱的合法旧账号拖垮 M01/M03;省略可选字段后由 adapter 统一为空串,不是旧字段兼容或双模型。GET 只定义读取;未来 PUT 必须另证省略字段是否保持原值并只发送 dirty fields,不能在本批预判。
-
-唯一 profile normalizer 在 mock 与 remote 中输出固定 `{maskedPhone,phoneAccessibleLabel,nickName,realName,email}`。原始手机号只在函数局部完成格式校验和掩码,页面、缓存、错误详情、日志与路由不得出现明文;可选字段只有真正缺席才规范成空串,出现但非法时整份响应失败。所有其他响应字段使用 allowlist 丢弃。`appApi.getProfile` 必须经 `resolveRuntimeMode()` 区分 mock/remote;非法配置失败关闭,remote 走严格 envelope、15 秒超时和 request controller,不以 `hasRemoteConfig() ? remote : fixture` 把错误配置伪装成本地数据。三个页面可以各自读取同一 adapter,但不建立跨会话缓存。
-
-M01 在 `onShow` 刷新并以 controller+generation 拒绝迟到结果;资料 loading/error 只替换身份卡,服务菜单和底栏不因普通读取失败而消失。旧 `query.state=error` 与“重新查看即 ready”是假状态,接线时删除;通知未读数在通知域接通前不得与真实 profile 混装为线上事实。M02 首次加载成功后再填充三个字段并重设 baseline,加载不能制造脏表单;普通 GET 失败可重试,编辑期间不后台刷新覆盖输入,保存仍明确是本地校验,不能冒充 PUT。M03 只让手机号行局部加载/失败,密码入口不依赖 profile;M05 的当前手机号展示在真正 remote 前也必须消费同一掩码 owner 或隐藏,不能保留 fixture。
-
-账号失效交给会话 owner,普通 network/timeout/5xx/畸形响应只产生可重试读取失败,没有写请求的 uncertain 状态。实施测试必须证明 optional 缺席、出现非法值、明文不泄漏、超大 `userId/avatar` 丢弃、错误配置、取消、迟到回调、M01/M03 局部失败和 M02 baseline。交互同时改为原生按钮,补加载播报、M02 字段错误关联与聚焦、44dp 目标、长昵称换行和装饰图隐藏;最终系统字号、TalkBack、纹理对比和返回流程仍只由 MuMu 验收。
-
-当前受保护双导出仍引用通用 `ObjectResult/RObject`;线上 `RAppProfileVo/AppProfileVo` 没有 required、phone pattern 或姓名/邮箱边界,GET operation 也缺有效 security/clientid。匿名真实响应是 HTTP 200+业务 `code=401`,文档却列 HTTP 401 string。`tests/profile-openapi-contract.ps1` 当前输出 `PROFILE-OPENAPI-CONTRACT BLOCKED`;问题固定为 `API-PROFILE-READ-001` 专用响应与最小字段闭包、`API-PROFILE-READ-002` 可选字段与隐私投影、`API-PROFILE-READ-003` 认证/媒体/错误一致性。门禁通过前不写 live-only adapter。
-
-### 23.4 通知读取与已读状态合同
-
-通知必须分成读取批次和写入批次,不能为了让页面看起来完整而在同一个本地 clone 中伪造读写闭环。读取只由不带 `readStatus` 筛选的 `GET /genealogy/app/notifications` 与 `GET /genealogy/app/notifications/unread-count` 持有;前者返回当前账号完整活动通知集合,集合最多 200 条、按最新优先,后者精确统计同一集合中 `readStatus=UNREAD` 的条目。两个独立请求之间若有新消息或多端读状态变化,短暂不相等是合法并发结果,页面分别展示成功响应并在下一次刷新收敛。
-
-读取成功的最小 wire 形状为 `RListNotificationVo → NotificationVo[]` 与 `RNotificationUnreadCount → int32`。两层 `code/data` required;计数范围为 0—200。通知首批只 required `noticeTitle/noticeContent/publishTime/readStatus`:标题 1—50,正文 1—1000、完整且为 plain text,时间为带时区的 RFC3339,状态精确枚举 `READ/UNREAD`。客户端不解释 HTML、Markdown、服务端 URL 或 `bizType`,也不从标题、类型或摘要猜业务目标。N01 只将摘要显示限制在最多 160 个 Unicode 字素,N02 必须持有同一响应中的未截断正文。
-
-读取 adapter 首版公开模型固定为 `{snapshotKey,title,content,publishedAt,unread}`。`snapshotKey` 使用成功响应 generation 与映射前 ordinal 组成的词法 key;裸 ordinal、数组筛选后 index、服务端 int64 ID 和内容哈希都不能成为页面身份。唯一内存快照不可变且不落盘;成功刷新原子替换 generation,退出或账号切换立即清空。N02 在进入时解析并持有该 generation 的完整条目,应用重启、旧 generation、直接构造或未知 key 统一显示“请返回消息中心重新打开”,不能虚构“服务端已删除/已撤回”。
-
-读取批次显式丢弃 `notificationId/genealogyId/senderUserId/senderPhone/bizId/bizType/noticeType` 等服务端字段;N01 的通用审核 CTA、空态 G10 按钮和 N02 目标按钮一并删除。只有后端以后提供闭合的 `bizType → route key+必填词法参数+权限/失效语义` 字典,并为每种目标给出越权、删除和跨谱反例,才能另立目标分流批次;任何原始 URL 都不得执行。M01 与 G01 共同消费未读数 owner,文案只称“未读消息”,可见数大于 99 时显示 `99+`,可访问名称仍包含真实数量;加载或错误只影响各自消息入口,不锁死根页其他功能。
-
-写入批次由 `POST /genealogy/app/notifications/{notificationId}/read` 与 `POST /genealogy/app/notifications/read-all` 唯一持有。此时唯一 notification controller 可以从同一个严格列表响应私有保留 `notificationId`,但页面模型、路由、日志和持久缓存仍只见 `snapshotKey`;ID 必须在列表实体与 path 中同为 1—128 位 URL-safe opaque string,禁止 int64 经 JavaScript 解析后再转字符串。该迁移必须原子删除首版“完全丢弃 ID”的内部实现和 N01/N02/M01/G01 所有 fixture 计数与本地 clone 写入口,不保留双 owner。
-
-单条已读和全部已读对当前账号必须幂等,重复调用成功且无重复副作用。认证失效返回稳定 401;不存在与跨账号单条 ID 统一为 404 `NOTIFICATION_NOT_AVAILABLE`,避免泄露实体存在性。read-all 的截止点是服务端接收该请求时当前账号已经存在的活动通知,截止点之后并发到达的消息保持未读;成功后客户端重取列表和未读数,不用本地递减猜结果。超时、断网、HTTP 408/5xx 或畸形响应属于结果未知,依靠幂等重试或重新读取收敛;明确 4xx 才是确定拒绝。
-
-当前受保护双导出把列表返回写成通用 `ListResult/RList`,完全缺少 unread-count 路径与专用通知模型;线上虽出现专用 VO 和四条操作,但 wrapper/VO 无 required,`readStatus` 无枚举、内容无长度/纯文本/完整性、列表无容量和顺序,ID 仍是 int64,operation 也缺有效 security/clientid。匿名 list/count 实测均为 HTTP 200+业务 `code=401`,与文档 HTTP 401 string 冲突。`tests/notification-read-openapi-contract.ps1` 和 `tests/notification-read-state-openapi-contract.ps1` 当前分别输出 `NOTIFICATION-READ-OPENAPI-CONTRACT BLOCKED` 与 `NOTIFICATION-READ-STATE-OPENAPI-CONTRACT BLOCKED`;问题固定为 `API-NOTIFICATION-READ-001`—`003` 和 `API-NOTIFICATION-STATE-001`—`003`。双门禁通过前不写 live-only adapter,也不把本地已读行为称为成功。
-
-### 23.5 M02 个人资料写入合同
-
-M02 继续只使用 `PUT /genealogy/app/auth/profile`,不同时发布 PATCH 或第二写入口。由于页面只拥有 `nickName/realName/email`,PUT 必须在 operation 与专用 `AppProfileMergeUpdateBody` 中明确是原子 dirty-only merge,而不是整个 profile replacement:只允许出现 1—3 个真正改变的可编辑字段,出现字段更新、省略字段保持,额外字段关闭;同一 payload 重复设置相同值不能产生重复通知或其他业务副作用。后端若无法证明 presence-aware merge,就必须先替换现有操作,客户端不能从“字段 optional”推断安全。
-
-`nickName` 出现时必须是去边界空白的 1—30 字符,空串和 null 均非法;这允许没有昵称的旧账号只修改其他字段,但不允许把已有昵称删除。`realName/email` 的精确空串只在 request command 中表示清空,省略仍表示保持;非空值分别满足 1—30 和 email 格式/1—100。null、纯空白、边界空白都非法,服务端不以隐式 trim 把空白偷偷解释成 clear。GET 和成功响应中,清空后的可选字段继续以属性省略表达,不能把请求命令形状泄漏回读取模型。
-
-并发只使用一个 opaque `profileVersion` owner。`AppProfileVo.profileVersion` required,值为 1—128 位 URL-safe string;PUT required `If-Match` 携带同一 token,请求 body 不重复版本。后端以当前 principal+tenant+version 原子 compare-and-set,成功 200 返回完整 canonical `RAppProfileVo` 与新版本;旧版本返回 409,唯一稳定码固定为 `PROFILE_VERSION_CHANGED`。本项目 T01 已使用 body version+If-Match+409 模式,资料写入沿用同一并发语义;H5 CORS 必须允许 `If-Match`。
-
-客户端先依赖 23.3 的 GET 取得 canonical 初值和版本,完成异步回填后建立 baseline。`normalizeProfileUpdate` 只从普通自有数据属性提取脏字段,禁止 getter、symbol、prototype、avatar/sex/birthday 和额外属性;clean 不发请求。提交开始时冻结三个输入并捕获规范快照、版本与 session generation;成功只接受严格 HTTP 200 typed envelope,以返回模型原子回填表单和 baseline。确定的 400/401/409/422 保留草稿并进入对应状态,409 不静默覆盖。
-
-超时、断网、408/5xx、取消或畸形成功响应都是 outcome unknown。客户端不得自动重复 PUT,而先重新 GET:若本次所有脏字段均等于提交值,视为已提交;仍等于旧 baseline 才可由用户重试;出现第三值或版本无法归因则进入 conflict,并保留当前草稿供用户明确选择重新载入或基于最新值继续。页面卸载、退出和账号切换中止等待并清空未持久草稿;RequestTask 取消不证明服务端没有落库,旧 session generation 的迟到响应永远不能污染新账号。
-
-M02 当前把 `currentUser.name` 同时填入昵称和真实姓名,是必须删除的 PII 伪造;500ms 定时器只形成本地预览,不是接口状态。真正实施时状态至少包括 loading、ready/dirty、saving、success、error、uncertain、conflict、auth-expired;保存期间锁定输入和返回,成功重置 dirty,失败保留草稿。头像假按钮、相册权限和 int64 avatar 不混入本批;“邮箱用于接收通知”在验证/送达合同缺失时删除。原生输入和按钮补齐 `aria-invalid/aria-describedby`、错误关联、首错聚焦、busy/status 播报、email 键盘类型与 44dp 目标,最终只由 MuMu 验收。
-
-受保护双导出仍使用旧 `ProfileUpdateBody`,缺 realName/email,示例还出现 schema 外 `regionCode/addressDetail`,成功为 generic `RObject`。线上改为 `AppProfileUpdateBody → RAppProfileVo`,但 body 无 required/minProperties/关闭额外字段/merge/version,响应无 required,operation 无 security/clientid,媒体还是 `*/*` 且只列 200/401。`tests/profile-update-openapi-contract.ps1` 当前输出 `PROFILE-UPDATE-OPENAPI-CONTRACT BLOCKED`;问题固定为 `API-PROFILE-UPDATE-001` 唯一 merge owner 与字段命令、`002` 版本并发和 409、`003` typed 响应/认证/错误/CORS、`004` 超时对账与账号隔离。读取和写入门禁都通过前不接 M02 真实保存。
-
-### 23.6 M10 当前设备退出合同
-
-`DELETE /genealogy/app/auth/logout` 唯一语义是撤销 Authorization bearer 所属的当前设备 credential family,包括同一登录会话的 refresh 能力(如果未来存在);同账号其他设备保持有效。“退出全部设备”必须是另一条接口、另一层确认和另一份权限合同。200 只在撤销已经传播到所有鉴权节点、旧 access token 不能再访问任何受保护接口且旧 refresh 不能换取新 token 时返回;已经在鉴权前通过的并发业务请求无法回滚,产品文案不得承诺取消所有进行中操作。
-
-DELETE 没有 body,required SaToken 和与 token client 绑定的非空 clientid。为形成唯一幂等成功出口,凡能验证为该 client 历史签发的 active、revoked 或 expired credential,重复调用都返回相同的 HTTP 200 `RVoid`,不产生额外副作用;伪造、格式非法和 client 不匹配才返回 401 `RLogoutRejected`,稳定码只允许 `TOKEN_INVALID/TOKEN_CLIENT_MISMATCH`,它们不是撤销成功。200/401 均为 application/json 且 `Cache-Control: private, no-store`,RVoid 的 integer code required,同时声明 400/429/500。
-
-客户端唯一 owner 是服务级 `logoutCoordinator`,而不是 M10、A01 和 session 各存一份。一次同步临界段按顺序:捕获 A 的 token/clientid 和当前 session epoch;通过 session owner 立即 bump epoch 并且只清一次 token、家谱上下文与所有已登记账号缓存;使用显式 A 快照创建不绑定页面 controller 的 DELETE RequestTask;发布非敏感 attempt 并立即 `goRoot(A01)`。该同步段没有 await,创建请求同步失败也不恢复 token。M10 页面永远拿不到 token,请求不会因 M10 卸载或 reLaunch 主动 abort。
-
-异步 callback、catch 和 finally 只能按 attemptId 更新 coordinator,绝不能再次 `session.clear()`;否则 A 的迟到响应会抹掉随后登录的 B。coordinator 的公开内存态固定为 `{attemptId,logoutEpoch,status}`,status 为 `pending/confirmed/unconfirmed/not-revoked`,不含 token、header、响应 payload 或服务端消息。最多允许用同一 A 快照做一次同进程短时有界重试;不写 storage、日志或持久队列,也不从 session 重新取 token。
-
-A01 仅在 session 仍为空、epoch 与 logoutEpoch 相等时订阅并原子消费一次状态;B 登录或 epoch 改变后丢弃 A 的迟到提示。进程被杀允许丢失提示,但本地退出已经持久完成。唯一主句始终是“已从本机退出”:pending 补“正在结束服务器会话”,严格 200 为 confirmed;network/timeout/408/429/5xx、畸形响应或 generic 401 为 unconfirmed;typed 401/400/403 为 not-revoked。所有分支都留在 A01、不恢复 token、不返回 M10、不阻塞重新登录;状态必须可播报且不能只靠短 toast 或颜色。
-
-M10 确认前的取消和 Android 返回只关闭确认层,零请求、零清理;确认后立刻退出可关闭弹层态并防双击,根导航失败时显示“本机已退出”遮罩且禁止返回受保护页面。当前文案“本机保存的密码不会被保留”没有任何密码存储 owner 证据,实施时改为“仅退出此设备,其他设备不受影响”。Mock 或错误 runtime config 也必须完成本机退出,并准确标记远端未确认,不能为了发请求把用户困在本地会话。
-
-当前 M10 只做 `session.clear → close → goRoot(A01)`,本机边界正确但没有远端撤销、重复保护、epoch 或跨根提示;旧静态测试也锁定这条本地序列。受保护双导出有 DELETE、SaToken、clientid 和 200 `RVoid`,但缺范围、幂等、required 和错误;线上只有 200/401 `*/*`,又缺 operation security/clientid。`tests/logout-openapi-contract.ps1` 当前输出 `LOGOUT-OPENAPI-CONTRACT BLOCKED`;问题固定为 `API-LOGOUT-001` 当前凭证族与撤销传播、`API-LOGOUT-002` 幂等成功/拒绝模型、`API-LOGOUT-003` 安全/媒体/no-store/部署反例。门禁通过前不新增 logout API 代码,也不把本机退出写成服务端注销成功。
-
-### 23.7 M04 登录态改密与统一密码凭证合同
-
-当前本地双导出要求 `oldPassword/newPassword` 为 32 个十六进制字符的 MD5,线上 `AppPasswordChangeBody` 也只把它放宽为大小写十六进制;登录、注册和找回同样接受静态摘要。该摘要不是一次性 proof,而是后端登录入口直接接受的密码等价物,一旦从日志、代理、调试记录或终端泄漏即可重放;同时服务端看不到原始长度与 blocklist 命中,无法成为生产策略 owner。新合同不得长期双读 raw/MD5,也不得只改 M04 留下其他入口。A01 登录、A04 注册、A05 找回和 M04 改密必须同一批删除全部 MD5 wire fallback;只在认证 HTTPS 通道提交 raw `writeOnly` 密码,服务端使用独立盐与 Argon2id,无法使用时才采用合规 scrypt/PBKDF2。
-
-密码 schema 只有两个 owner:`CurrentPasswordSecret` 原样、不 trim,允许 1—64 Unicode code point 以兼容已有账号;`NewPasswordSecret` 在明确 NFC 规则后为 15—64 Unicode code point,允许空格、Unicode、粘贴和密码管理器,不设置字母/数字/符号组成规则。注册、找回与改密新值共用后者;登录与改密当前值共用前者。服务端在写入前执行常见/泄露密码 blocklist、账号级限速、当前密码重新认证和新旧不同;客户端只镜像即时提示,不能成为可绕过的权威。TAC 是反机器人证据,不代替当前密码;用户要求的登录/注册/找回 TAC 继续由认证合同持有,正常 M04 不另建一套 TAC。
-
-M04 的唯一会话方案是 ALL,而不是返回并安装新 token,也不是保留旧 bearer。严格 HTTP 200 `RVoid` 只能在新 verifier 已持久化、账号 `credentialEpoch` 已原子递增,并且包括请求者在内的所有设备、所有 client 的既有 access/refresh/renewal 会话已跨鉴权节点失效后返回。方案 B 会要求 typed 新 token 和响应丢失恢复协议,当前 RVoid 无法承载;方案 C 会让可能被盗的旧 token 在改密后继续有效,均被否决。两个使用同一旧密码的并发请求必须通过服务端 CAS 至多一笔成功,另一笔返回 typed 409 `CREDENTIAL_VERSION_CONFLICT`。
-
-PUT required SaToken、非空 clientid、`application/json` 和关闭额外字段的 `PasswordChangeBody`;body 只含 oldPassword/newPassword,confirm 永不出端。200/400/401/409/422/429/500 都必须是 JSON 且 `Cache-Control: private, no-store`,429 带 `Retry-After`。409/422 的 `RPasswordChangeRejected.businessCode` 只允许 `CREDENTIAL_VERSION_CONFLICT/CURRENT_PASSWORD_INCORRECT/NEW_PASSWORD_SAME_AS_CURRENT/PASSWORD_POLICY_VIOLATION`;服务端和网关日志、APM、分析、崩溃记录及错误消息不得含密码、摘要或请求体。
-
-客户端在 dispatch 前由 session owner 持久化唯一非敏感 marker `{sessionEpoch,startedAt}`,不保存 token、密码、摘要、body、重试键或 operation id。明确未写的 400/422/429 原子清 marker 并留页;严格 200、401、409 均清同 epoch 全部账号态并回 A01。network、timeout、取消、畸形 2xx 或 5xx 在发出后属于结果未知,同样清秘密与本机会话、回 A01 并只提示“请尝试使用新密码重新登录”,绝不自动重试或宣称失败。冷启动发现同 epoch marker 时,在任何受保护缓存渲染前先清会话;新登录 bump epoch,旧 marker 和 A 的迟到响应不得清掉 B。无需新增 operation-status,重新登录就是最小对账路径。
-
-页面实施时状态至少是 ready/submitting/known-error/unknown/success:提交中冻结三个输入、显隐控制、按钮和返回;确定字段错误聚焦并关联 `aria-invalid/aria-describedby`,显隐改为可键盘操作的原生按钮与 `aria-pressed`,目标至少 44dp,持续状态可播报。成功与 unknown 的跨根提示不能只靠短 toast。M03“建议定期更新”改为风险触发建议;M04 允许自动填充、粘贴和密码管理器。`tests/password-change-openapi-contract.ps1` 当前输出 `PASSWORD-CHANGE-OPENAPI-CONTRACT BLOCKED`;`API-PASSWORD-001`—`005`、密码登录 TAC、双设备/并发/故障注入和 MuMu 原生矩阵通过前,不修改 M04 的诚实本地预览。
-
-### 23.8 M05 手机号换绑与统一短信码合同
-
-M05 当前只展示脱敏 fixture,以 500ms 定时器验证新手机号和 4 位验证码并明确“不提交服务器”;没有当前密码、TAC、远端请求、会话迁移或结果未知状态。受保护双导出的 PUT body 是 `clientId/phone/smsCode`,线上则只有 `phone/smsCode` 并返回完整 profile;两者都缺 existing-factor 再认证、号码唯一性、会话撤销和 typed 错误。共享发码接口在线上还明确忽略权限。活动 bearer 加攻击者控制的新号验证码因此足以构成账号接管,不能接线。
-
-三人比较了“共享发码 operation 按 scene 条件鉴权”和“专用受保护 operation”。标准 OpenAPI 3.x 无法把 operation-level security 与 body 中的 `sceneCode` 条件绑定;`security: [{}, {SaToken: []}]`、文字说明或 vendor extension 都不能让通用 validator、网关和 SDK 自动拒绝匿名 `APP_PHONE_CHANGE`,会产生 validator 允许而 runtime 拒绝的双合同。唯一方案是 `POST /genealogy/app/auth/phone/sms/code`:required SaToken 与非空 clientid,闭合 body 只有 `phone/validToken`,scene 在服务端固定,公共 `/auth/sms/code` 的 enum 删除 `APP_PHONE_CHANGE`。两个 operation 只分协议边界,底层仍调用同一 OTP 生成、存储和限流 owner,不复制策略。
-
-最终 PUT 的身份闭环是活动 session+raw `currentPassword`+新号 OTP。TAC 只防自动化,不能替代既有因子;新号 OTP 只证明新号码控制权。不强制旧号 OTP,因为旧号丢失是正常换绑原因且不会增加独立因子;成功事务改为持久化旧号安全通知 outbox。所有账号若不保证有密码,稳定返回 `STEP_UP_UNAVAILABLE` 并进入独立找回,M05 不得降级为 bearer+新号 OTP。最终 body 精确为 `currentPassword/phone/smsCode`,不含 currentPhone、clientId、validToken、challengeId 或供应商字段;它依赖 M04 先完成 raw-password/慢哈希迁移,当前 MD5 wire 不得复用。
-
-短信码唯一 schema owner 是 `SmsCodeSecret`:CSPRNG 生成恰好 6 位 ASCII 十进制字符串,保留前导零,TTL 5 分钟,60 秒重发冷却,最多 5 次失败,单次消费;重发原子废止旧码且不重置累计失败计数。同一 `(account,session/credentialEpoch,tenant,client,scene,newPhone)` 只有一个 active generation,服务端内部 generation 足以消歧,因此最终 PUT 不新增 challengeId/attemptId。A01/A04/A05/M05、注销等活动消费者、短信模板、生成器、OpenAPI、validator、页面和测试必须同版本从 4 位原子迁移为 6 位,禁止兼容双长度。
-
-服务端在同一事务内验证当前密码与 active OTP、执行 `(tenant,canonicalPhone)` 唯一约束、消费 OTP、更新手机号、递增 credentialEpoch、撤销包括当前在内的全部 access/refresh session,并持久化旧号通知 outbox;严格 200 只返回 `RVoid`。两个并发换绑至多一笔成功,另一笔按 credential CAS 无写入。发码 POST 的结果未知不清登录态,但按服务端冷却避免立即轰炸;最终 PUT dispatch 前复用无秘密 `{sessionEpoch,startedAt}` credential marker,200、401、409、network/timeout/5xx/畸形响应或进程终止均清同 epoch 本机会话回 A01且不自动重试。
-
-M05 页面实施时状态至少为 ready/tac/sending/code-sent/submitting/known-error/unknown:新号变化作废 TAC 与 OTP,发码后锁定号码,提交中冻结全部字段和返回。当前密码支持粘贴、密码管理器和带 `aria-pressed` 的显隐按钮;手机号与 OTP 使用能保留前导零的文本/电话输入和 numeric inputmode,错误具备 `aria-invalid/aria-describedby` 与首错聚焦,发送按钮为至少 44dp 的原生按钮,倒计时和持续状态可播报但不每秒打断 TalkBack。`tests/phone-change-openapi-contract.ps1` 当前输出 `PHONE-CHANGE-OPENAPI-CONTRACT BLOCKED`;`API-PHONE-001`—`005`、M04/认证前置门禁、两设备/OTP/故障注入和 MuMu 矩阵完成前不修改诚实预览。
-
-### 23.9 G03 家谱与始祖原子创建合同
-
-G03 当前在一个页面实例中先收集家谱资料,再录入始祖,两个 320ms 定时器只生成 `local-created-*` 预览;没有真实 API、可信 `regionCode`、上下文安装或 G01/G05 远端回流。受保护双导出的 `GenealogyCreateBody` 和线上 `AppGenealogyCreateBody` 都只创建家谱;通用 `/lineage/persons` 又允许客户端提交代数、父母和账号字段。若按旧接口先建谱再建根,会制造非产品需求的 `ROOT_REQUIRED` 半成品及两次结果未知。三人先讨论了两写恢复,再反向检查是否存在跨库或“保存空谱”的硬约束;当前没有任何证据,因此一致选择原子 bootstrap。只有后端以后证明事务边界不可跨越时才重新立 saga,而不是把补偿复杂度预埋客户端。
-
-唯一写 owner 仍是 `POST /genealogy/app/genealogies`,但旧 `GenealogyCreateBody/AppGenealogyCreateBody` 必须被 `AppGenealogyBootstrapBody` 原子替换,不保留双收。根对象关闭额外字段,只允许 `genealogyName/surname/ancestralHall/regionCode/accessPreset/rootPerson`,前五项除堂号外均必填;`rootPerson` 关闭额外字段,只允许 `name/sex/birthDate/biography` 且 name/sex 必填。服务端固定根人物 `generation=1` 和唯一首根,不接收 `generationName/personNo/appUserId/fatherId/motherId/status`;`sex` 只允许 `MALE/FEMALE/UNKNOWN`,页面默认 UNKNOWN;生日是本地日 `format: date`,不保留页面武断的 1800 年下限。文本按 Unicode code point、NFC 和无边界空白统一验证,长度沿用页面现有 4/24/12/20/200 上限。
-
-严格 200 前必须在一个事务内完成配额竞争检查、家谱、OWNER 成员关系、唯一一世始祖、READY 状态和幂等成功回执;任一步失败全部回滚,通用人物 POST 只服务 READY 家谱中的普通人物,不能承担 bootstrap。数据库 `bootstrap-root` 标记是根身份唯一权威,不能从 generation=1 猜测:普通人物 POST 即使提交一世也不能新建/替换根;人物 PUT 对根的可编辑白名单精确且只有 `name/sex/birthDate/biography`,operation 以 `x-bootstrap-root-editable-fields` 登记这四项并以 `x-bootstrap-root-noneditable-policy=REJECT_422_BOOTSTRAP_ROOT_IMMUTABLE` 登记拒绝策略;任何 status/personStatus、账号绑定、世代、父母、根标记或其他字段即使出现在通用 body 中也必须以 typed 422 拒绝,不能用“值未变化”掩盖越权字段。人物 DELETE 不能删除根,parents mutation 不能给根新增或重挂父母。未 READY 固定 typed 409 `GENEALOGY_NOT_READY`,触碰白名单外根字段或根身份固定 typed 422 `BOOTSTRAP_ROOT_IMMUTABLE`。成功 `GenealogyBootstrapResult` 必填词法字符串 `genealogyId/rootPersonId`、`setupState=READY`、`roleType=OWNER` 和 `canView=true`;两个 ID 从 JSON 到 storage、context 和 URL 都不得经过 JavaScript Number。同姓、同名和同地区均合法,页面重复提醒只能是建议,后端不得把名称当唯一键。
-
-访问规则的唯一 wire owner 是共享 `GenealogyAccessPreset`,枚举只有 `MEMBER_ONLY/PUBLIC_APPLY`。这不是 G03 私有别名:同一后端版本必须让 APP 家谱读取 `AppGenealogyVo`、bootstrap 创建和 G11 设置更新都引用它,并删除 `visibility/joinMode`、旧 create/update DTO 和 `utils/genealogy-contracts.js` 的远端数字映射;客户端不得长期同时接受新 enum 与旧 pair。设置请求同步收紧为闭合、至少一个脏字段的 `AppGenealogySettingsUpdateBody`,只含 `genealogyName/intro/accessPreset`。本任务只统一 G11 的字段合同,不代表设置写入已经可上线;G11 的 `If-Match`、版本/CAS、权限刷新和结果未知仍须在独立批次建立门禁。在后端合同尚未落地的当前本地预览阶段,现有 fixture 映射暂不改写,也不能冒充生产 wire。
-
-所在地只能从 required SaToken、非空 clientid 的 `GET /genealogy/app/region/search` typed `RegionSelectVo` 选择;同版删除旧公共 `/genealogy/region/search`,不能让 APP 在两条 owner 间漂移。`regionCode/label/selectable` 必填,code 使用共享词法 `GenealogyRegionCode`;`leaf` 只表示树导航,不能被客户端猜成“可提交”。页面展示 label、只提交 code,最终 POST 在业务事务中再次验证仍可选;不强制县、乡或 leaf,避免无依据排除省市级、历史地域或要求过细隐私位置。搜索加载、无结果、失败、迟到响应和失效选项分别表达,自由文本不得反推 code。
-
-POST required SaToken、非空 clientid 和 `Idempotency-Key`。`GenealogyBootstrapOperationKey` 精确为 `gcb.{13位毫秒时间}.{22—43位 base64url 随机量}`,随机量必须来自至少 128 位 CSPRNG;`issuedAt` 从 key 提取,`acceptUntil=issuedAt+10 分钟`,一律以服务端时间判定,issuedAt 晚于 serverNow 5 分钟以上固定 400 `OPERATION_KEY_INVALID`。schema 同时用 `x-issued-at-source=KEY_EPOCH_MILLISECONDS`、`x-accept-window-seconds=600`、`x-max-future-skew-seconds=300` 机器锁定公式。仍在窗口内的首次请求先用短控制事务按 `(account,tenant,client,path,key)` 唯一 CAS 认领 `PENDING`、canonical digest、fencing lease 和 `resolveBy`;`resolveBy<=claimedAt+2 分钟`,并以 `x-resolve-from=CLAIMED_AT/x-resolve-sla-seconds=120` 锁定。相同作用域、key 与 canonical body 的已存在操作即使超过 acceptUntil 也可重放同一结果,不同 digest 固定 409 `IDEMPOTENCY_KEY_REUSED`;截止后仍不存在的 key 固定 409 `OPERATION_KEY_EXPIRED`,不得启动工作。
-
-控制事务认领后,业务事务才原子执行配额竞争检查、家谱、OWNER、唯一一世始祖、READY 和 `SUCCEEDED` 回执;任一写点失败全部回滚,再以 fencing token CAS 成不可变 `FAILED_NO_COMMIT`。超出 lease/resolveBy 的 watchdog 也只能用同一 CAS 终结,旧 worker 失去 fencing 后不得提交,保证 PENDING 最迟 2 分钟内收敛。严格 200 只表示业务事务与成功回执均已提交;SUCCEEDED 防重记录至少覆盖实体生命周期,FAILED_NO_COMMIT 记录至少保留 30 天。
-
-为避免把始祖姓名、生日和生平写入 UniApp 普通持久存储,崩溃恢复选择受鉴权 `GET /genealogy/app/genealogy-bootstrap-operations/{operationKey}`,不持久化完整 body。状态响应必须用带显式 mapping 的 discriminator `oneOf` 精确区分 `PENDING{resolveBy,retryAfterSeconds}`、`SUCCEEDED{result}`、`FAILED_NO_COMMIT`,三个 status 均是单值 string;PENDING 的 `retryAfterSeconds` 为 1—30,避免给所有 200 错加 Retry-After。`x-state-transitions` 只登记 `ABSENT→PENDING` 与 `PENDING→SUCCEEDED/FAILED_NO_COMMIT`,两个终态无出边,`x-terminal-immutable=true`;FAILED schema 同时固定 `x-domain-effects=NONE` 与 `x-quota-consumed=false`,机器保证家谱、OWNER、始祖和配额均未提交。SUCCEEDED 返回与 POST 相同严格回执。GET 只允许 operationKey path 与 clientid header、不得有 request body,是纯读且绝不创建墓碑或推进状态:acceptUntil 前无记录返回 typed 404 `BOOTSTRAP_OPERATION_NOT_AVAILABLE`,同时返回服务端 acceptUntil 与 Retry-After;截止后无记录则按 key 时间可计算地返回 FAILED_NO_COMMIT 而不写库,迟到 POST 仍永久拒绝。跨 account、tenant 或 client 查询统一 404且不泄漏存在性,禁止额外 403 分叉。操作记录不进 `/mine`、不占业务配额,也不返回请求 body 或人物 PII;GET 零写入和 FAILED 零领域提交最终仍须数据库观测测试证明,OpenAPI 描述与扩展不能冒充实现证据。
-
-客户端唯一 coordinator 在最终按钮校验全部字段后才冻结 canonical snapshot、生成 key,并在 dispatch 前持久化 `{sessionEpoch,operationKey,startedAt}`;第一步 CTA 只写“下一步:录入首代”,绝不发网络请求。客户端本地校验失败不写 marker;请求对象创建失败且能证明零发出时清 marker。服务端在 claim 前返回的 400/401/403 均保证无 operation,清 marker,其中 401 还必须清会话并回登录,403 失败关闭。409 `IDEMPOTENCY_KEY_REUSED` 视为合同/篡改冲突,marker 转入 fatal/quarantined,不查询或安装该 key 的 status、不自动换 key;只有用户看到明确警告并显式放弃后才清 marker、重新开始。创建上限、过期 key 和 422 是确定未提交,可清 marker后修正。429 保持 marker、同 key/body,先查 status 再按 Retry-After 重试;500、网络、超时、408、发出后的取消、任意意外 2xx/3xx、畸形 200 或进程终止均是 unknown,保持 marker并查 status,绝不换 key。status 的截止前 404 保持 key,400 表示本地 marker 已损坏并安全清除,401 执行会话失效,429/500、网络、取消、意外状态和畸形 200 均保持并退避;只有 FAILED_NO_COMMIT 或可证明未认领的确定失败才清 marker。
-
-当前进程 unknown 可用相同 key 与内存 snapshot 重放;进程重启只查状态,不从 `/mine` 按名字猜测,也不自动生成新 key。SUCCEEDED 的唯一次序固定为:持久化 committed receipt → 失效或定点更新 `/mine` 缓存 → 安装 genealogy context → 进入 G05;context 或导航失败只重试本地安装/导航,绝不重发创建。退出、换账号和 epoch 变化必须隔离旧操作;任何日志、路由、marker、遥测和崩溃记录都不得包含表单正文。
-
-页面实施必须同步删除伪提交 owner 与 mock fixture mutation,覆盖地区加载、确定拒绝、fatal/quarantined、PENDING、结果未知、已提交待进入、上下文失败和导航失败。文本标签与 input 建立关系;访问预设使用真正 radio/`aria-checked`;按钮至少 44dp,提交中冻结字段和返回;错误具备 `aria-invalid/aria-describedby`、首错聚焦和持续状态播报;重复提醒与成功/放弃层复用具备焦点圈定和恢复的 `AppDialog`。当前源码仍有 clickable view、54rpx 目标、23rpx 选项、无关联错误和 UTC 日期上限,这些只登记为实施项;没有 MuMu 证据前不得宣称视觉或 TalkBack 上线。后端门禁先执行无第三方依赖的 `tests/openapi-yaml-json-parity-runtime-smoke.js`,以无损任意精度数字、严格 YAML mapping 分隔符和完整对象结构深比较 JSON/YAML,确保不安全整数差一也不能假绿,再由 `tests/g03-bootstrap-openapi-contract.ps1` 检查唯一 JSON 语义、组合 schema 内旧字段、同 scope 参数重复、根 PUT 精确白名单和结构化不可变终态;客户端门禁 `tests/g03-bootstrap-client-release-gate.ps1` 实际执行依赖注入的 marker/status 状态机测试,不再用 helper 名称顺序冒充行为证据。两项只是 G03 自身门禁;真实开放还必须同时通过家谱工作区读取门禁、聚焦测试全量回归与 MuMu 原生交互/无障碍验收,任一红灯都不得开放真实创建。
-
-### 23.10 G06/G08/G09/G10 普通加入申请合同
-
-普通申请与邀请码直入是两个独立业务合同。任务 36 只覆盖七个 APP operation:`appSearchPublicGenealogies`、`appCreateGenealogyJoinApplication`、`appGetGenealogyJoinApplicationRequest`、`appListMyGenealogyJoinApplications`、`appWithdrawGenealogyJoinApplication`、`appListPendingGenealogyJoinApplications`、`appReviewGenealogyJoinApplication`。邀请码成功后直接建立成员关系且不生成审核记录,后续必须使用独立票据和直接加入接口;G08 的 `source=invite` 不得调用本批普通申请 POST。
-
-`API-JOIN-001` 固定三个专用 cursor page 和词法身份。搜索、mine、pending 都使用 `limit=1..50`、opaque cursor、无 `total`;cursor 绑定 tenant/account/client 与过滤条件。搜索按 `updatedAt DESC, genealogyId DESC`,mine/pending 按 `submittedAt DESC, applyId DESC`,不得跨投影复用不存在的排序字段。`GenealogyId/JoinApplicationId` 均为 1—128 位 URL-safe 词法字符串,禁止 JSON int64。搜索项只含识别家谱所需的谱名、姓氏、地区、可选堂号/上级谱/支系/认证标签/成员数/更新时间与单一 `viewerState`;不同时返回可冲突的 `canApply`。mine 用 discriminator 精确区分 `PENDING/APPROVED/REJECTED/WITHDRAWN`,只有 REJECTED 必填申请人可见 `rejectionReason`;pending 只含 `applyId/applicantName/relationDesc/applyReason?/submittedAt`,递归禁止 phone、用户、邀请人和审核人身份。
-
-`API-JOIN-002` 固定闭合申请体 `applicantName/relationDesc/applyReason?`,前两项必填,长度依次为 1—50、1—100、1—500。`JOIN_APPLICATION_TEXT_V1` 是本域唯一文本规范:Unicode NFC、去首尾边界空白、CRLF/CR 归一为 LF、不折叠内部空白并按 Unicode code point 计长。旧 `GenealogyJoinApplyBody/GenealogyJoinAuditBody`、`phone/inviterUserId` 与数字 `status/auditRemark` 不再是 APP owner;通用 G-series 与 core-flow 测试必须把所有权移交给专项门禁。
-
-`API-JOIN-003` 固定无 PII 幂等与崩溃恢复。`GenealogyJoinApplicationRequestKey` 为 `gja.{13 位 issuedAt 毫秒}.{22—43 位 base64url CSPRNG}`,随机量至少 128 位;服务端按时间固定 10 分钟接受窗、5 分钟未来偏差与认领后最多 2 分钟收敛。canonical identity 覆盖 method、规范 path、genealogyId、tenant、account、client 与规范 body。同 scope/key/request 重放同一 `GenealogyJoinApplicationReceipt`,不同 digest 返回 `IDEMPOTENCY_KEY_REUSED`;同 tenant/account/genealogy 最多一个活动 PENDING,必须由数据库唯一约束保证。幂等 scope、活动唯一 scope、事务 effects、重验字段、状态迁移与 cursor 机器扩展都必须是真实 JSON 数组,逗号字符串不能冒充集合。POST 在领域事务内重验 genealogyState=READY、accessPreset=PUBLIC_APPLY 与 applicationEligibility,并与 G11 设置 PUT 共同声明 `x-public-apply-coordination=ATOMIC_SINGLE_WINNER`;关闭公开申请与新准入竞态只能一方提交。申请领域行和 SUCCEEDED 回执在同一业务事务提交,resolver 判定 FAILED 前不得把已提交申请误报为零写。
-
-状态唯一 owner 是只读 `GET /genealogy/app/genealogies/join-apply-requests/{requestKey}`。响应以显式 mapping 的 oneOf 精确为 `PENDING{resolveBy,retryAfterSeconds}`、`SUCCEEDED{result}`、`FAILED_NO_COMMIT`;只允许 `ABSENT→PENDING→SUCCEEDED/FAILED_NO_COMMIT`,终态不可变。GET 不创建墓碑、不推进状态;接受窗内未知 key 返回带 acceptUntil/Retry-After 的非泄漏 404,窗后无记录按 key 时间零写计算 FAILED,迟到 POST 永久拒绝。跨 account/tenant/client 统一 404。客户端只持久 `{sessionEpoch,requestKey,startedAt}`;当前进程可用冻结 snapshot 重放,重启只查 status,不把姓名、关系、理由或完整 body 落盘。
-
-`API-JOIN-004` 固定撤回 CAS:DELETE 只允许当前申请人撤回 PENDING;`WHERE status=PENDING` 决定唯一赢家,相同撤回只返回 WITHDRAWN typed receipt,审核已赢或其他终态返回 typed 409 与无 PII current state。`API-JOIN-005` 固定审核 CAS:body 只允许 `{decision:APPROVE}` 或 `{decision:REJECT,rejectionReason}` 两个闭合分支;相同决定只重放 APPROVED/REJECTED 原 200,规范化后不同拒绝理由或相反决定返回 409,审核成功绝不返回 WITHDRAWN。批准在一个事务内重验权限、READY 与 PUBLIC_APPLY,完成 PENDING CAS、唯一成员关系和 APPROVED;入口 capability 不是服务端授权证明。POST 的 409 只引用 `RJoinApplicationKeyConflict`,DELETE/PUT 的 409 只引用带 current 的 `RJoinApplicationStateConflict`;禁止用联合两类业务码的宽响应 owner 产生跨操作假绿。key 复用、过期或活动 PENDING 冲突不强制携带不存在的申请 current,只有申请状态/决定冲突分支必带 current。不引入 applicationVersion、If-Match 或审核详情端点。
-
-`API-JOIN-006` 固定部署与客户端发布门槛。七个 operation required SaToken/非空 clientid,所有声明响应只允许 `application/json` 与 `Cache-Control: private, no-store`,429 带 Retry-After;禁止 `*/*`、default、int64 身份、通用 RList/RObject/RVoid、HTTP 200 包装认证错误。OpenAPI 静态扩展只能登记幂等、cursor、CAS 和事务意图,不能证明数据库实现;后端还须用数据库观测、并发与 fault injection 验证唯一约束、零写、事务、fencing、真实 HTTP/CORS。客户端门禁通过前 G06/G08/G09/G10 继续本地预览;接线时原子删除 G10 手机号、三处消息中心承诺、LOCAL_WITHDRAWN 和遗留 adapter,补齐原生按钮、44dp、提交冻结、状态播报、错误关联、首错聚焦、长文换行及 MuMu 的系统字号/TalkBack/键盘/返回/慢网/杀进程矩阵。
-
-`tests/join-application-openapi-contract.ps1` 是上述七个 operation、schema 与响应闭包的唯一静态 owner,当前精确输出 `JOIN-APPLICATION-OPENAPI-CONTRACT BLOCKED`。只有后端同版本重导 JSON/YAML、专项门禁、后端集成反例、客户端状态机、全量回归和 MuMu 发布矩阵全部通过,普通加入申请才可称为上线闭环;静态门禁单独转绿不开放页面。
-
-### 23.11 G06/M08 邀请码签发与直接加入合同
-
-任务 37 与普通申请完全隔离。唯一产品流程为:M08 管理自己有权签发的活动邀请;G06 在 JSON body 中安全解析邀请码(不消费票据、不建立成员,仅允许轮换短时 grant 摘要),展示可信的最小家谱目标和“确认后立即成为成员、不进入审核”,用户明确确认后直接兑换;成功刷新 workspace、安装家谱 context,再进入 G01/G05。邀请码流程不进入 G08,不提交 `applicantName/relationDesc/applyReason`,不创建 join-application、PENDING 或审核通知。真实接线时必须原子删除 G06→G08 的 invite 导航、G08 `source=invite` 分支、`JP2026`、首个 fixture 目标和普通 `canApply` 资格复用;成员资料或人物关联另立合同。
-
-`API-INVITE-001` 固定六个 operation:`appListMyGenealogyInviteTickets`、`appIssueGenealogyInviteTicket`、`appRevokeGenealogyInviteTicket`、`appResolveGenealogyInviteTicket`、`appRedeemGenealogyInviteTicket`、`appGetGenealogyInviteRedemptionRequest`。所有 operation required SaToken、非空 clientid、typed JSON 和 private/no-store;429 带 Retry-After。邀请码只能置于 resolve 的 JSON body,绝不进入 URL、query、导航、持久化、日志、APM、分析、自动测试、崩溃报告或发布证据截图;用户主动显示/复制/系统分享属于受提示的显式动作。列表只返回当前活动票据元数据,不返回原码、领取人或剩余目标身份。
-
-`API-INVITE-002` 固定首版为单次、24 小时、服务端时间判定的 opaque bearer ticket。原码使用版本前缀和 26 位 Crockford Base32 随机量,至少 128 位 CSPRNG 熵;展示可分组,canonical 校验不接受易混淆字符。数据库以 HMAC/摘要查找,仅为同 key 幂等重放使用隔离 KMS envelope encryption 保存原码 600 秒;恢复窗内重放同一 ticket 和原码,窗后只返回同一 ticket 的无秘密 metadata 与 `ISSUED_SECRET_UNAVAILABLE`,不得新建票据。列表永不恢复原码。状态唯一为 `ACTIVE→CONSUMED/REVOKED/EXPIRED`,终态不可逆。resolve 不消费票据或建立成员,但允许写入/轮换每个 tenant/account/client/ticketVersion 唯一的短时 grant 摘要;旧 grant 立即失效、TTL 最多五分钟并清理。redemption token 绑定 tenant/account/client/inviteTicketId/ticketVersion/genealogyId/authorizationEpoch;这里的 authorizationEpoch 是服务端邀请授权版本,签发者移除/降权、邀请功能关闭或票据版本变化时提升并使旧 grant 失效。编辑输入、切账号或 session epoch 变化立即销毁客户端内存 token。
-
-`API-INVITE-003` 固定签发与撤销权限。M08 从 workspace `/mine` 取得当前明确家谱,不新增可信 URL genealogyId;workspace 投影字段 `canInviteMembers` 唯一映射服务端 capability `INVITE_MEMBER`,服务端仍重验 READY、邀请功能和当前成员关系。POST 无可配置 body,并用数据库约束控制每个 tenant/genealogy/issuer 的活动票据上限。签发 `Idempotency-Key` 为 `gii.{13 位毫秒}.{22—43 位 base64url CSPRNG}`;600 秒只限制不存在 key 的首次认领,已存在 key 永远定位同一 ticket,不同 digest 优先 409,恢复窗内重放原码、窗后只返 metadata,绝不签第二枚。客户端 marker 固定 `{sessionEpoch,genealogyId,requestKey,startedAt}`,不得从重启后的当前 workspace 猜 genealogyId。KMS 密文、ticket、HMAC lookup 和 request receipt 作为单一提交单元,任一步失败零票据。DELETE 只允许签发者本人管理并做 ACTIVE→REVOKED CAS,相同撤销重放原 200;CONSUMED/EXPIRED 返回 typed 409 current state,跨签发者统一 404。权限降级或邀请功能关闭必须让活动票据和旧 redemption token 立即失效。
-
-`API-INVITE-004` 固定兑换事务。redeem 无 request body,只通过 required、敏感的 `Genealogy-Redemption-Token` header 和 `gir` Idempotency-Key 消费当前账号 grant。服务端在同一事务内重验 token 绑定/有效期、票据 ACTIVE/版本/未过期、签发者权限、家谱 READY/邀请功能、账号可加入与容量,执行 ACTIVE→CONSUMED CAS、唯一 `(tenant,genealogyId,account)` MEMBER 关系和 SUCCEEDED receipt;失败全部回滚。不得建立人物、亲属关系或姓名副本。同码两账号、同账号两码、撤销/兑换、权限撤销/兑换竞态都只能有一个事务赢家;失败事务不得消费票据。已有普通 PENDING 固定 `ACTIVE_PENDING_APPLICATION`,引导先在 G09 撤回,邀请流程不得暗改任务 36 状态。
-
-`API-INVITE-005` 固定结果未知恢复。兑换 request key 采用 `gir.{issuedAt}.{CSPRNG}`,600 秒接受窗、300 秒未来偏差、认领后 120 秒内收敛;状态纯读 GET 只允许 `ABSENT→PENDING→SUCCEEDED/FAILED_NO_COMMIT`,终态不可变,已存在终态优先于 absent 计算,FAILED 保证票据未消费且成员未创建。成员、票据消耗和成功回执同事务提交,resolver/watchdog 以 fencing CAS 收敛,旧 worker 不得迟交。终态回执至少保留 30 天,客户端 marker TTL 为 30 天并先于回执清理;任何清理后也不得凭控制记录缺失否定已提交领域写。客户端 dispatch 前只持久 `{sessionEpoch,requestKey,startedAt}`,不持久邀请码、redemption token、目标或 body;SUCCEEDED 后刷新 `/mine` 并只重试本地 context/导航收口,FAILED 回 G06 重新输入,unknown 不换 key。
-
-`API-INVITE-006` 固定安全、交互与发布反例。invalid/expired/revoked/consumed/跨 tenant 统一非枚举 `INVITE_TICKET_NOT_AVAILABLE`,resolve 需要账号、设备/IP、前缀和全局多维限流与时间侧信道控制。M08 覆盖加载、无权限、无票据、签发/unknown、原码显示/复制/分享、即将过期、撤销/竞态;G06 覆盖输入、格式错、解析、可信目标、明确确认、redeem PENDING/unknown、已加入、活动普通申请、限流、票据失效、账号切换和迟到响应。原生按钮、tablist/tab/aria-selected、label、aria-invalid/describedby、首错聚焦、44dp、状态播报、长码/长谱名换行和提交冻结均为发布门槛;MuMu 覆盖 320/360/412、1.3 倍字号、TalkBack、键盘、粘贴、双击、慢网/断网、杀进程、Android 返回与系统分享取消。后端还须用真实账号、数据库观测、并发、fault injection、日志审计和正式 HTTP/CORS 证明合同,OpenAPI 扩展不能替代实现证据。
-
-### 23.12 G11 家谱设置版本化写入合同
-
-任务 38 只治理 G11 的设置读取与写入,不混入 G12 字辈、成员管理、邀请码签发或普通申请审核。全局唯一写 owner 保留 `PUT /genealogy/app/genealogies/{genealogyId}`,operationId 固定为 `appUpdateGenealogySettings` 且全局只出现一次;不新增 PATCH、`/settings` 旁路或任何递归引用设置 body/包含任意一个 `genealogyName/intro/accessPreset` 单字段的第二写入口,外部或错分区同名 `$ref` 也按违规 owner 失败,只有精确 G03 建谱 POST 豁免。为消除裸 `intro` 歧义,`/genealogy/app/genealogies...` 写 body 根层的 `intro` 由设置合同保留,子域必须使用自身有界名称。单谱唯一读取 owner 继续是 `GET /genealogy/app/genealogies/{genealogyId}/overview`,同版删除重复的通用 GET,并对全部 `/genealogy/app/` GET 以响应 schema 闭包和 allOf 属性合成拒绝任何旁路详情;G11 只消费 workspace 唯一门禁的 PASS 结论,每次进入必须 fresh 读取 overview 后才建立可编辑 baseline,不从路由、`/mine` 卡片、G05 旧内存对象、`roleType` 或 fixture 推导当前设置与权限。
-
-`API-SETTINGS-001` 固定共享字段与唯一模型。家谱 ID 继续引用词法 `GenealogyId`;新增共享 `GenealogyName`,统一 G03 创建、G11 更新和 `AppGenealogyVo` 为非 null、NFC、无边界空白、无换行/控制字符的 1—24 Unicode code point,删除 G11 旧 20 字双上限。共享 `GenealogyIntro` 精确允许非 null 空串,或 NFC、无边界空白、1—80 code point 的内容;正文只允许内部 LF,拒绝 CR、tab 和其他控制字符,空串就是清空,省略才是保持,null 与纯空白非法。`GenealogyAccessPreset` 仍由任务 35 作为 APP 读/建/改唯一枚举 owner,只有 `MEMBER_ONLY/PUBLIC_APPLY`。overview 与 PUT 200 都复用关闭额外字段、精确 `{code,data}` 的 `RAppGenealogyVo → AppGenealogyVo`;后者 required `genealogyId/genealogyName/intro/accessPreset/settingsVersion/canManage`,不新建会重复字段规则的 settings snapshot。
-
-`API-SETTINGS-002` 固定原子 dirty-only merge。请求 body 唯一为关闭额外字段、`minProperties=1/maxProperties=3` 的 `AppGenealogySettingsUpdateBody`,属性精确为 `genealogyName/intro/accessPreset` 且都非 required;出现字段更新、省略字段保持,body 不携带 version。服务端在同一事务锁定家谱并重新校验权限后一次应用全部出现字段,不能按整资源 PUT 把其他字段覆盖。canonical 后实际无变化可返回 200,但必须保留原版本且除审计外不产生领域副作用;客户端 clean draft 永不发请求。
-
-`API-SETTINGS-003` 固定唯一并发模型。新增非 null、1—128 位 URL-safe opaque `GenealogySettingsVersion`,只允许比较,不得解析、递增或经过 JavaScript Number;它以 `x-version-scope-fields=[genealogyName,intro,accessPreset]` 和 `x-version-change-policy=CANONICAL_SETTINGS_CHANGE_ONLY` 锁定只在这三个 canonical 设置实际变化时更换,其他领域写与 canonical no-op 都不得误增版本。`AppGenealogyVo.settingsVersion` required,PUT required `If-Match` 引用同一 owner,请求 body 不复制 version。项目统一采用 typed HTTP 409,而不是为 G11 单独引入强 ETag/412。409 `RGenealogySettingsConflict` 根层只允许 `oneOf/discriminator` 两个关键词,每个分支只能是 exact local schema ref;`GENEALOGY_SETTINGS_VERSION_CHANGED` 分支 required `current: AppGenealogyVo`,`GENEALOGY_NOT_READY` 与 `ACTIVE_PENDING_APPLICATIONS` 分支不得带 current 或审核数据。只有仍具管理权限的调用者可得到版本/current;服务端事务内重验权限。冲突优先级固定为 version → READY → active PENDING,旧 writer 不得用过期 baseline 触发业务判断。
-
-`API-SETTINGS-004` 固定访问预设迁移与普通申请并发。活动 PENDING 只阻断实际的 `PUBLIC_APPLY→MEMBER_ONLY`:只改名称/简介、已经是 MEMBER_ONLY 的 no-op 或 `MEMBER_ONLY→PUBLIC_APPLY` 不得被误阻断;同一请求还改名称时,只要访问预设迁移被阻断,整笔请求零写。活动 PENDING 返回 `ACTIVE_PENDING_APPLICATIONS`,G11 引导去 G10 处理,不自动拒绝、撤回或迁移申请;邀请码合同不受影响。设置 PUT 和任务 36 新申请 POST 都必须在事务内重验 genealogyState/accessPreset(申请另重验 applicationEligibility),并共同声明 `x-public-apply-coordination=ATOMIC_SINGLE_WINNER`;PENDING 检查、preset 更新和新申请准入竞态只能一方提交,不把实现限制为特定数据库隔离级别。
-
-`API-SETTINGS-005` 固定响应、结果未知与缓存收口。PUT 精确声明 200/400/401/403/404/409/422/429/500,全部只允许 typed `application/json`;每个 response 必须包含固定单值 enum `Cache-Control: private, no-store`,429 另有 1—300 秒 `Retry-After`,只允许 `traceparent/tracestate/x-request-id/x-correlation-id` 非语义 tracing header,禁止 ETag 与其他语义 header。parameter/response/header/schema 解析只接受 exact local component ref;四种 tracing header 若内联,必须是 allowed-key 关闭且带非 null 的 string schema 的 Header Object,不能以 external/wrong-section ref 或任意 inline schema 绕过。所有标量、引用字段、成功/错误 envelope 和 fieldErrors 用 allowed-key 集拒绝 `nullable`、readOnly/writeOnly、冲突组合与其他未拥有的验证关键字。禁止 default、3xx、`*/*`、通用 RObject/Void、可加 debug 字段的宽 envelope 和 HTTP 200 包业务错误。200 返回完整 canonical `RAppGenealogyVo`;400、401、403、404、422、429 为确定失败,500 `GENEALOGY_SETTINGS_OUTCOME_UNKNOWN`、网络、超时、408、取消和畸形 2xx 都是结果未知。客户端提交时冻结 `{baseline,dirtyPatch,settingsVersion,sessionEpoch}`,未知后不自动第二次 PUT,而 fresh 读取 overview:全部脏字段等于目标只可陈述“当前设置已与所选内容一致”,不能证明本次请求成功;仍为 baseline 才允许用户明确重试;部分匹配或第三值进入字段级三方比较。成功原子回填 canonical baseline,失效 `/mine`、overview、公开搜索和公开预览缓存并重新校验 context;权限/成员关系已变时清 context 回 G01,否则回 G05。
-
-`API-SETTINGS-006` 固定客户端与发布激活条件。本批只建立 OpenAPI 门禁与权威文档,不创建因生产 coordinator 不存在而恒红、只扫描源码 token 或复制 OpenAPI 断言的占位 client gate。后端同版双导出、workspace 读取和共享 owner 门禁转绿后,客户端批次第一项写操作必须先新增实际执行生产 normalizer/coordinator 的纯 Node 失败测试,再实现 adapter/coordinator;覆盖 24/80 code point、dirty/clear、三个 409、三方比较、unknown 对账、权限撤销、双击/取消/迟到响应、sessionEpoch、canonical 回填、缓存/context 收口。随后才可原子删除 fixture 数字映射、本地成功 timer 和“禁止 appApi”旧断言。页面至少有 loading、ready/dirty、saving、saved、validation、uncertain/reconciling、conflict、no-permission、auth-expired、unavailable;用原生 button/radio、真实 label、aria-invalid/describedby、首错聚焦、busy/live 状态、44dp 与返回冻结。G11 OpenAPI、workspace/shared owner、可执行客户端行为门禁、聚焦/全量回归及 MuMu 320/360/412、1.3 倍字号、TalkBack、软键盘、双击、慢网/断网/杀进程、Android 返回与权限/版本竞态必须全部通过,OpenAPI 绿只表示可以开始客户端 TDD,不表示允许直接接线或上线。
-
-`tests/g11-settings-openapi-contract.ps1` 是全局唯一设置写入口、body、settingsVersion/If-Match、409 oneOf、响应矩阵与设置字段 owner 的唯一静态门禁;任务 35 的 G03 门禁只继续拥有 bootstrap、共享 accessPreset/旧 DTO 删除及其读取传播,不再检查设置 operation、body 或响应,workspace 与 join 门禁分别唯一拥有读取基础和申请准入反向协调。当前专项门禁稳定输出 `G11-SETTINGS-OPENAPI-CONTRACT BLOCKED` 和 48 项缺口;受保护 OpenAPI 未修改。
-
-### 23.13 G12 字辈集合版本化保存合同
-
-任务 39 只治理 G12 字辈集合读取与原子保存,不混入逐条编辑、人物世代、T01 高亮、邀请码或 G11 设置。`API-POEM-001` 固定全局唯一 owner 为 `GET/PUT /genealogy/app/genealogies/{genealogyId}/generation-poems`,operationId 分别且全局唯一为 `appGetGenerationPoemSet`、`appUpdateGenerationPoemSet`。同版删除旧 collection POST、逐行 PUT、`/batch/preview`、`/batch/save`、`/management` 及其旧 schema/response;不引入 preview token、服务端 preview/status 或第二写入口。GET/PUT 200 共用关闭额外字段的 `RGenerationPoemSetSnapshot → GenerationPoemSetSnapshot`,快照精确为 `{genealogyId,poemSetVersion,items}`,只投影 ACTIVE、严格按 generationNo 升序;普通读只要求 canView,维护写在事务内重验 tenant、canEditContent 与 READY。
-
-`API-POEM-002` 固定唯一请求与完整候选语义。`AppGenerationPoemSetUpdateBody` 精确 required `{items,disableMissing}`,items 为 0—500 个严格 generationNo 升序的 `AppGenerationPoemSetItem`。已有 ACTIVE 行必须提交当前词法 poemId,允许把稳定 ID 显式移动到新世代;新行省略 poemId,引用已停用/未知 ID 失败。generationNo 是唯一排序 owner,范围 1—2147483647;generationText 允许重复。`disableMissing=false` 保留全部未声明 baseline ACTIVE,`true` 软停用遗漏项;空 false 是 no-op,空 true 停用全部,历史绝不物理删除。服务端必须依次 `RESOLVE_BASELINE_ACTIVE_IDS`、`VALIDATE_DECLARED_STRICT_ORDER`、构造声明目标、应用遗漏策略、按 generationNo 排序 merged candidate,再验证 ID/世代唯一、`GENERATION_SLOT_CONFLICT`、连续性、`VALIDATE_FINAL_ACTIVE_CAPACITY`,随后 `ALLOCATE_UNIQUE_NEW_IDS` 并验证新 ID 非空、唯一、非 baseline,最后 `WRITE_ATOMICALLY`。swap 必须显式声明所有受影响行,全部成功或零领域写且外部不可见中间态。
-
-`API-POEM-003` 固定唯一并发与文本模型。`GenerationPoemSetVersion` 是非空、词法、不可解析且永不复用的 ACTIVE 语义版本;PUT required `If-Match` 引用同一 owner,body 不重复版本,不发布 ETag/412。canonical no-op 返回当前 200 并保持版本,ACTIVE 语义变化必须生成新版本。字辈 ID 与版本均只能词法比较,不经 JavaScript Number。`GenerationPoemText` 必须为 well-formed UTF-16、NFC、1—50 Unicode code point、无边界空白,并拒绝 C0/C1、CR/LF/tab、bidi override/isolate、方向标记、zero-width、BOM、word joiner、行/段分隔符与孤立 surrogate;不以 UTF-16 code unit 截断。
-
-`API-POEM-004` 固定 typed HTTP、授权和部署 owner。GET 精确声明 200/400/401/404/429/500,PUT 另含 403/409/422;成功、固定错误、409 union 和 422 fieldErrors 都是关闭额外字段的 typed `application/json`,禁止 default、3xx、`*/*`、200 包业务错误或通用 RObject。所有响应 required `Cache-Control: private, no-store`,429 required Retry-After;SaToken 必须是精确 header apiKey `Authorization` 且 security requirement 是 JSON 数组,clientid 非空。浏览器预检唯一声明 owner 为顶层 `x-app-gateway-policies.APP_GATEWAY_PREFLIGHT`,精确允许 Authorization/Content-Type/If-Match/clientid、GET/PUT/OPTIONS、显式部署 origin allowlist 和 600 秒;operation 只引用该 owner。正式发布仍须真实 gateway OPTIONS/preflight smoke,导出扩展不能替代部署证据。
-
-`API-POEM-005` 固定冲突与结果未知恢复。409 只允许 `POEM_SET_VERSION_CONFLICT + current` 和 `GENEALOGY_NOT_READY`;422 精确包含请求顺序、重复 ID/世代、slot collision、非连续、容量、文本与行不可用,校验失败全程零写。网络、超时、408、取消、5xx 和畸形 2xx 都按 unknown。客户端冻结 baselinePoemSetVersion、baselineOrderedItems、declaredItems、disableMissing 与 sessionEpoch,按相同规则构造 effective target 后 fresh GET,执行 `FRESH_GET_THREE_WAY_NO_AUTO_PUT`:existing 按 poemId+generationNo+NFC 文本匹配,NEW 按 generationNo+文本匹配且返回 ID 必须非空、唯一、非 baseline;比较要求同基数、无额外 ACTIVE 行,忽略版本判断语义等价,但变化 target 必须有新且未复用版本。先判 current==target 并执行 `CURRENT_EQUALS_TARGET_FIRST_NO_ATTRIBUTION`,只确认当前事实;再判 current==old 允许用户明确重试,否则进入 divergent,任何分支都不自动 PUT。
-
-`API-POEM-006` 固定客户端、无障碍与激活条件。本批只建立受保护 OpenAPI 门禁、对抗合同、Unicode 运行时证据和中文权威文档;G12 在全部后端门禁转绿前保持明确本地预览。后端同版双导出通过后,客户端第一项写操作必须新增直接执行生产 normalizer/coordinator 的纯 Node 失败测试,再实现唯一 adapter/coordinator,并原子删除 fixture、timer、本地成功、旧 preview/save 假合同及“禁止 appApi”旧断言。页面覆盖 loading/empty/editing/validating/saving/saved/unknown/conflict/no-permission/auth-expired/unavailable、清空二次确认、草稿冻结、live region、首错聚焦、原生按钮、44dp 与返回保护;MuMu 覆盖 320/360/412、1.3 倍字号、TalkBack、软键盘、0/1/500×50、swap、双击、慢网/断网/杀进程、权限撤销、READY 变化和账号切换。未来 T01 高亮只消费正式 ACTIVE 快照,不能成为字辈写 owner。
-
-唯一静态 owner 为 `tests/g12-generation-poem-openapi-contract.ps1`,当前输出 `G12-GENERATION-POEM-OPENAPI-CONTRACT BLOCKED`;合法 zero issues 种子、大小写严格 JSON Pointer、ref 图、HTTP 方法、callback、候选/unknown/CORS 和 annotation 非 owner 由 `tests/g12-generation-poem-openapi-adversarial-contract.ps1` 覆盖,字辈 Unicode 由 `tests/g12-generation-poem-unicode-contract-runtime-smoke.js` 覆盖。G-series 只保留 owner 转移说明,不再重复 G12 合同;受保护 OpenAPI 与页面保持未修改。
-
-### 23.14 F01/F03 家族动态与一级评论读取合同
-
-任务 40 只治理 F01 动态列表、F03 动态详情和正常一级评论读取,不混入 F02 发布、点赞、评论/回复写、回复读取或媒体文件读取。受保护双导出中的 APP 路径已有谱上下文,页面与 fixture 也以 `(genealogyId,feedId)` 为身份;因此三方否决全局 feed 路由,保留谱内解析和授权。2026-07-23 线上 OpenAPI 3.1.0 与受保护旧导出都不能直接接页:两者分别存在 `/feeds` 与 `/feeds/page`、`/comments` 与 `/comments/page` 双读取 owner,无稳定 operationId,身份仍为 int64,feed 使用通用或无 required 的响应,线上 `FamilyFeedCommentVo` 还暴露手机号、业务用户 ID、内部审核人/动作/原因、状态和持久化字段。双导出内部 parity 只能证明两份旧文件相同,不能证明它们与线上同版本或适合发布。
-
-`API-FEED-READ-001` 固定三个唯一 owner:`GET /genealogy/app/genealogies/{genealogyId}/feeds` 的 `appListFamilyFeeds`、`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}` 的 `appGetFamilyFeed`、`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments` 的 `appListFamilyFeedRootComments`。同版本删除两个 `/page` GET;非分页 collection GET 成为唯一 cursor owner。写方法、likes、replies 和媒体读取不由本批声明或删除,不能借本批旁路接入。三个 operationId 在全局各出现一次,GET 无 request body。
-
-`API-FEED-READ-002` 固定词法身份与无 PII 最小投影。`GenealogyId/FamilyFeedId/FamilyFeedCommentId` 均为 1—128 位 URL-safe opaque string,客户端只比较、不解析,不得进入 JavaScript Number。`AppFamilyFeedReadItem` 是 closed required `{feedId,feedContent,authorDisplayName,publishedAt,hasMedia}`:正文为 `FAMILY_FEED_TEXT_V1`、1—300 Unicode code point;作者名是经过授权的展示投影,原账号缺失时由服务端提供非空退化文案;时间是服务端生成且不可修改的 RFC3339。`hasMedia` 只证明存在附件,不泄露 `mediaOssIds`;在独立媒体读取合同通过前客户端必须展示诚实占位,不能把媒体动态静默伪装为完整纯文字内容。标题、标签、点赞、状态、排序值和总评论数不是当前页面的可靠服务端字段,不从 fixture 或正文猜值。
-
-`AppFamilyFeedRootCommentReadItem` 是 closed required `{commentId,commentContent,authorDisplayName,publishedAt}`;正文为 `FAMILY_FEED_COMMENT_TEXT_V1`、1—1000 Unicode code point。comments collection 只投影当前正常可见的一级评论,排除回复、删除占位、parent/level、手机号、账号/业务用户 ID、tenant、状态、remark、审核字段和 createBy/updateBy。详情不嵌 comments,评论独立加载和独立失败;没有 total 时客户端只能显示“已加载 N 条”,不得把已加载数组长度冒充服务端总数。
-
-`API-FEED-READ-003` 固定对象级可见性。三个 GET 每次请求都重新验证 tenant、genealogy 与 membership;详情和评论另验证 feed 属于 path 家谱且当前可见。未知 ID、错谱、动态删除/隐藏、无权、撤权或 cursor 跨主体/跨谱/跨 feed 重放统一 typed `404 FAMILY_FEED_NOT_AVAILABLE`,不以 403 或不同消息泄露资源存在性。未认证固定 401。后端只能从已通过可见性过滤的根评论集合生成响应和 cursor;前一页授权不延续为后一页授权。
-
-`API-FEED-READ-004` 固定 opaque keyset cursor,不采用 pageNum/pageSize。首请求不带 cursor;`limit` 可省略且默认 20,范围 1—50;refresh 必须丢弃旧 cursor;`nextCursor` 缺席表示结束,响应不含 total、pageNum 或 hasMore 冗余真值。feed 按 `(publishedAt DESC, feedId DESC_ORDINAL)`,一级评论按 `(publishedAt ASC, commentId ASC_ORDINAL)`。cursor 绑定 tenant/account/authSession/client、genealogyId、评论的 feedId、projection/order/limit、windowUpperBound 与 lastTuple,并具有完整性和过期校验;篡改或过期返回 `400 FAMILY_FEED_CURSOR_INVALID`,不静默从首页重启。
-
-读取窗口精确命名为 `UPPER_BOUND_KEYSET_LATEST_VISIBLE`,不能宣传成严格 MVCC snapshot:首次请求确定上界,新插入内容等 refresh 后进入;后续读取前删除、审核隐藏或撤权的内容省略;仍可见但已编辑的正文按该页读取时的最新可见版本返回。无 total,因此上述变化不会伪造恒定总量;keyset 与不可变 publishedAt/词法 ID tie-breaker 只保证在合同窗口内不因新增头部内容产生 offset 重复或漏项。
-
-`API-FEED-READ-005` 固定 typed HTTP、安全与缓存。三个 GET 精确声明 200/400/401/404/429/500,只允许 closed typed `application/json`;禁止 default、3xx、`*/*`、通用 RList/RObject/PageResult、HTTP 200 包业务错和开放 DTO。所有 response 必须有单值 `Cache-Control: private, no-store`,429 另有 1—300 秒 Retry-After;operation security 必须是精确 SaToken 数组且空 scopes,required `clientid` 为非空 1—128 字符串。读取复用唯一 `APP_GATEWAY_PREFLIGHT`,OpenAPI 扩展只登记 owner;正式 H5 origin 的真实 OPTIONS/preflight、凭证与拒绝 origin/header/method 反例仍由部署门禁证明。
-
-`API-FEED-READ-006` 固定激活顺序。`tests/family-feed-read-openapi-contract.ps1` 是三条 GET、词法 ID、closed projection、cursor、可见性、typed response 与 no-PII 闭包的唯一静态 owner,当前输出 `FAMILY-FEED-READ-OPENAPI-CONTRACT BLOCKED`、`Issues: 85`。`tests/family-feed-read-openapi-adversarial-contract.ps1` 用完整 zero issues 合法种子和 58 个独立变异覆盖旧 owner、外部/多跳 ref、大小写、security owner/数组、HEAD/OPTIONS/callback、PII/审核字段、int64、offset/total、错误 403 分流、wildcard 与缓存头,输出 `FAMILY-FEED-READ-OPENAPI-ADVERSARIAL-CONTRACT PASS MUTANTS=58`;它只证明静态门禁会正确转绿和拒绝反例,不解除后端红灯。后端还须以同版本 JSON/YAML/live `/v3/api-docs`、真实账号、权限撤销、跨谱 cursor、并发插入/删除/隐藏、数据库观测与正式 HTTP/CORS 关闭 P0。
-
-后端绿前 F01/F03 保持按复合身份深拷贝且失败关闭的 fixture,`runtimeConfig.mode` 保持 mock,不把 dormant `appApi.getFeeds` 宽分支接页,也不在远端失败后静默回退 fixture。后端三份证据通过后,客户端第一项写操作必须是直接执行生产 read normalizer/coordinator 的纯 Node 失败测试;随后原子迁移 F01 列表和 F03 详情/评论,删除 fixture 锁、嵌入评论、伪重试和旧“必须 fixture”断言。状态必须覆盖首屏 loading/empty/error、refresh、load-more/end/局部失败、详情 404、评论独立失败、`hasMedia` 占位、离页取消、sessionEpoch/切谱/切账号迟到响应、权限撤销、滚动与焦点恢复;原生 button、44dp、live region、长文换行和 MuMu 320/360/412、1.3 倍字号、TalkBack、键盘、慢网/断网/返回矩阵是发布条件。
-
-## 二十四、当前精确执行顺序
-
-后续不再按页面样式迁移重做,而按以下独立阶段执行:
-
-1. 导航栈语义统一:静态任务 1—10 已完成,MuMu 流程矩阵待执行。
-2. T01 大规模世系树:设计与 OpenAPI 红灯已完成;等待后端新图合同后按规范化、布局、Scene、Canvas 和页面交互分批实施。
-3. TAC 认证:客户端与静态/纯运行时门禁已完成;等待后端关闭 `API-AUTH-TAC-001`—`004`,随后执行真实环境与 Android 发布门禁。
-4. 领域上下文基础与 M07 真实反馈客户端已完成;家谱工作区三人审查与 OpenAPI 红灯已完成,等待后端关闭 `API-GENEALOGY-WORKSPACE-001`—`003` 后再接 G01/G05。
-5. G03 原子 bootstrap 三人审查与 OpenAPI 红灯已完成;等待后端关闭 `API-G03-001`—`005` 后,再实现严格 coordinator、无 PII 状态恢复、地区选择、context/G05/G01 闭环和独立 MuMu 矩阵。
-6. M06 帮助三人审查与 list-only OpenAPI 红灯已完成;等待后端关闭 `API-M06-001`—`003` 后再接严格 adapter。等待期间继续下一个无依赖只读域,不与验证码、T01 或支付混合。
-7. M01/M02/M03 个人资料读取三人审查与 OpenAPI 红灯已完成;等待后端关闭 `API-PROFILE-READ-001`—`003` 后再接掩码 adapter,不与资料写入混合。
-8. 通知读取和已读写入已分别完成三人审查与 OpenAPI 红灯;后端先关闭读取合同后实现无 ID 内存快照,再在独立写批次私有迁移字符串 ID、删除伪本地读状态并验证并发收敛。
-9. M02 资料写入三人审查与 OpenAPI 红灯已完成;等待读取与 `API-PROFILE-UPDATE-001`—`004` 同时关闭后,再分 normalizer、API 和页面状态实现。
-10. M10 当前设备退出三人审查与 OpenAPI 红灯已完成;等待后端关闭 `API-LOGOUT-001`—`003` 后,再实现 session epoch、logoutCoordinator 和 A01 一次性状态。
-11. M04 登录态改密与四条密码 wire 三人审查、OpenAPI 红灯已完成;等待后端关闭 `API-PASSWORD-001`—`005` 后,原子迁移共享策略、MD5 消费者、session marker、页面状态机与全设备撤销。
-12. M05 手机号换绑与全活动 OTP 三人审查、OpenAPI 红灯已完成;等待后端关闭 `API-PHONE-001`—`005` 且 M04/认证前置门禁通过后,再原子迁移六位码、专用受保护发码、最终 PUT 与 credential marker。等待期间转向 G/F/R,不混入本批。
-13. 任务 36 普通加入、任务 37 邀请码直入、任务 38 G11 设置、任务 39 G12 字辈集合和任务 40 F01/F03 家族动态读取的三人审查、专项 OpenAPI 红灯与 owner 移交已完成;等待后端分别关闭 API-JOIN/API-INVITE/API-SETTINGS/API-POEM/API-FEED-READ 后按各自客户端 TDD 顺序实施,任何单项 OpenAPI 转绿不开放页面。当前继续下一个独立业务域。
-14. 全局文字层级与无障碍第二轮。
-15. 生产配置、隐私权限、可观测性、构建发布、升级回滚与 MuMu 全流程终审。
-
-T01 必需的线性目录和 44dp 控件随 T01 一起完成;认证浮层的壳层无障碍不扩张为全项目已通过。外部门禁阻塞时继续无依赖批次,但任何真实成功、接口兼容或视觉通过都必须有对应证据。
diff --git a/docs/接口与页面映射总表.md b/docs/接口与页面映射总表.md
deleted file mode 100644
index df96bb7..0000000
--- a/docs/接口与页面映射总表.md
+++ /dev/null
@@ -1,670 +0,0 @@
-# 接口与页面映射总表
-
-> 更新日期:2026-07-22
-> 阶段状态:阶段 0、导航任务 1—10、A01/A04/A05 TAC 客户端、领域上下文基础与 M07 反馈客户端已完成;家谱工作区、G03 原子创建、M06 帮助、个人资料读写、通知读写、M10 服务端退出、M04 密码凭证与 M05 手机号换绑三人审查及 OpenAPI 红灯已完成;普通加入、邀请码直入与 G11 设置三人审查及 OpenAPI 红灯也已完成;T01、TAC、工作区、G03、帮助、profile、通知、logout、password 与 phone-change 后端接口门禁当前红灯,加入、邀请与 settings 同样保持红灯;MuMu 原生矩阵待执行
-> 接口状态:已完成 A 系列认证/TAC、G 系列第一轮、G01/G05 工作区专项、G03 原子创建、Task36 普通加入、Task37 邀请码直入与 Task38 G11 设置专项、F 系列当前写接口边界、M06 帮助、M07 反馈、M01/M02/M03 个人资料读取、M02 资料写入、N01/N02/M01/G01 通知读写、M10 当前设备退出、M04/四条密码 wire、M05/全活动 OTP wire、T01 世系图及 2026-07-22 新线上 OpenAPI 差异核对;其余操作仍待逐项审查
-
-## 一、权威边界
-
-本文件是活动页面、业务目标、进入方式、返回或完成目标、适用状态与接口归属关系的唯一总表。`pages.json` 是活动路由的唯一注册清单;两者必须同轮更新并保持精确一致。
-
-接口的唯一编辑源是后端维护的 Apifox 项目。根目录 `APP.openapi.json` 用于离线自动分析,`APP.openapi.yaml` 用于人工阅读与跨工具导入;部署地址的 `/v3/api-docs` 只提供当前线上实现证据。阶段 0 保护的双导出是 OpenAPI 3.0.1、112 路径、153 操作的旧快照;2026-07-22 21:52 只读核对 `https://backend-api.ddxcjp.cn/v3/api-docs` 得到 OpenAPI 3.1.0、722 路径、858 操作、507 模型。发现差异时必须由后端生成同版本双导出,不能手工覆盖受保护文件,也不能把专项结论扩张为全部线上操作均已审查。
-
-当前边界如下:
-
-- `pages.json` 注册 `52` 条活动路由;A02 已并入 A01,A06 保留源码但不属于活动路由。
-- 全项目响应式迁移与统一扫描已经完成;退役通用页面和零消费者旧表单删除后,实际 `64/64` 个 Vue 文件均在覆盖清单中。
-- 任务 5 实施前,A 系列及 G01—G10 曾由用户在 MuMu 中人工确认,G11、G12 以及 T、F、R、N、M 页面也曾逐页、逐状态审核并修复;这只是历史视觉基线,不覆盖任务 5—6 后的 G/T 动作、文案、权限和布局变更。任务 4—6 的当前代码仍须按实施计划重新完成 MuMu 流程矩阵。
-- 上述视觉结论是当前继续工作的基线,不等于真实接口、持久化、系统权限、真实短信、微信、支付或跨页数据闭环已经完成。
-- 后续发现明确、可复现的样式、交互或业务问题时可以重新打开页面;不得因为旧结论写着“通过”就忽略证据。
-
-## 二、全局业务与交互合同
-
-### 2.1 账户、启动与登录
-
-- APP 不设游客模式。首次打开、无有效凭证或凭证过期时进入 A01;有效登录态进入 G01。
-- A01 是唯一活动登录页,承载密码登录、短信登录、注册、找回密码、协议入口和尚未接入的微信登录入口。当前默认密码登录;开发/联调 wire 已按线上 `POST /genealogy/app/auth/login` 接通,成功统一保存 `AppLoginVo.access_token` 并进入 G01。默认 `runtimeConfig.mode=mock` 不会发真实请求;remote 测试入口先展示 static TAC,但线上登录接口尚未消费票据,因此只可用于联调,不能据此解除生产发布红灯。
-- A04 注册成功的目标是建立登录态后进入 G01。2026-07-22 新线上 OpenAPI 已确认 `POST /genealogy/app/auth/register` 与两种登录操作统一返回 `RAppLoginVo`,`data` 引用 `AppLoginVo`,会话字段为 `access_token`;`utils/api.js` 只读取这一当前字段。正式接入应保存有效会话后直接进入 G01,不让用户重复登录,也不为受保护旧快照保留并行兼容路径。行为验证与短信发送时机仍在后续短信状态机阶段核对。
-- A05 重设成功后不自动登录:返回 A01,保留合规的手机号信息,切换密码方式、聚焦密码框并让用户使用新密码登录。
-- A04、A05、M04 当前预览仍共用 `utils/validation.js` 的 `8–32+字母数字` 旧策略;Task33 已证明该规则只在客户端且无法作为生产 owner。门禁通过后必须与 A01/A04/A05/M04 的 MD5 wire 同批原子迁移为服务端权威的 15—64 Unicode code point、NFC、允许空格与 Unicode、无组成规则,并同步替换本地唯一 owner、页面文案和测试;不得只改 M04 或保留双轨。
-- A01 未勾选协议时在协议区域就近高亮并显示错误,不弹原生提示、不跳页;用户勾选后立即清除错误状态。
-- A01、A04、A05 已接入同一个 `TacVerification` 和 `static/tac/`,不能把本地滑动成功冒充服务端验证。A01 短信登录使用 `APP_SMS_LOGIN`,A04 使用 `APP_REGISTER`,A05 使用 `APP_FORGOT_PASSWORD`;三者都先从 `/captcha/require` 取得严格 provider/type 合同,再由 `/captcha/challenge` 和 `/captcha/verify` 换取 `validToken`,携票调用 `POST /genealogy/app/auth/sms/code`。A01 密码联调入口暂借现有 TAC 场景做客户端前置后调用线上密码登录 wire,但 `validToken` 未进入或被服务端消费;它不是安全闭环,`API-AUTH-TAC-001` 仍阻止 remote 配置成为生产发布配置。
-- A01/A04/A05 已实现可发送、发送中、60 秒倒计时、失败重试、手机号变更失效、验证码到期和重复发送保护;短信码精确为 4 位。认证 HTTP 只接受 HTTP 200 严格 envelope,统一 15 秒超时,Android 返回或页面卸载会中止 RequestTask,迟到回调不得改变已离开页面。真实限流、前后台剩余时间恢复和多设备重放仍需后端集成与 MuMu 证明。
-- 凭证过期先回 A01,再显示项目自定义的单按钮信息弹窗并聚焦登录表单;主动退出清除凭证,但可以保留用户上次选择的密码或短信登录方式,不保存密码。
-
-### 2.2 家谱上下文与加入、创建
-
-- 一个账号允许创建或加入多个家谱。G01 列表按“我创建的”“我加入的”“加入申请”分组,顶部只表示当前选中项。
-- G01 顶部当前家谱卡用于打开切换层;下方可用家谱卡直接进入 G05。只有导航成功后才同步顶部选中项和本机当前家谱 ID,失败或并发点击不得把页面与持久上下文串到不同家谱。首次且没有历史选择或失效标记时可确定使用首个可用家谱;调用方给定的新列表不再包含历史 ID,或显式目标不可用时,必须清空、持久标记并要求用户重选,跨重载也禁止静默回退到另一家谱。只保存词法字符串 ID,不复制整份家谱数据;真实撤权检测等待 workspace 接入 onShow/事件刷新。
-- 审核中记录只展示进度和“撤回申请”,顶部卡不可进入家谱;被拒绝记录展示原因和“修改后重新提交”,进入 G08 而不是 G05;已退出或被移除记录展示原因和“重新申请”,不得访问原家谱内容。
-- 只有 READY 且当前账号 `canView=true` 的家谱能够成为全局家谱上下文;审核中、被拒绝、已退出或被移除的记录不得覆盖最近一个可用上下文。G03 新合同不再产生“待录入始祖”业务状态;历史半成品如真实存在应由后端迁移/隔离,不能继续成为客户端正式状态。
-- 没有可用家谱时,相关页面不得展示上一个失效家谱的缓存内容,应引导用户搜索家谱、使用邀请码或创建家谱。
-- G01 空态的主次顺序为搜索家谱、邀请码加入、创建家谱;非空列表保留“添加家谱”底部弹层。所有者可见世系、成员、字辈诗、申请审核四个快捷入口,普通成员不显示申请审核。
-- G06 同时承载搜索与邀请码定位。产品目标仍是“邀请码直接加入且不生成审核记录”,但当前 OpenAPI 没有邀请码校验或直接加入操作,因此本地流程只展示目标并进入 G08 填写确认,完成后无结果返回 G01,不能选中家谱或声称已经加入。搜索申请进入审核;真实邀请码终点必须等后端合同补齐后替换本地预览。
-- G06 结果至少需要谱名、姓氏、地区、堂号、所属上级谱、当前支系、管理者或认证信息、成员规模和最近更新时间,以区分同名家谱和支系;未加入、已加入、审核中、被拒绝、已退出或移除、我创建的六种关系各自只出现一个明确动作。
-- G08 当前用真实姓名、与已知长辈的文字关系和补充说明表达申请;用户可见示例统一使用“某某某堂侄”等通用占位,不出现具体姓名。后端提供结构化参照成员或关系字段后,应以新合同完整替换文字关系旧路径。
-- G03 当前在同一页面实例内依次完成“创建家谱”和“录入始祖”,不接收 `step` 或 `genealogyId` 路由参数;门禁前本地成功无业务结果进入 G05 明确预览态。生产目标不允许创建中断成空谱:第一步零网络写,最终按钮一次原子创建家谱、OWNER 与唯一始祖;进程终止后按 operationKey 查询服务端操作状态,不恢复已删除的路由步骤合同,也不让 G01 承担半成品恢复卡。
-- G05 同一路由区分公开预览与成员视图。公开预览不得闪现成员隐私或管理入口;所有者和普通成员采用最小权限模型,最终权限以接口合同为准。
-- G05 首屏按身份确认、来源确认、可信度确认三层组织信息;世系是次级入口,不自动抢占首次进入流程。
-- G11 只维护当前可解释的名称、访问预设和家谱简介;门禁前本地 fixture 的“仅成员可见”“公开可申请”仍由 `utils/genealogy-contracts.js` 映射旧 `visibility/joinMode` 并对未知组合失败关闭。任务 38 已固定唯一 merge PUT、fresh overview baseline、`settingsVersion+If-Match+typed 409`、24/80 code point、活动 PENDING 迁移阻断和 unknown 对账;后端门禁通过前不删除诚实本地预览或接宽松接口,见 2.16/5.15。任务 39 已把 G12 收紧为唯一 GET/PUT、ACTIVE-only 完整集合、`poemSetVersion+If-Match`、完整候选校验、软停用与 unknown 三方对账;后端绿前仍只做本地预览,见 2.17/5.16。
-
-### 2.3 页面状态与请求结果
-
-- 每个可请求页面至少判断正常、加载、空、失败、无权限和数据失效是否适用;表单另覆盖本地校验、提交中、成功、失败、取消和重复提交。
-- 本地校验先于请求;字段错误就近展示。关联错误必须关联并聚焦到真正相关的字段,页面级或系统级错误在提交区或自定义结果弹窗中说明。
-- 提交开始后锁定同一动作,避免重复写入;失败保留用户输入并提供明确重试;成功先完成必要数据刷新,再结束当前流程。
-- 列表进入详情后返回,应恢复滚动位置、搜索词、筛选条件、展开分组、已加载页数和当前家谱选择;只有主动刷新、账号切换或原数据失效时才重置。
-- 目标数据过期、权限变化、网络失败和取消不是空数据,必须分别呈现可理解的结果和下一步。
-- 分页加载必须保留已有内容和滚动位置;失败显示就地重试,结束显示明确末尾状态,数据不足一页时不制造虚假“到底”文案,也不循环触发。
-- 下拉刷新保留原列表,成功后只在确有变化时提示更新;失败在列表顶部提供重试,不把刷新和触底加载混成同一状态。
-- 空态必须区分首次使用、搜索或筛选无结果、确实没有内容、加载失败和无权限;每种空态只突出一个主操作,最多一个次操作。
-
-### 2.4 导航、弹层与流程终点
-
-- 当前三个业务根页面是 G01“家谱”、F01“家族”和 M01“我的”,A01 是认证根页;导航栈语义统一已经完成,路由注册表、导航网关、共享页头、自定义底栏、认证、G、T、F、R、N/M 系列活动页均按测试先行落地,退役通用页面、临时页面目录和最后一个零消费者旧表单组件均已删除。源码导航扫描为 `MIGRATION-DEBT=0`;认证至 N/M 的 MuMu 原生流程复核仍待执行。
-- 返回、取消、完成和重复进入必须分别验证。页面完成后不得把已经结束的旧流程继续留在栈中,也不得用 `navigateBack` 猜测一个可能不存在的返回目标。
-- 普通底部弹层可由遮罩或 Android 返回键关闭;存在未保存输入时先确认是否放弃。确认弹窗的返回键等同取消;任何取消都不得被记录为成功。
-- 弹窗高度只允许使用视口 `max-height` 和内部滚动;普通页面内容高度由内容决定,不为单一设备压缩字号、行高或控件尺寸。
-- 用户可见反馈使用项目自定义组件,不新增原生 UniApp Toast、Modal、Loading 或 ActionSheet 作为正式体验。
-- 轻提示、底部弹层、居中确认、结果说明和危险操作按决策成本分级。不可逆操作必须说明后果并二次确认;普通操作不滥用确认。
-- 产品合同已经定案为“邀请码直接加入且不生成审核记录”:只有未来真实邀请码校验与直接加入接口成功才允许建立成员关系。当前 G06/G08 只做本地流程预览并明确未提交服务器;M08 的旧审核分支、硬编码邀请码、复制和海报伪能力已经删除,在真实邀请码签发与校验合同落地前保持不可用。
-
-### 2.5 三个根页面与主要流程
-
-```text
-A01 登录/A04 注册
-→ G01 我的家谱
-→ 搜索或邀请码加入(G06 → G08 → G09 或 G01)
-→ 创建家谱(G03 创建 → G03 录入始祖 → G05)
-→ 家谱浏览与管理(G05 → T01/G10/G11/G12)
-
-G01/G05
-→ F01 家族内容
-→ 动态、谱文、相册、人物、礼仪、备忘与功德
-
-G01/M01
-→ N01 消息中心
-→ N02 消息详情
-→ 对应业务目标
-
-M01 我的
-→ 资料、安全、帮助、反馈、推广、服务与关于
-```
-
-### 2.6 当前本地数据与路由参数边界
-
-当前 `52` 条活动页面除 A01/A04/A05 的认证调用外,仍使用页面内本地状态、fixture 或 mock 数据;其他活动页面没有 `appApi` 消费者。认证调用已经对准真实端点,但 `runtimeConfig.mode` 固定为 `mock` 并失败关闭,不能解释为真实后端已经联通。以下只记录页面源码当前主动读取的查询参数;上游传入但页面未读取的参数属于待审债务,不能写成有效合同。
-
-| 页面 | 当前主动读取的查询参数 |
-| --- | --- |
-| A01、A04、A05 | 无 |
-| G01 | `genealogyId`、`state` |
-| G03 | 无 |
-| G05 | `genealogyId`、`state` |
-| G06 | `mode`、`state` |
-| G08 | `genealogyId`、`source`、`state` |
-| G09 | `state`、`status` |
-| G10 | `genealogyId`、`state` |
-| G11 | `genealogyId`、`state` |
-| G12 | `genealogyId`、`state` |
-| T01 | `genealogyId`、`state`、`selectedId` |
-| T03 | `genealogyId`、`personId`、`state` |
-| T04 | `genealogyId`、`personId`、`mode`、`state` |
-| T05、T06 | `genealogyId`、`personId`、`state` |
-| T07 | `genealogyId`、`state` |
-| T08 | `genealogyId`、`personId`、`state` |
-| F01 | `genealogyId`、`state` |
-| F02 | `genealogyId`、`state` |
-| F03 | `genealogyId`、`feedId`、`state` |
-| F04 | `genealogyId`、`state` |
-| F05 | `genealogyId`、`articleId`、`state` |
-| F06 | `genealogyId`、`articleId`、`mode`、`state` |
-| F07 | `genealogyId`、`state` |
-| F08、F09 | `genealogyId`、`albumId`、`state` |
-| F10 | `genealogyId` |
-| R01 | `genealogyId`、`state` |
-| R02 | `genealogyId`、`mode`、`personId`、`state` |
-| R03 | `genealogyId`、`state` |
-| R04 | `genealogyId`、`mode`、`relativeId`、`state` |
-| R05 | `genealogyId`、`state` |
-| R06 | `genealogyId`、`ceremonyId`、`state` |
-| R07 | `genealogyId`、`mode`、`ceremonyId`、`state` |
-| R08、R09 | `genealogyId`、`personId`、`state` |
-| R10、R11 | `genealogyId`、`state` |
-| N01 | `genealogyId`、`state` |
-| N02 | `id`、`state` |
-| M01 | `state` |
-| M02—M08、M10 | 无 |
-| M09 | `state` |
-
-`state` 参数目前只用于直接加载页面时的本地状态审查,不代表后端请求字段;导航网关不注册也不会生成这个展示钩子。R 系列的 `count/saveResult/personName/giftId/ritualId` 已全部退役,人物名称和实体资料只能由受校验的复合身份从唯一只读 owner 取得。G03 的 `step/genealogyId`、G05 的 `mode/role/genealogyName`、G08 的 `previous/genealogyName` 以及 G12 的 `startGeneration/currentGeneration` 已从页面和注册表删除:页内步骤留在页面状态,名称按词法 `genealogyId` 从唯一 fixture 或后续领域数据取得,来源只由真实栈与受验证 `sourceKey` 表达。T03 初始 `personId` 是不可变宿主页路由身份,亲属浏览只改变页内活动成员和轨迹;因此当前 T05 本地预览必须以 `goBack()` 回到原实例,不得用活动成员重写 T03 URL。其余参数仍须在对应业务阶段判断为真实输入、页内状态、领域数据或删除项,不得把调试参数固化成接口合同。
-
-T01/T03—T08 当前共用 `data/mock.js` 的唯一成员夹具 owner:列表查询必须传 `genealogyId`,单成员查询必须同时传 `genealogyId/personId`,返回值与嵌套亲属均为快照。错误家谱下的已知成员、未知成员或缺失必填身份不得回退到 1001、首位成员或“待核实成员”;T04 只有 `mode=first` 且 `personId` 为空时可以建立首位成员草稿。该夹具只支撑当前本地设计流程,不代表后端字段已经完整;任务 18 接入真实接口时必须删除临时 owner 与选择器,而不是并存第二份成员合同。
-
-### 2.7 全局非功能门槛
-
-- 默认字号和约 `1.3` 倍系统字号下,超长谱名、生僻姓名、错误说明和主操作不得重叠或丢失关键含义。
-- 主要触控目标不小于约 `44dp`;点击后 `100ms` 内出现反馈,预计超过 `300ms` 的操作显示明确加载状态。
-- 长列表至少用 `500` 条 mock 数据验证分批渲染、稳定 key、刷新、分页、末项可达和返回现场恢复。
-- 同一详情连续进入和退出 `20` 次,并快速切换根页面、重复开关弹层;不得出现白屏、串状态、重复堆栈、残留遮罩或逐次变慢。
-- Android 性能以约 `4GB` 内存的中低端设备为底线,验证启动、键盘、长列表、图片解码、页面切换和系统返回手势。
-- 页面离开时清理本页创建的定时器、监听器、上传任务和动画状态;连续使用不得积累重复请求或实例。
-- 当前导航阶段已完成任务 1—10 的共享基础、组件、退役入口、认证、G、T、F、R、N/M 系列静态迁移和零债务门禁;A01/A04/A05 的 TAC 客户端、领域上下文与 M07 反馈客户端也已完成,MuMu 原生矩阵尚未执行。T01、认证与家谱工作区后端门禁并行等待外部合同关闭;跨页面领域数据持久化以工作区门禁为前置,本地先按无依赖业务域、全局文字层级和无障碍第二轮逐批推进,不得一次混合实施。
-
-### 2.8 G 系列第一轮接口差距账本
-
-本轮已逐页核对 G01、G03、G05、G06、G08—G12 与受保护双导出,并对照新线上 OpenAPI 做了第一轮差异检查;随后任务 26 又对 G01/G05 做了三人反向质询、部署探测与失败门禁,但没有在 schema owner 未定时把页面接到 `appApi`。所有 G 页面仍是本地交互预览,页面显示角色也只是 fixture 的最小权限投影,不代表服务端授权。以下问题在真实接入前必须由接口适配合同或后端同版本新导出关闭:
-
-- 公共边界:受保护旧双导出的家谱详情、列表和申请列表多为通用 `Object/ListResult`;新线上虽改为 `RListAppGenealogyVo/RAppGenealogyVo/RListGenealogyJoinApplyVo` 等类型化响应,但三个工作区模型均无 `required`。`AppGenealogyVo.genealogyId` 仍是 JSON `integer/int64`,合法最大值在 JavaScript 中不可逆失真;`roleType/status/memberStatus` 无 enum,且没有可直接用于 current context 的 `canView`。首批工作区只要求 `genealogyId/genealogyName/canView/canManage/canEditContent/roleType` 的最小闭包,不要求 22 个字段全部必填。`GET /genealogy/app/genealogies/quota` 虽已返回 `GenealogyQuotaVo`,它属于后续创建/加入写流程,不混入 G01/G05 只读批次。申请、用户、字辈等其他 int64 只在各自实际消费批次逐项关闭,不能用解析后 `String()` 冒充无损。
-- G03:任务 35 已完成三人专项审查。受保护旧双导出的 `GenealogyCreateBody` 与线上 `AppGenealogyCreateBody` 都只建谱,页面又缺可信 `regionCode`,通用人物 POST 不能保证唯一始祖或两写原子性。生产目标固定为最终按钮一次 `AppGenealogyBootstrapBody` 创建谱+OWNER+一世始祖+READY,使用 `/genealogy/app/region/search`、`GenealogyRegionCode`、`RegionSelectVo.selectable`、统一 `GenealogyAccessPreset`、词法 ID、Idempotency-Key 与无 PII operation-status;当前后端 `G03-BOOTSTRAP-OPENAPI-CONTRACT BLOCKED` 和客户端 `G03-BOOTSTRAP-CLIENT-RELEASE BLOCKED` 均为独立发布红灯,见 5.12。
-- G01/G05 只读工作区:`/mine` 是唯一可访问集合 owner,`/{genealogyId}/overview` 是 G05 唯一读取 owner,不同时调用语义重复的 `/{genealogyId}`。G01 必须在 `onShow` 或失效事件中取消旧请求并成功取得严格列表后才 reconcile;网络/5xx 不写撤权 tombstone。G05 在新请求前清旧数据并取消迟到响应,远端失败不回退 fixture。线上没有当前首屏用于确认来源和可信度的 `source/manager/certification/ancestorName/parentName/branchName/updatedAt/activeCount`;首批可以诚实隐藏或降级这些可选展示,若产品坚持保留则另补后端合同,不能让 fixture 成为真实详情。
-- G06:新线上公开搜索已经返回类型化家谱对象,但仍没有显式 `canApply`、六类关系字典、邀请码校验、邀请码目标解析或直接加入端点;未来必须由服务端返回可信的 `canJoinByInvite` 或等价结果,搜索申请资格不能代替邀请码资格,也不能信任 `source=invite` 查询参数。
-- G08:`GenealogyJoinApplyBody` 提供 `applicantName/phone/relationDesc/applyReason/inviterUserId`,当前页面的 `realName/relation/message` 仍需显式映射、手机号来源和必填规则确认;接口没有邀请码票据字段。搜索来源本地完成仅进入 G09 预览,邀请码来源本地完成仅回 G01,二者都不建立成员关系。
-- G09/G10:新线上我的申请和待审核列表已返回类型化申请行,但申请状态仍缺正式 enum/字典;真实撤回和审核必须携带服务端词法 `applyId`。线上审核体为 `{status,auditRemark}`,`status` 必填且匹配 `[12]`(1 通过、2 拒绝),`auditRemark` 最长 500;`utils/api.js` 已同步严格校验,旧 `{approved}` 路径已删除。当前本地 `LOCAL_WITHDRAWN` 和审核预览仍不得当成服务端状态。
-- G11:受保护旧双导出的 `GenealogyUpdateBody` 与线上 `AppGenealogyUpdateBody` 都有 `genealogyName/intro/visibility/joinMode`,且缺版本、If-Match、closed merge 与 typed 错误。任务 38 保留现有 PUT 为唯一 dirty-only owner,删除 generic GET/PATCH,复用 overview 的 `RAppGenealogyVo`,新增 `GenealogyName/GenealogyIntro/GenealogySettingsVersion` 与 409 三分支;G03 门禁只继续拥有共享 accessPreset 和旧 DTO/pair 删除,见 2.16/5.15。
-- G12:任务 39 已否决旧 `{poemText,disableMissing}`、collection POST、逐行 PUT、batch preview/save 与 management 多 owner,固定唯一 GET/PUT aggregate。请求改为显式 0—500 行 `{poemId?,generationNo,generationText}`+disableMissing,generationNo 唯一排序且声明严格升序;新行省略 ID,已有 ACTIVE ID 可显式移动,重复文字允许。false 保留遗漏 baseline、true 软停用,empty false no-op、empty true 清空 ACTIVE;服务端先校验声明严格升序,再构造完整 merged candidate,随后验证 ID/世代/slot/连续/最终容量并原子写,历史不物理删除。Unicode 精确为 NFC、1—50 code point 且拒绝控制/bidi/zero-width/孤代理。后端门禁仍有 72 项红灯,真实接入不得再依赖服务端 preview items 或猜批次首代,见 2.17/5.16。
-
-### 2.9 新线上 OpenAPI 差异与运行边界
-
-- 新运行基址为 `https://backend-api.ddxcjp.cn`,已经由 `utils/config.js` 唯一持有且无尾斜杠;当前仍保持 `mode: 'mock'`,不会让尚未接完的页面误打真实服务。线上文档的 `servers` 却仍生成 `http://backend-api.ddxcjp.cn`;客户端配置只能使用 HTTPS,后端需修正文档声明,不能让 H5 产生混合内容风险。
-- 本地 112 条路径中 109 条仍在线;旧 `/genealogy/app/files/reference`、`/genealogy/app/files/upload`、`/genealogy/pc/files/upload` 三条当前不在线,线上另有 613 条路径。任何上传与文件引用实现都必须先按新线上合同重新审查。
-- 线上把本地若干 `Genealogy*Body/View` 改为 `AppGenealogy*Body/Vo`,部分字段说明、响应包装和 operationId 也已漂移;现有离线测试只能证明受保护双导出内部的 G 系列快照,没有证明线上与旧快照一致。
-- 行为验证服务已能返回 `validToken`,短信发送体也强制接收它;但密码登录体没有票据字段。A01 密码登录、注册、忘记密码三条流程共用 TAC 是产品硬要求,后端必须明确各自 `sceneCode`、provider/captchaType、票据一次性消费与过期/重放/限流规则,以及密码登录如何强制校验。
-- 新线上文档的 `722` 条路径中没有任何 `/genealogy/app/v2/`,`507` 个 schema 中没有 `LineageGraphWindow/LineageOverview/LineageLocator` 或 `schemaVersion/treeVersion/familyUnits/edges/rootVisibility/ancestorPathSegments/affected*Ids` 等辨识字段,`LINEAGE_QUERY_INVALID/LINEAGE_FOCUS_NOT_AVAILABLE/TREE_VERSION_CHANGED/RELATIONSHIP_PATCH_EMPTY` 也全部不存在。`tests/lineage-openapi-contract.ps1` 已对受保护 JSON/YAML 建立聚合红灯并证明四条目标操作和三个固定根模型同时缺失,因此不能解除 `API-T01-001` 门禁,也不能开始任务 12。
-- 已验证 `http://localhost:5173` 对 `/captcha/challenge` 的预检允许 `POST`、`content-type`、`clientid` 和 credentials;正式 H5 域名、App 原生请求、错误码与限流仍须分别验证,不能用本次预检替代上线验收。
-
-### 2.10 认证与 TAC 后端缺口账本
-
-认证客户端批次已经完成,但 `runtimeConfig.mode` 继续固定为 `mock`;下列问题关闭、后端提供同版本双导出并完成真实联调前,客户端不得切换远端或宣称登录注册可上线:
-
-- `API-AUTH-TAC-001`:密码登录体尚无票据字段。后端必须让 `POST /genealogy/app/auth/login` 强制消费与短信发送相同安全语义、绑定 `APP_PASSWORD_LOGIN + tenant + client + canonical phone` 的短时单次票据。A01 已开放开发/联调 wire,但客户端先展示滑块不能充当服务端强制校验,故默认仍为 mock 且生产发布保持阻塞。
-- `API-AUTH-TAC-002`:2026-07-22 对真实 `APP_REGISTER` 请求只读联调时,`POST /captcha/challenge` 返回 HTTP 500 且响应体为空。后端必须修复并提供成功、无效场景、过期、限流和服务不可用的稳定错误 envelope;不得用客户端重试掩盖空 500。
-- `API-AUTH-TAC-003`:当前 `VerificationCheckBody` 未将 `providerCode/captchaType/payload` 全部声明为必填,根对象与 TianAi/SystemImage payload 也未关闭额外字段,且缺少以 evidence/provider 为 discriminator 的 `oneOf`。后端必须建立关闭额外字段的严格分支;客户端提交的 provider/type 不能替代 challenge 的服务端所有权。`tests/auth-tac-openapi-contract.ps1` 当前聚合六项结构缺口并输出 `AUTH-TAC-OPENAPI-CONTRACT BLOCKED`。
-- `API-AUTH-TAC-004`:验证码中心必须是唯一 owner。`/captcha/require` 返回服务端绑定 `tenant/client/scene/canonical subject/riskPolicyVersion` 的 `verificationSessionId`、允许方法和短时有效期;`required=false` 也必须直接返回可供短信端点原子消费的一次性 `validToken`。同一 session 只允许一个活动 challenge,刷新或切换方法立即作废旧题但不清零失败计数;`/captcha/verify` 只在服务端验证 evidence 并结合本地风险策略通过后签发票据,票据继续绑定 method/assurance/audience。`/sms/code` 必须在同一事务中完成 `ISSUED → CONSUMED` 与唯一短信 outbox 创建:相同幂等键返回原结果,并发或不同键重放不能创建第二个任务;跨手机号、场景、租户或客户端全部失败。
-- 无障碍不得成为降风控布尔开关:禁止 `accessibility=true`、`skipCaptcha`、检测 TalkBack 后放行、供应商故障时直接发短信,以及由客服绕过验证中心触发短信。P0 先落 provider-neutral 验证中心和支持屏幕阅读器、文字聊天/中继的可审计人工兜底;文字渠道只是通信媒介,各 `sceneCode` 仍须定义独立身份或号码控制证据。案件继承且不得改写原 session 的 subject/scene,具有去重、RBAC、主体/IP/设备/审核员限额、审计、服务时段、容量与 SLA,高风险找回或换号双人复核;坐席只提交决定,验证中心才可签票。异步案件和批准授权可在合理期限内恢复,用户重新进入原流程时才激活短时 `validToken`,避免通知前过期;不得要求用户证明残障。中国大陆非交互风控供应商只进入限时 POC,真实 UniApp Android WebView 必须证明 TalkBack、外接键盘、Switch Access、弱网、错误票据、误杀和攻击拦截门槛,达标后才可成为默认自动路径,不能预先宣称无障碍合规。只有此前在同一 subject 的已认证会话绑定私钥、服务端 nonce、RP/App 绑定、`userVerification=required`、短时单次且检查撤销的设备断言才可独立放行;普通设备指纹、完整性检测或仅 user-presence 只能加权,注册和未绑定设备不能使用。音频验证码必须另经可懂度、听障覆盖和 ASR 对抗 POC,不能单独上线或充当唯一替代。
-- 客户端当前只完成浮层壳层的对话语义、焦点进入/圈定/恢复、Escape/Android 返回、原生刷新/关闭、48px 目标与小视口滚动;第三方 TianAi 仍以指针拖动为主,不能据此宣称 TalkBack 可完成。`tests/auth-android-accessibility-release-gate.ps1` 在缺少非拖动等价路径与三人 MuMu 证据时固定输出 `ANDROID-AUTH-ACCESSIBILITY-RELEASE BLOCKED`。
-
-### 2.11 F 系列线上写合同与上传阻塞
-
-本节只记录 2026-07-22 从 `https://backend-api.ddxcjp.cn/v3/api-docs` 只读核对到的线上事实,不改写受保护的 `APP.openapi.yaml/json`,也不代表 F 页面已经接入写接口:
-
-- 动态:`AppFamilyFeedBody.feedContent` 必填且 `minLength=1`,其余字段为 `feedType`、`mediaOssIds`、`sortOrder int64`、`status`。`AppFamilyFeedCommentBody.commentContent` 必填,但文档边界为 `minLength=0/maxLength=1000`,另有可选 `parentCommentId int64`;空字符串虽然被模型允许,产品页仍可采用更严格的非空校验,但适配器不能把页面规则误写成服务端约束。
-- 谱文与相册:`AppArticleBody.articleTitle/articleContent` 必填且均为 `minLength=1`,`categoryId/coverOssId/sortOrder` 为 int64;`AppAlbumBody.albumName` 必填且 `minLength=1`,`coverOssId/sortOrder` 为 int64。所有 int64 标识在客户端边界继续以词法字符串保存,只有合同已经消除歧义的请求适配器才可编码。
-- 上传初始化:`SysOssResumableInitBo` 的 `uploadId/fileName/fileMd5/totalSize/totalChunks/chunkSize` 六项必填;`fileMd5` 匹配 `^[a-fA-F0-9]{32}$`,三个大小或分片数均要求正整数。初始化响应的即时命中分支 `SysOssResumableInitVo.ossId` 是 int64。
-- 分片与完成:chunk 要求 query `uploadId/chunkIndex/chunkMd5` 和 multipart `file`;complete 的 `SysOssResumableCompleteBo` 要求 `uploadId/fileName/fileMd5/totalSize/totalChunks`,MD5 与正整数边界同初始化。
-- 硬阻塞:complete 返回的 `SysOssUploadVo.ossId` 被声明为 string,而创建照片的 `AppAlbumPhotoBody.ossId` 必填且声明为 int64;两条成功路径对同一对象存储标识给出冲突类型。后端统一类型或明确无损转换责任并重新导出同版本文档前,客户端不得自行 `Number()`、不得提交照片创建,也不得显示上传成功。F09 因此只能保留明确的本地预览。
-
-### 2.12 R 系列线上接口与静态迁移边界
-
-三位评审者已经同时从接口字段、业务闭环、异常交互和视觉风险审查 R01—R11。以下是 2026-07-22 线上 OpenAPI 证据与 Task8 静态批次边界,不表示页面已经调用真实接口:
-
-- 人物:R01/R02 对应 `/genealogy/app/genealogies/{genealogyId}/lineage/persons` 与详情路径;搜索分页另有 `/page`,接收 `keyword/generation/personStatus` 和必填 `pageQuery`,返回 `TableDataInfoAppLineagePersonVo`。`AppLineagePersonBody` 只要求 `name`,页面旧 `role/legacy` 不是可靠请求字段;人物状态与写权限也没有正式字典或能力位。Task8 只复用树成员只读 owner,真实人物写入留到独立接口批次与 T01 v2 原子变更一并治理。
-- 人情往来:R03/R04 对应 `relative-records`,不是强制依赖 `ceremonyId` 的 ceremony gifts。请求只要求 `relativeName`,另有 `relationName/eventName/eventTime/giftAmount/recordContent/mediaOssIds`;模型没有收礼/送礼方向及金额币种语义,后端补齐或产品明确单向定义前不能声称完整礼账闭环。
-- 礼仪:R05—R07 对应 `ceremonies`,请求要求 `ceremonyTitle/ceremonyType`;`ceremonyType/status` 无正式枚举。邀请列表只有 `inviteeUserId/inviteStatus` 等字段,页面若展示姓名必须与同谱成员选项按用户 ID 受控联接,且“受邀人”不能直接写成“已参与者”。
-- 成长:R08 对应 `growth-records`,请求要求 `recordTitle`;页面必须额外强制 `lineagePersonId`,因为家谱级列表没有人物筛选参数。`recordType/status` 无枚举,不能据此在客户端发明分类。
-- 人生事:R09 没有独立线上端点,且 `growth-records.recordType` 没有枚举或人生事件值说明。后端提供正式合同前页面硬关闭,不读取、不写入、不展示 fixture 时间轴。
-- 备忘:R10 对应 `memos`,请求要求 `memoTitle`;`completed/status` 是无枚举字符串,也没有独立幂等切换端点或版本字段,Task8 禁止点击卡片本地翻转官方状态。
-- 功德:R11 对应 `merit-records`,请求要求 `donorName/meritTitle`;`meritType/status` 无枚举,`amount` 也没有币种、精度或非负边界。当前汇总只能来自只读列表,新增预览不得改变正式次数或金额。
-- 公共边界:上述接口都只说明“需要登录”,响应没有统一 `canCreate/canEdit/canDelete`;任何页面角色、创建人或 fixture 权限都不能冒充服务端授权。所有 int64 ID 保持词法字符串;未知实体、缺参、跨谱必须失败关闭。真实写接口未接入前,R 页只允许独立且明确未提交的本地预览,生产路由没有结果能力。
-
-### 2.13 N/M 系列线上接口与静态迁移边界
-
-三位评审者已同时核对页面流程、2026-07-22 线上 OpenAPI、异常交互和视觉风险。Task9 完成 N/M 安全导航与诚实静态边界;其后只有 M07 在独立 Task25 接入已核对的真实反馈 owner,其余页面仍未提前接入远端:
-
-- 消息:Task29 把 `GET /genealogy/app/notifications` 与 unread-count 固定为独立读取批次:无筛选列表完整返回当前账号最多 200 条活动通知、最新优先,计数精确覆盖同一集合;首版 adapter 只公开 `snapshotKey/title/content/publishedAt/unread`,N02 由当前内存 generation+ordinal key 读取完整正文。Task30 单独约束两个已读 POST 的字符串 ID、幂等与 read-all 截止点。当前受保护双导出缺 unread-count 和专用模型,线上又无 required/enum/容量、ID 为 int64 且匿名行为与文档冲突,因此两项门禁均为红灯,见 5.6/5.7。首批删除所有通用目标 CTA;后端没有闭合 `bizType` 目标字典前,客户端不猜路由且永不执行服务端 URL。
-- 个人资料:Task28 固定 `GET /genealogy/app/auth/profile` 为 M01/M02/M03 唯一读取 owner。首批 wire 只 required canonical `phone`;`nickName/realName/email` 未设置时省略,出现时分别满足 1—30、1—30、email 且 1—100。adapter 立即掩码手机号并丢弃 `userId/avatar/status` 等未消费字段,当前 `PROFILE-OPENAPI-CONTRACT BLOCKED`,见 5.5。Task31 保留 PUT 为唯一 dirty-only merge owner,只允许脏的三项资料;省略保持,realName/email 精确空串清空,`profileVersion+If-Match+409` 防并发覆盖,当前 `PROFILE-UPDATE-OPENAPI-CONTRACT BLOCKED`,见 5.8。头像与 M05 换绑继续各自独立。
-- 密码与手机:Task33 已判定 `PUT /genealogy/app/auth/password` 和登录/注册/找回共用的 32 位十六进制 MD5 不可上线;四条入口须原子迁移到 raw writeOnly、15—64 Unicode/NFC、blocklist/限速/慢哈希。M04 200 前撤销包括当前设备在内的 ALL access/refresh session;unknown 也清本机回 A01,崩溃窗口由无秘密的 sessionEpoch marker 关闭,当前 `PASSWORD-CHANGE-OPENAPI-CONTRACT BLOCKED`,见 5.10。Task34 又固定 M05 为 currentPassword 再认证+新号 `APP_PHONE_CHANGE` TAC/6 位 OTP;换绑发码必须走专用 SaToken operation,最终 200 前换号、消费 OTP、提升 epoch、撤销 ALL session并持久化旧号通知,当前 `PHONE-CHANGE-OPENAPI-CONTRACT BLOCKED`,见 5.11。M04/M05 都不伪提交。
-- 家谱创建:Task35 否决空谱+通用人物两写,固定 G03 最终按钮一次 atomic bootstrap;访问规则同版统一为 accessPreset,地区只提交 selectable 项的词法 code,结果未知按 operationKey 精确查询且本地不存始祖 PII。当前 `G03-BOOTSTRAP-OPENAPI-CONTRACT BLOCKED`,见 5.12;通过前不接宽松 create API。
-- 家谱设置:Task38 保留唯一 PUT 但收紧为原子 dirty-only merge,`/overview` 是 fresh baseline 唯一读取 owner;`GenealogySettingsVersion+If-Match+409` 与 T01/M02 并发模型一致,PUBLIC_APPLY 关闭时与普通申请准入串行化。当前 `G11-SETTINGS-OPENAPI-CONTRACT BLOCKED`,见 5.15;后端绿只允许开始客户端 TDD,不允许直接接页。
-- 字辈集合:Task39 固定唯一 `appGetGenerationPoemSet/appUpdateGenerationPoemSet`、`GenerationPoemSetVersion+If-Match`、完整候选与 `FRESH_GET_THREE_WAY_NO_AUTO_PUT`;浏览器预检由 `APP_GATEWAY_PREFLIGHT` 唯一声明。当前 `G12-GENERATION-POEM-OPENAPI-CONTRACT BLOCKED`,见 5.16;页面保持本地预览。
-- 帮助与反馈:M06 首批固定 `GET /genealogy/app/help-articles` 为完整列表唯一 owner,不调用详情、不消费 `helpId`;adapter 只允许投影分类、标题和纯文本正文,分类由当前列表动态派生。受保护双导出仍是通用 `ListResult/RList`,线上专用模型又缺 required、正文格式、仅发布和顺序语义,匿名行为也与文档 401 冲突,因此 `HELP-CENTER-OPENAPI-CONTRACT BLOCKED` 保持红灯,详见 5.4。`AppFeedbackBody.feedbackContent` 必填,`feedbackType/contactInfo` 可选且无 enum;M07 已由 `appApi.submitFeedback` 精确 POST `/genealogy/app/feedback`,调用方不能关闭认证头,只接受 HTTP 200 与整数成功 `code`。mock 模式不伪提交;成功、确定失败、结果未知和迟到输入已分离。两页真实服务与 MuMu 验收都等待认证远端门禁关闭。
-- 邀请:`GET /genealogy/app/promotions` 只返回推广内容与通用 `targetUrl`,没有家谱邀请码签发、校验、失效或直接加入端点,不能支撑产品邀请闭环。M08 已删除硬编码码值、剪贴板和海报伪能力,并显示不可用;未来只能接入“校验成功直接加入且不生成审核记录”的单一路径。
-- VIP 与订单:线上存在套餐和订单的查询/创建端点,但当前文档未闭合支付方式、价格精度、订单状态、重复下单、支付回调、退款与续费语义。M09 不读取查询参数、不生成演示订单并保持不可用,待独立支付合规审查后再开放。
-- 退出:Task32 固定 `DELETE /genealogy/app/auth/logout` 只撤销当前 bearer credential family,其他设备保持有效;同 client 的 active/revoked/expired 凭证重复调用都收敛为同一 200,非法/client 不匹配为 typed 401。客户端未来由唯一 logoutCoordinator 在同一同步段捕获 A、清本地并 bump epoch、用显式 A 启动不随 M10 卸载取消的请求,然后立即进入 A01;迟到结果不再 clear。当前本地/线上合同都缺 required、范围/幂等/no-store 与复用反例,`LOGOUT-OPENAPI-CONTRACT BLOCKED`,见 5.9。
-
-### 2.14 任务 36 普通加入申请合同边界
-
-普通申请唯一流程为 G06 鉴权搜索 → G08 普通申请 → G09 mine/撤回,以及 G10 pending/审核;邀请码成功后直接加入且不生成审核记录,另立后续批次。七个稳定 owner 为 `appSearchPublicGenealogies`、`appCreateGenealogyJoinApplication`、`appGetGenealogyJoinApplicationRequest`、`appListMyGenealogyJoinApplications`、`appWithdrawGenealogyJoinApplication`、`appListPendingGenealogyJoinApplications`、`appReviewGenealogyJoinApplication`。所有 genealogyId/applyId 使用词法字符串,三个列表使用绑定 actor/filter 的稳定 cursor、limit 1—50、无 total。
-
-搜索投影只保留识别家谱所需字段与单一 viewerState;mine 以 PENDING/APPROVED/REJECTED/WITHDRAWN discriminator 表达,只有拒绝分支必带申请人可见 rejectionReason;pending 精确为 `applyId/applicantName/relationDesc/applyReason?/submittedAt`,递归禁止 phone、user、inviter、auditor。申请体只含 `applicantName/relationDesc/applyReason?`,审核只含 APPROVE 或 REJECT+rejectionReason;统一 `JOIN_APPLICATION_TEXT_V1` 规范 NFC、边界空白和换行。
-
-Idempotency-Key/requestKey 共用 `GenealogyJoinApplicationRequestKey`:`gja.{13 位毫秒时间}.{22—43 位 base64url CSPRNG}`,600 秒接受窗、300 秒未来偏差、120 秒 PENDING 收敛;canonical scope 包含 method/path/genealogyId/tenant/account/client/body。状态 GET 纯读且只返回 PENDING/SUCCEEDED/FAILED_NO_COMMIT。撤回和审核都用 `WHERE status=PENDING` CAS;批准同事务创建唯一成员并写终态。静态 OpenAPI 只能锁定合同,真实唯一约束、零写、fencing、事务和 HTTP/CORS 仍须部署集成反例。
-
-当前 `tests/join-application-openapi-contract.ps1` 精确输出 `JOIN-APPLICATION-OPENAPI-CONTRACT BLOCKED`;旧 G-series/core-flow 不再拥有 APP 加入 schema。后端门禁前 G06/G08/G09/G10 不接远端。后续接线必须删除 G10 手机号、三处消息中心承诺、LOCAL_WITHDRAWN 和遗留 adapter,并补状态机、无障碍与 MuMu 矩阵。
-
-### 2.15 任务 37 邀请码签发与直接加入合同边界
-
-邀请与普通申请是两个独立 owner。六个稳定 operation 为活动票据列表、无 body 幂等签发、撤销、JSON body 安全解析(无票据消费/成员写,仅轮换短时 grant 摘要)、无 body 直接兑换和兑换状态查询。真实流程固定为 M08 管理票据,G06 输入原码→resolve 最小可信目标与短时 redemption token→明确确认“直接加入、不经审核”→redeem→status 收敛→刷新 `/mine`→安装 context→G01/G05;不再进入 G08,不提交姓名/关系/理由,不创建申请、审核记录、人物或亲属关系。
-
-首版票据固定单次、24 小时和至少 128 位随机量;原码只允许在 resolve body 与签发成功/同 key 600 秒恢复窗中出现,查找使用 HMAC,短时恢复使用隔离 KMS 密文。列表、撤销、兑换、status、错误、URL/query、导航、storage、日志/APM/分析均不得出现原码或 redemption token。签发 unknown 使用 `{sessionEpoch,genealogyId,requestKey,startedAt}` 重放原路径/key,不自动换 key;600 秒只限制不存在 key 的首次认领,已存在 key 在窗内返同码、窗后返同 ticket metadata+秘密不可恢复,不签第二码。resolve 可轮换一个 HMAC 摘要 grant但不消费票据,token 最多五分钟并绑定 tenant/account/client/ticket/version/genealogy/authorizationEpoch。
-
-兑换使用敏感 header 与 `gir` key,在一个事务中重验票据、grant、权限、READY、功能、账号资格与容量,完成 ACTIVE→CONSUMED CAS、唯一 MEMBER 和 SUCCEEDED receipt;FAILED_NO_COMMIT 保证票据未消费且成员未建。已有普通 PENDING 返回 `ACTIVE_PENDING_APPLICATION`,用户先去 G09 撤回,邀请流程不得暗改任务 36。当前 `tests/invite-ticket-openapi-contract.ps1` 精确输出 `INVITE-TICKET-OPENAPI-CONTRACT BLOCKED`;后端门禁前 M08 保持不可用、G06/G08 保持诚实预览,不接虚构接口。
-
-### 2.16 任务 38 G11 家谱设置版本化写入合同边界
-
-G11 全局唯一写 owner 保留 `PUT /genealogy/app/genealogies/{genealogyId}`,operationId 为全局唯一 `appUpdateGenealogySettings`;不新增 PATCH、`/settings` 旁路或递归引用设置 body/字段的第二写入口,并删除重复 generic GET。G11 只消费 workspace owner 门禁结论,每次进入 fresh 调用 `/{genealogyId}/overview` 建立 canonical baseline,不能信任路由、`/mine` 卡片、旧 G05 内存、roleType 或 fixture。overview 与 PUT 200 共用精确 `{code,data}` 的 `RAppGenealogyVo`,不建立第二套 settings snapshot。共享 `GenealogyName` 统一创建/更新/读取为非 null、NFC、无边界空白、无换行或控制字符的 1—24 Unicode code point;`GenealogyIntro` 为非 null 精确空串或规范 1—80,正文只允许内部 LF 并拒绝 CR/tab/其他控制字符,空串清空、省略保持;accessPreset 仍只引用 `GenealogyAccessPreset`。
-
-`AppGenealogySettingsUpdateBody` 关闭额外字段并只允许 1—3 个 `genealogyName/intro/accessPreset` 脏属性,服务端事务内重验管理权限并原子 merge;canonical no-op 返回当前 200、版本不升且无领域副作用。并发唯一使用 `AppGenealogyVo.settingsVersion` 和 required `If-Match`,body 不重复版本;版本以 `x-version-scope-fields` 锁定只随三个 canonical 设置实际变化。旧版本返回 typed 409 `GENEALOGY_SETTINGS_VERSION_CHANGED`+current `AppGenealogyVo`,不用 ETag/412;409 wrapper 只允许 discriminator+三个 exact local ref 分支。另两条 409 为 `GENEALOGY_NOT_READY` 与只在实际 `PUBLIC_APPLY→MEMBER_ONLY` 且有活动待审时返回的 `ACTIVE_PENDING_APPLICATIONS`;后者引导 G10、不自动处理申请,设置 PUT 与普通申请 POST 共同声明 `ATOMIC_SINGLE_WINNER` 并在事务内重验准入。
-
-unknown 不新增 status owner,也不持久含谱名/简介的 body。客户端冻结 baseline/dirty/version/sessionEpoch,网络、超时、408、取消、5xx 或畸形 2xx 后 fresh 读 overview 对账,不自动 PUT;目标值一致只说明当前事实,不能证明本次请求成功。成功后原子回填 canonical 模型,失效 mine/overview/公开搜索/预览缓存并重验 context。响应与 parameter/response/header/schema 解析只接受 exact local component ref,Cache-Control 由单值 enum 固定。当前 `tests/g11-settings-openapi-contract.ps1` 稳定输出 `G11-SETTINGS-OPENAPI-CONTRACT BLOCKED`、48 项;本批不建占位 client gate,后端绿后的第一项写操作必须是实际执行生产 normalizer/coordinator 的纯 Node 失败测试。
-
-### 2.17 任务 39 G12 字辈集合版本化保存合同边界
-
-G12 唯一 aggregate owner 为 `GET/PUT /genealogy/app/genealogies/{genealogyId}/generation-poems`,operationId 为 `appGetGenerationPoemSet/appUpdateGenerationPoemSet`;旧 collection POST、逐行 PUT、batch preview/save、management 及其 schema/response 同版删除,不引入 preview token、服务端 preview/status。两条 200 共用 ACTIVE-only `GenerationPoemSetSnapshot {genealogyId,poemSetVersion,items}`,按 generationNo 严格升序;GET 重验 canView,PUT 事务内重验 tenant、canEditContent、READY 和版本。
-
-`AppGenerationPoemSetUpdateBody` 精确 required `{items,disableMissing}`。声明行最多 500 且严格升序;已有行 poemId 必须来自 baseline ACTIVE,新行省略 ID,稳定 ID 可随显式 generationNo 移动。false 保留未声明 baseline ACTIVE,true 软停用遗漏项;空 false no-op,空 true 停用全部。服务端先执行 `VALIDATE_DECLARED_STRICT_ORDER`,再构造声明目标与 merged candidate,随后执行 ID/世代唯一、`GENERATION_SLOT_CONFLICT`、连续性、`VALIDATE_FINAL_ACTIVE_CAPACITY`、`ALLOCATE_UNIQUE_NEW_IDS` 及新 ID 非空/唯一/非 baseline 校验;swap 显式声明所有受影响行并原子成功或零写,历史不物理删除。generationText 可重复,但每项必须 NFC、1—50 Unicode code point、well-formed 且拒绝边界空白、控制/bidi/zero-width/孤代理。
-
-唯一并发 owner 为 `GenerationPoemSetVersion+If-Match`,body 不复制版本,不用 ETag/412;no-op 保持版本,ACTIVE 语义变化生成永不复用的新版本。unknown 以 baseline/version、declaredItems 和 disableMissing 构造 effective target,按 `FRESH_GET_THREE_WAY_NO_AUTO_PUT` fresh GET:existing 比较 ID+generation+NFC 文本,NEW 比较 generation+文本并要求返回 ID 新鲜;同基数且无额外 ACTIVE 行才相等。先执行 `CURRENT_EQUALS_TARGET_FIRST_NO_ATTRIBUTION`,只陈述当前事实;再判 old,否则 divergent,全部不自动 PUT。
-
-响应只允许 typed JSON、private/no-store,429 带 Retry-After;SaToken security 必须是 JSON 数组,clientid 非空。顶层 `x-app-gateway-policies.APP_GATEWAY_PREFLIGHT` 是唯一 CORS 声明 owner,精确包含 Authorization/Content-Type/If-Match/clientid、GET/PUT/OPTIONS、显式 origin allowlist 与 600 秒;发布仍须真实 OPTIONS/preflight。当前主门禁输出 `G12-GENERATION-POEM-OPENAPI-CONTRACT BLOCKED`、`Issues: 72`;zero issues seed 与严格大小写/ref/security/annotation 反例输出 `G12-GENERATION-POEM-OPENAPI-ADVERSARIAL-CONTRACT PASS`,Unicode 输出 `G12-GENERATION-POEM-UNICODE-RUNTIME-SMOKE PASS`。后端绿前 G12 保持本地预览;绿后第一项客户端写操作必须是可执行生产 normalizer/coordinator 失败测试,再原子删除 fixture/timer/本地成功和旧合同。
-
-### 2.18 任务 40 F01/F03 家族动态读取合同边界
-
-本批只拥有 F01 动态列表、F03 动态详情和正常一级评论读取。唯一 owner 为 `GET /genealogy/app/genealogies/{genealogyId}/feeds`、`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}`、`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments`,operationId 为 `appListFamilyFeeds/appGetFamilyFeed/appListFamilyFeedRootComments`;删除两个 `/page` GET。发布、点赞、评论/回复写、回复读与媒体文件读分别留给后续独立批次。受保护双导出和线上 3.1.0 当前仍有双 owner、int64、通用/开放 response;线上评论 DTO 还含手机号、业务用户 ID 和审核字段,故不得接页。
-
-`AppFamilyFeedReadItem` closed required `{feedId,feedContent,authorDisplayName,publishedAt,hasMedia}`,`AppFamilyFeedRootCommentReadItem` closed required `{commentId,commentContent,authorDisplayName,publishedAt}`。ID 均为 1—128 位词法字符串;正文非 null 且有界;publishedAt 为服务端生成的不可变 RFC3339;作者只返回授权展示名和非空退化文案。评论只含正常可见一级评论,不含 reply/删除占位/parent/level/status/审核字段。标题、标签、点赞和总评论数不是本批合同。`hasMedia=true` 时客户端在媒体读取合同前展示诚实占位,不泄露或解析 mediaOssIds,不把附件静默丢失。
-
-两个列表使用默认 20、范围 1—50 的 opaque cursor,无 total/pageNum。feed 排序为 `publishedAt:DESC,feedId:DESC_ORDINAL`,comment 为 `publishedAt:ASC,commentId:ASC_ORDINAL`;`UPPER_BOUND_KEYSET_LATEST_VISIBLE` 只固定上界并排除刷新前的新头部内容,后续删除/隐藏项省略、可见编辑返回该页读取时的最新内容,不宣称 MVCC snapshot。cursor 绑定 actor/session/client、谱/动态、projection/order/limit/windowUpperBound/lastTuple;每页重验 tenant、membership、feed 归属与可见性,篡改/过期 typed 400,错谱、跨主体、撤权、删除或隐藏统一 `404 FAMILY_FEED_NOT_AVAILABLE`。
-
-三个 GET 精确 200/400/401/404/429/500 typed JSON,全部 private/no-store,429 带 Retry-After,required SaToken/clientid 并复用 `APP_GATEWAY_PREFLIGHT`。当前 `tests/family-feed-read-openapi-contract.ps1` 输出 `FAMILY-FEED-READ-OPENAPI-CONTRACT BLOCKED`、`Issues: 85`;zero issues 合法种子和 58 个 ref/大小写/PII/int64/offset/HTTP/cache 变异由 `tests/family-feed-read-openapi-adversarial-contract.ps1` 证明为 `FAMILY-FEED-READ-OPENAPI-ADVERSARIAL-CONTRACT PASS MUTANTS=58`。后端绿前保持复合身份 fixture,禁止连接 dormant 宽 `getFeeds` 或失败回退 fixture。后端同版本 JSON/YAML/live 通过后,客户端首写先建立直接执行生产 read normalizer/coordinator 的失败测试,再原子迁移 F01/F03 和无障碍/异常状态。
-
-## 三、52 个活动页面映射
-
-表中“返回或完成目标”描述业务意图,不表示现有导航 API 已经正确;导航栈阶段需要用源码扫描、测试和 MuMu 完整流程逐项验证。A04、G 系列第一轮、F 系列当前写边界、T01 和新线上差异已形成专项证据;其余接口列继续标记“待对应业务阶段 OpenAPI 审查”,避免把旧思维导图、页面 mock、旧离线快照或 PC 接口误当成当前 App 合同。
-
-| 编号 | 页面 | 路由 | 当前业务目标 | 主要进入方式 | 返回或完成目标 | 必测状态 | 接口业务域 | 当前接口核对状态 |
-| --- | --- | --- | --- | --- | --- | --- | --- | --- |
-| A01 | 登录 | `pages/auth/a01-entry` | 完成密码/短信认证并处理协议;微信待合同关闭 | APP 启动、凭证失效、主动退出 | 成功进入 G01;取消或失败留在本页 | 密码、短信、协议错误、TAC、发送中、倒计时、请求取消、登录失败、凭证过期 | 认证与账户 | 密码登录线上 wire 与 `AppLoginVo.access_token` 已接入,默认 mock;`validToken` 未由登录接口消费,`API-AUTH-TAC-001` 仍阻止生产发布,见 2.10 |
-| A04 | 注册账号 | `pages/auth/a04-register` | 建立新账号并确认协议 | A01 注册入口 | 成功建立登录态并进入 G01;取消返回 A01 | 本地校验、TAC、短信、注册中、手机号占用、成功、失败、取消 | 认证与账户 | `APP_REGISTER`、4 位码、`RAppLoginVo → AppLoginVo.access_token` 客户端链已落地;真实 challenge 与 OpenAPI 仍红灯,见 2.10 |
-| A05 | 重设密码 | `pages/auth/a05-reset-password` | 验证手机号并设置新密码 | A01 忘记密码 | 成功返回 A01 的密码登录态;取消返回 A01 | 4 位码、TAC、密码策略、不一致、提交中、成功、失败、取消 | 认证与账户 | `APP_FORGOT_PASSWORD` 客户端链已落地;真实后端、Android 可访问替代与 MuMu 仍红灯,见 2.10 |
-| G01 | 我的家谱 | `pages/genealogy/g01-my-genealogies` | 选择全局家谱并完成加入或创建分流 | 登录成功、根 Tab、业务完成回流 | 进入 G03、G05、G06、G09、G10、G12、T01 或 N01 | 正常、空、加载、失败、审核中、被拒绝、退出或移除、切换弹层、未读消息 | 家谱、成员关系与通知计数 | Task26 工作区红灯已建立;`/mine` 尚未接远端,见 2.8/5.3;Task29 unread-count 红灯要求与 M01 共用唯一未读数 owner,见 2.13/5.6 |
-| G03 | 创建家谱 | `pages/genealogy/g03-create-genealogy` | 在同页收集家谱与始祖并最终原子创建 | G01 创建入口 | 门禁前进入 G05 本地预览;生产成功按 receipt→mine cache→context→G05 唯一次序收口,放弃零写 | 地区加载/失败、重复建议、始祖校验、提交中、PENDING、结果未知、fatal/quarantined、已提交待进入、放弃确认 | 家谱与成员关系 | Task35 已建立 atomic bootstrap、无 PII operation-status、统一 accessPreset、APP 可信地区与词法 ID 的后端/客户端双红灯;开放还依赖 Task26 workspace 与 MuMu,见 2.8/5.12 |
-| G05 | 家谱总览 | `pages/genealogy/g05-genealogy-overview` | 按公开预览、成员、所有者或本地预览浏览身份、来源和可信度 | G01、G06、G09、G03 本地预览 | 返回实际来源;按权限进入 T01、G08、G10、G11、G12 或 F01 | 公开预览、成员视图、所有者、本地预览、加载、空、失败、无权限 | 家谱与权限 | Task26 选定 `/overview` 为唯一 owner;最小 schema、对象级授权和错误语义未关闭,丰富首屏字段另待取舍,见 2.8/5.3 |
-| G06 | 加入家谱 | `pages/genealogy/g06-search-genealogies` | 普通搜索,或解析邀请码后明确确认并直接加入 | G01 空态或添加家谱弹层 | 普通搜索按 viewerState 进入 G05/G08/G09;邀请成功刷新 workspace/context 后进入 G01/G05 | 搜索六关系;邀请码输入、格式错、解析、目标、确认、PENDING/unknown、已加入、普通申请冲突、失效、限流 | 普通搜索与独立邀请 | Task36 搜索见 2.14/5.13;Task37 六 operation 邀请红灯见 2.15/5.14,门禁前不接远端 |
-| G08 | 关系确认与入谱 | `pages/genealogy/g08-join-application` | 只提交普通加入申请;真实接线时删除全部 invite source | G06、G05 或 G09 的普通申请入口 | 普通申请成功刷新 G09 | 不可申请、字段校验、PENDING、unknown、成功、失败、放弃 | 普通加入申请 | Task36 后端红灯见 2.14/5.13;Task37 明确邀请不得进入 G08,现有 invite 预览待接线时原子删除 |
-| G09 | 我的申请 | `pages/genealogy/g09-my-applications` | 查看四状态申请并撤回或重新申请 | G01、G08、G06 审核中 | 已通过进入 G05;拒绝/撤回可重新申请;unknown 刷新 mine | 列表、空、失败、待审、通过、拒绝、撤回、重新提交 | 加入申请 | mine 四状态、拒绝原因和撤回 CAS 由 Task36 门禁拥有;消息中心承诺待接线时删除 |
-| G10 | 入谱审核 | `pages/genealogy/g10-application-review` | 审核不含手机号的 pending 最小投影 | G01 或 G05;首版不承诺通知目标 | 审核后刷新 pending;行消失只称状态变化 | 列表、空、失败、通过确认、拒绝原因、提交中、无权限、竞态冲突;拒绝字段保留 `aria-describedby`、错误关联与失败聚焦 | 加入审核与权限 | Task36 固定 APPROVE/REJECT、PENDING CAS 与事务权限重验;手机号节点待接线时原子删除 |
-| G11 | 家谱设置 | `pages/genealogy/g11-genealogy-settings` | 门禁前本地维护;生产目标原子更新名称、访问预设和简介 | G05 管理入口,进入后 fresh overview 鉴权 | 门禁前只更新本页预览;生产成功 canonical 回填、刷新缓存/context 后回 G05 或撤权回 G01 | loading、dirty、saving、validation、saved、unknown 对账、三类 409、无权限、认证失效、不可用、未保存返回 | 家谱设置与权限 | Task38 已建立唯一 merge PUT、settingsVersion/If-Match、409 three-way、待审串行化与 unknown 红灯;页面尚未接远端,见 2.16/5.15 |
-| G12 | 字辈诗 | `pages/genealogy/g12-generation-poems` | 分批浏览并本地维护完整字辈序列 | G01 快捷入口或 G05 | 门禁前保存只更新本地列表;生产成功 canonical 回填并刷新消费者 | loading、空、编辑、校验、saving、saved、unknown、版本/READY 冲突、无权限、0/1/500×50、swap、软停用历史 | 字辈与权限 | Task39 已建立唯一 GET/PUT、poemSetVersion/If-Match、完整候选集合、unknown 与 CORS owner 红灯;页面尚未接远端,见 2.17/5.16 |
-| T01 | 世系树 | `pages/tree/t01-tree-overview` | 以当前成员为焦点阅读可扩展世系窗口,并在图、概览和线性列表间定位成员 | G01 快捷入口或 G05 | 返回来源;进入单实例 T03、T04、T06、T07 | 上二代/下二代初始窗口、搜索、四级 LOD、多配偶联合点、宽支系聚合、代际缺口、四类边界、图/列表、空、失败、版本冲突、500 节点性能;节点与线由同一 Canvas/矩阵/帧绘制 | 世系与成员 | 专项已核对:现有递归 `LineagePersonTreeView` 不满足;待后端按规范图窗口问题单更新 Apifox |
-| T03 | 成员档案 | `pages/tree/t03-member-profile` | 在单个原生页面实例内查看成员资料、亲属与受控状态 | T01、T07、R02 的成员关联 | 页内成员轨迹优先返回;轨迹结束后回实际来源;进入 T05、T08 | A→B→C→B→A 页内轨迹、可编辑、隐私、无权限、成员缺失、加载失败、离世状态;读取成功后才推进轨迹 | 成员档案与权限 | 待对应业务阶段 OpenAPI 审查 |
-| T04 | 新增亲属 | `pages/tree/t04-add-relative` | 录入首位成员或为目标成员新增亲属 | T01 指定节点或空树入口 | 当前只生成“尚未提交服务器”的本地预览,确认放弃后无结果回 T01;真实写成功后才定位新成员 | 首位成员、普通亲属、关系选择、必填、长摘要、保存中、本地预览、失败、放弃确认 | 成员与亲属关系 | 待对应业务阶段 OpenAPI 审查 |
-| T05 | 编辑成员 | `pages/tree/t05-edit-member` | 修改指定成员身份和生平资料 | T03 编辑入口 | 当前本地预览确认放弃后用 `goBack()` 回原 T03 实例且不产生结果;真实写成功后才刷新当前活动成员 | 加载、字段校验、长简介、保存中、本地预览、失败、无权限、放弃确认 | 成员档案与权限 | 待对应业务阶段 OpenAPI 审查 |
-| T06 | 编辑关系 | `pages/tree/t06-edit-relationship` | 校正两个现有成员之间的关系 | T01 关系操作 | 当前只生成“尚未提交服务器”的本地预览,确认放弃后无结果回 T01;真实写成功后才刷新关系 | 成员选择、校验、冲突、循环关系、冲突规则弹窗、保存中、本地预览、失败、无权限 | 亲属关系与权限 | 待对应业务阶段 OpenAPI 审查 |
-| T07 | 成员目录 | `pages/tree/t07-member-directory` | 搜索、筛选并选择家谱成员 | T01 成员目录入口 | 进入 T03;返回 T01 并恢复目录现场 | 完整列表、筛选、搜索无结果、明确空态、失败重试、加载、长列表、成员选择 | 成员查询 | 待对应业务阶段 OpenAPI 审查 |
-| T08 | 成员状态 | `pages/tree/t08-member-states` | 解释成员隐私、纪念或无权限状态 | T03 人物状态入口 | 返回 T03;家谱不可用时回 G01 | 隐私隐藏、离世纪念、无权限、无效成员、权限变化 | 成员状态与权限 | 待对应业务阶段 OpenAPI 审查 |
-| F01 | 家族动态 | `pages/family/f01-family-feed` | 按当前成员家谱展示动态并承载内容和档案入口 | 根 Tab 或 G05 | URL 已规范化后进入 F02—F04、F07、F10、R01、R03、R05、R10、R11 | 加载、列表、空、失败、无有效家谱、跨谱失败关闭 | 家族内容聚合 | Task40 已建立唯一 cursor GET、无 PII 投影、逐页鉴权与非泄露 404 红灯;后端绿前保持 fixture,见 2.18/5.17 |
-| F02 | 发布动态 | `pages/family/f02-publish-feed` | 编辑文字或媒体动态的本地预览 | F01 发布入口 | 预览不发布、不产出结果;取消保留或确认放弃后回同一 F01 | 表单、空内容校验、长内容、媒体权限、本地预览、无权限、放弃确认 | 动态发布与上传 | 线上写请求要求 `feedContent` 且 minLength=1,另有 `feedType/mediaOssIds/sortOrder/status`;真实调用与媒体上传未启用,mock 以 `WRITE_UNAVAILABLE` 失败关闭,详见 2.11 |
-| F03 | 动态详情 | `pages/family/f03-feed-detail` | 按 `genealogyId + feedId` 阅读动态并编辑评论草稿 | F01 动态卡 | 评论只在本页预览,不插入、不计数、不清空;返回同一 F01 | 加载、正常、内容失效、失败、评论校验、本地预览、无权限 | 动态与评论 | Task40 已拆分详情与一级评论 cursor owner;后端绿前保持 fixture,评论写仍只做未提交预览,见 2.18/5.17 |
-| F04 | 谱文列表 | `pages/family/f04-article-list` | 按家谱分类、搜索和浏览谱文 | F01 谱文入口 | 进入精确 F05 或 create 模式 F06;返回同一 F01 | 加载、列表、分类、搜索无结果并重置、空、失败、长列表、新建权限 | 谱文 | 任务 7 已核对线上列表及写接口;当前列表由唯一只读 owner 提供深拷贝 |
-| F05 | 谱文详情 | `pages/family/f05-article-detail` | 按 `genealogyId + articleId` 阅读并按权限进入编辑 | F04 谱文卡 | 返回同一 F04;有权限进入 edit 模式 F06 | 加载、正常、收藏暂未开放、编辑、失效、隐私、失败、无权限 | 谱文与权限 | 线上未证明收藏合同,当前禁用收藏;文章写请求要求 `articleTitle/articleContent` 且均为 minLength=1,详见 2.11 |
-| F06 | 编辑谱文 | `pages/family/f06-article-editor` | 新建或编辑谱文的本地预览 | F04 新建或 F05 编辑 | create 回 F04,edit 回精确 F05;预览不保存、不产出结果 | 新建、编辑、校验、加载、本地预览、失败保留、长正文、放弃确认 | 谱文编辑 | 线上 POST/PUT 已存在,`categoryId/coverOssId` 为 int64;真实调用未在导航批次启用,详见 2.11 |
-| F07 | 相册列表 | `pages/family/f07-album-list` | 按家谱浏览相册并制作独立的新相册预览 | F01 相册入口 | 正式相册进入 F08;本地预览不插入列表;返回同一 F01 | 加载、列表、长列表、空、失败、创建弹窗、本地预览、校验、权限、放弃确认 | 相册 | 线上创建要求 `albumName`;当前不调用写接口、不伪增列表或计数 |
-| F08 | 相册详情 | `pages/family/f08-album-detail` | 按 `genealogyId + albumId` 浏览照片墙和相册信息 | F07 相册卡 | 先关闭照片预览,再返回 F07;进入同一相册的 F09 | 加载、照片墙、末张预览、Android 返回先关预览、空相册、相册失效、失败、权限 | 相册与媒体 | 任务 7 已核对;当前严格按复合身份读快照,未知或跨谱相册不回退首条 |
-| F09 | 上传照片 | `pages/family/f09-media-upload` | 选择照片并填写批量及逐张说明的本地预览 | F08 添加照片入口 | 预览不上传、不生成成功态;取消确认放弃后回同一 F08 | 初始、权限、最多九张、增删、独立说明、必填、本地预览、放弃确认、无效相册 | 媒体上传 | 旧 `/files/upload` 已下线;resumable init/chunk/complete 的 complete 返回 `ossId` 为 string,而照片创建要求 int64;后端消除类型冲突前不得转换或提交,详见 2.11 |
-| F10 | 家族视频 | `pages/family/f10-video-list` | 按有效家谱说明当前视频服务尚未开放 | F01 视频入口 | 当前只返回同一 F01 | 待开放、无效家谱、返回 F01;未来能力不冒充当前功能 | 视频服务 | 任务 7 未发现可支撑当前页面闭环的已启用视频产品合同,保持关闭 |
-| R01 | 人物录 | `pages/records/r01-people-list` | 按当前家谱搜索和浏览人物只读快照 | F01 人物录入口 | 进入带精确家谱与模式的 R02;返回 F01 | 加载、列表、搜索、无结果、空、失败、分页、跨谱失败 | 人物记录 | 任务 8 已核对 `lineage/persons/page`;ID 必须保持词法字符串,真实分页尚未接入 |
-| R02 | 人物详情 | `pages/records/r02-person-detail` | 查看人物或制作不写库的新建/编辑预览 | R01 人物卡或预览入口 | 预览不产出结果;进入 R08 或硬关闭的 R09;取消回来源 | 查看、新建、编辑、校验、预览、隐私、失效、跨谱 | 人物记录与权限 | 任务 8 已核对 `AppLineagePersonBody`,`name` 必填;真实写入未启用,权限字典待补 |
-| R03 | 贺礼簿 | `pages/records/r03-gift-list` | 浏览同谱人情往来只读快照 | F01 贺礼簿入口 | 进入携带 `relativeId` 的 R04;返回 F01 | 加载、列表、空、失败、跨谱 | 人情往来 | 任务 8 已核对 `relative-records`,不是 ceremony gifts;收礼/送礼方向语义仍缺 |
-| R04 | 贺礼编辑 | `pages/records/r04-gift-editor` | 查看往来记录或制作不写库的本地预览 | R03 记录或预览入口 | 预览不插入列表、不删除记录;取消回来源 | 查看、新建、编辑、校验、本地预览、无效实体、跨谱 | 人情往来与权限 | 任务 8 已核对 `relativeId` 与 `relativeName` 必填;真实写入未启用,只允许本地预览 |
-| R05 | 礼仪列表 | `pages/records/r05-ritual-list` | 浏览同谱礼仪活动只读快照 | F01 礼仪入口 | 进入 R06 或 R07 预览;返回 F01 | 加载、列表、空、失败、活动展示、跨谱 | 礼仪活动 | 任务 8 已核对 ceremonies,`ceremonyTitle/ceremonyType` 必填且类型、状态无正式枚举 |
-| R06 | 礼仪详情 | `pages/records/r06-ritual-detail` | 查看精确礼仪与受邀人快照 | R05 活动卡 | 返回 R05;进入同一礼仪 R07 | 加载、详情、受邀人、失败、失效、跨谱 | 礼仪活动与邀请 | 任务 8 已核对 invitations;姓名需与成员选项受控联接,不能把受邀者冒充参与者 |
-| R07 | 礼仪编辑 | `pages/records/r07-ritual-editor` | 制作新建或编辑礼仪的本地预览 | R05 预览入口或 R06 编辑入口 | create 预览回 R05,edit 预览回原 R06;不产出结果 | 新建、编辑、校验、本地预览、无效实体、跨谱 | 礼仪活动与权限 | 任务 8 已核对 `ceremonyId`;必填与枚举见 R05,真实写入未启用 |
-| R08 | 成长日志 | `pages/records/r08-growth-journal` | 按同谱人物展示成长快照并制作独立预览 | R02 或 T03 人物入口 | 预览不插入正式时间轴;返回实际人物来源 | 加载、时间轴、空、失败、预览弹窗、必填、跨谱 | 人物成长记录 | 任务 8 已核对 growth-records;客户端必须强制 `lineagePersonId`,`recordType` 无枚举 |
-| R09 | 人生事 | `pages/records/r09-life-events` | 明确说明人生事件服务当前不可用 | R02 或 T03 人物入口 | 不读取或写入成长记录;安全返回人物来源 | 接口缺失、无效人物、返回来源 | 人生事件 | 任务 8 已核对:没有独立人生事件接口,后端补端点或正式类型字典前硬关闭 |
-| R10 | 家族备忘 | `pages/records/r10-memo-list` | 浏览同谱备忘快照并制作独立预览 | F01 备忘入口 | 预览不插入列表、不切换正式完成状态;返回 F01 | 加载、列表、空、失败、预览、跨谱 | 家族备忘 | 任务 8 已核对 memos,`memoTitle` 必填而 `completed` 无枚举,真实切换未启用 |
-| R11 | 功德记录 | `pages/records/r11-merit-records` | 浏览只读汇总并制作独立贡献预览 | F01 功德录入口 | 预览不改变正式汇总或列表;返回 F01 | 加载、汇总、列表、空、失败、预览、跨谱 | 功德与贡献 | 任务 8 已核对 merit-records,`donorName/meritTitle` 必填,类型、状态与金额边界无枚举 |
-| N01 | 消息中心 | `pages/notification/n01-message-center` | 展示当前账号完整活动通知快照与服务端读状态,不猜业务目标 | G01 或 M01 消息入口 | 以当前内存 `snapshotKey` 进入 N02;返回来源 | 加载、未读、已读、空、失败重试、认证失效、长内容、并发刷新 | 消息与通知 | Task29 读取红灯已建立;完整活动集合、专用 required、纯文本、时区、二值状态和计数同域待关闭,见 2.13/5.6;Task30 前不得本地伪写 |
-| N02 | 消息详情 | `pages/notification/n02-message-detail` | 从当前 generation 的内存快照展示完整纯文本正文,不持有服务端 ID | N01 消息卡 | 返回 N01;无快照时提示从消息中心重新打开,不跳业务页 | 加载、详情、无快照、认证失效、长正文、读状态写入待开放 | 消息与通知状态 | Task29 选定 list-owned snapshot 且删除目标 CTA;Task30 独立约束私有字符串 ID 与幂等写入,见 2.13/5.6/5.7 |
-| M01 | 我的 | `pages/profile/m01-profile-home` | 展示脱敏账号身份并保持通知、服务与设置入口可达 | 根 Tab | 进入 M02、M03、M06、M08、M09、M10 或 N01 | 身份与通知局部加载、正常、失败重试、认证失效、未读数不可用、服务可用性 | 个人中心聚合 | Task28 profile GET 红灯保证身份失败不锁菜单,见 2.13/5.5;Task29 unread-count 红灯删除 fixture 伪数并统一“未读消息”,见 2.13/5.6 |
-| M02 | 个人资料 | `pages/profile/m02-edit-profile` | 从唯一 profile owner 初始化并以版本化 dirty-only merge 保存昵称、真实姓名和邮箱 | M01 资料入口 | 成功应用权威响应并留在本页;放弃确认后回 M01 | 加载、失败重试、认证失效、异步 baseline、字段校验、保存、结果未知、版本冲突、账号切换、头像未接入 | 用户资料 | Task28 读取红灯仍是前置;Task31 已建立 PUT merge、清空、If-Match、typed response 和 409 红灯,头像不混入,见 2.13/5.5/5.8 |
-| M03 | 账号与安全 | `pages/profile/m03-security-settings` | 展示密码入口与脱敏绑定手机号,不伪造设备安全结论 | M01 安全入口 | 进入 M04 或 M05;返回 M01 | 手机号局部加载、正常、失败重试、认证失效、功能受限 | 账号安全 | Task28 已建立 profile GET 红灯;普通读取失败不得阻断密码入口,设备状态仍无合同,见 2.13/5.5 |
-| M04 | 修改密码 | `pages/profile/m04-change-password` | 以当前密码重新认证并安全更新统一密码凭证;门禁前保持本地预览 | M03 密码入口 | 确定错误留页;200/401/409/结果未知清本机并回 A01;放弃确认回 M03 | 空字段、15/64 边界、Unicode/NFC、blocklist、当前错误、并发、限流、提交中、结果未知、进程终止 | 账号安全与会话 | Task33 已建立 raw writeOnly、ALL 会话撤销、typed 错误与 session marker 红灯;四条密码 wire 必须同批迁移,见 2.13/5.10 |
-| M05 | 修改手机号 | `pages/profile/m05-change-phone` | 以当前密码重新认证,并通过受保护 TAC/6 位 OTP 验证新号码;门禁前保持本地预览 | M03 手机号入口 | 确定错误留页;最终 200/401/409/结果未知清本机回 A01;放弃确认回 M03 | 当前密码、新号、TAC、发送与倒计时、6 位码、占用、限流、提交中、并发、结果未知、进程终止 | 账号安全、短信与会话 | Task34 已建立专用 SaToken 发码、全活动六位码、ALL 会话撤销、outbox 与 credential marker 红灯;依赖 M04 raw wire,见 2.13/5.11 |
-| M06 | 帮助中心 | `pages/profile/m06-help-center` | 从完整帮助列表搜索、分类并展开纯文本正文,无法解决时进入反馈 | M01 帮助入口 | 返回 M01;无法解决时进入 M07 | 加载、服务端空、分类、搜索无结果、展开、失败重试、认证失效、取消 | 帮助内容 | Task27 选定列表唯一 owner 并建立红灯;专用 required、纯文本、仅发布、顺序和认证语义待后端关闭,见 2.13/5.4 |
-| M07 | 意见反馈 | `pages/profile/m07-feedback` | 通过唯一真实 owner 提交必填内容及可选类型、联系方式 | M06 联系入口 | 成功留页保留提交快照;编辑后可再提交;未提交修改放弃确认回 M06 | 必填、提交中、成功防重、失败、结果未知、mock 不可提交、未保存返回 | 用户反馈 | Task25 已接 `POST /genealogy/app/feedback` 严格客户端;remote 实测与 MuMu 待认证门禁关闭,见 2.13 |
-| M08 | 邀请家人 | `pages/profile/m08-promotion` | 从 workspace 选择有正式邀请权限的家谱并管理单次活动票据 | M01 推广入口 | 签发、显示/复制/系统分享、撤销;返回 M01 | 加载、无权限、无票据、签发/unknown、原码恢复窗、即将过期、撤销/竞态、权限失效 | 家谱邀请与系统分享 | Task37 六 operation 邀请红灯见 2.15/5.14;通过前保持不可用且不展示假码 |
-| M09 | VIP 与订单 | `pages/profile/m09-vip-orders` | 展示基础说明并明确订单服务当前不可用 | M01 服务入口 | 查看关闭说明;返回 M01 | 服务未开放、无订单数据、说明弹层 | 服务权益、订单与支付 | 套餐/订单端点存在但支付闭环未定义,已删除查询参数演示订单,见 2.13 |
-| M10 | 关于家谱 | `pages/profile/m10-about-settings` | 从 manifest 展示版本和协议说明,并安全退出当前设备凭证族 | M01 设置入口 | 协议/退出取消留在本页;确认后立即清本机并回 A01,远端结果只更新一次性提示 | 版本、协议、隐私、退出确认、双击、pending、撤销确认/未确认/拒绝、账号竞态、根导航失败 | 配置、协议与认证 | Task9 已完成本机清理基线;Task32 已建立当前凭证族、幂等 200、logoutCoordinator、required RVoid 与部署复用红灯,见 2.13/5.9 |
-
-## 四、封存与已移除页面
-
-| 页面 | 当前决定 | 合同边界 |
-| --- | --- | --- |
-| A02 账号登录 | 已完整并入 A01,不保留兼容路由 | 任何注册、重设或退出后的登录目标统一指向 A01 |
-| A03 | 已移除 | 不恢复无明确业务职责的历史入口 |
-| A06 登录状态 | 源码保留、活动路由封存 | 未来只有账号冻结、停用或风险限制等无法继续登录的阻断状态,且产品重新确认独立页面后才能恢复 |
-| G02 | 并入 G01 空状态 | 搜索、邀请码加入和创建三个入口由 G01 空状态承载 |
-| G04 | 并入 G03 始祖步骤 | 创建家谱与录入始祖属于同一可恢复流程 |
-| G07 | 并入 G06 | 搜索、筛选、结果与无结果均由 G06 双模式承载 |
-| T02 | 并入 T01 | 世系阅读提示、空态和失败态不再拆分独立路由 |
-
-## 五、后续接口审查填充规则
-
-每个对应业务阶段都必须先解析并比对两份 OpenAPI 导出,再按三人独立首审、交叉补漏、反向质询和共同收敛的顺序更新本文件。每个页面和用户操作都要补齐以下事实:
-
-1. 接口分类:App 可直接使用、PC 专用、App/PC 可能共用待确认、App 合同不完整、App 缺失、页面无合理用途或双方需重定义。
-2. 精确合同:路径、方法、鉴权、请求参数、字段类型、必填性、可空性、枚举、响应模型和错误码。
-3. 数据行为:分页、排序、筛选、上传、幂等、防重复提交、并发冲突、权限和数据副作用。
-4. 页面结果:成功、失败、取消、返回、完成、来源页刷新、重复进入和目标数据过期时的表现。
-5. 证据与状态:OpenAPI 位置、页面与代码位置、MuMu 操作步骤、三人结论、后端问题编号和关闭条件。
-
-接口问题不能只写“缺接口”或“字段不够”。需要给后端的每一项都必须能够直接用于修改 Apifox,并明确验收步骤。后端更新后由用户重新导出 JSON 和 YAML,先通过语义一致性与差异合同,再允许页面接入。
-
-### 5.1 已核对结论 API-A04-001
-
-- 页面与动作:A04 提交注册并建立会话。
-- 当前接口:`POST /genealogy/app/auth/register`。
-- 已确认响应:受保护旧快照的响应形状已经过期;2026-07-22 新线上注册成功响应为 `RAppLoginVo`,`data` 引用 `AppLoginVo`,唯一会话字段为 `access_token`。密码登录与短信登录使用同一响应链。
-- 客户端合同:`utils/api.js` 只消费 `AppLoginVo.access_token`;旧字段读取已经删除。必须等同版本双导出落地后再把页面接到远端,不能把线上证据手工写回受保护源文件。
-- 产品结论:取得并保存有效令牌后直接清理认证流程并进入 G01;不保留“注册成功后再登录”的并行终点。
-- 尚未关闭范围:短信发送、行为验证、限流和验证码状态机不由本结论代替,按后续短信阶段单独审查。
-
-### 5.2 后端问题单 API-T01-001
-
-**优先级:** P0;现有 6 人默认数据已能出现确定性断线,当前合同也无法安全支持几十代、几百代。
-
-**受影响页面:** T01 主页面,T03 定位,T04 新增亲属,T06 编辑关系,T07 搜索成员;G01/G05 只受入口与焦点参数影响。
-
-**当前接口与问题:**
-
-- `GET /genealogy/app/genealogies/{genealogyId}/lineage/tree` 只接受 `genealogyId`,返回递归 `LineagePersonTreeView[]`。
-- 递归 `children/spouses` 与 `fatherId/motherId` 不能无歧义表达多个家庭联合点、单亲、收养、继亲、监护、主入边、窗口边界和树版本。
-- 世系 ID 使用 `integer/int64`,超过 JavaScript 安全整数时会改变身份。
-- 缺少世代×支系概览、人物定位、关系编辑和统一树版本并发合同。
-
-**要求后端在 Apifox 原子更新:**
-
-```http
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/tree
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/tree/overview
-GET /genealogy/app/v2/genealogies/{genealogyId}/lineage/persons/{personId}/locator
-PATCH /genealogy/app/v2/genealogies/{genealogyId}/lineage/relationships/{relationshipId}
-```
-
-- `/lineage/tree` 查询参数固定为 `mode,focusPersonId,ancestorDepth,descendantDepth,boundaryId,cursor,limit,treeVersion`,不接受 `branchId/generation`。FOCUS 模式可省略焦点,但非空焦点只能是 VISIBLE 稳定人物 ID;REDACTED、不可见、过期或不存在的焦点统一返回 `404 LINEAGE_FOCUS_NOT_AVAILABLE`。深度为 0—20 的整数且默认上二代/下二代;BOUNDARY 模式必须同时提供 `boundaryId/cursor/treeVersion` 且不得带焦点或深度;`limit` 为最小 1、默认 200、最大 500,非法组合返回 `422 LINEAGE_QUERY_INVALID`。
-- 响应唯一根模型:`LineageGraphWindow`,必含 `version,state,genealogyId,nodes,familyUnits,edges,window`;版本字段固定为 `schemaVersion,treeVersion,generatedAt`,`state` 以 `EMPTY/POPULATED` 为 discriminator 使用 `oneOf`。EMPTY 精确要求空 nodes/familyUnits/edges、空 `entryPersonIds`、空 boundaries、`focusPersonId=null、generationRange=null、returnedNodeCount=0`;POPULATED 要求非空 nodes、引用其中 VISIBLE 节点的焦点、有效入口、非空代际范围,并满足 `returnedNodeCount === nodes.length`。
-- `entryPersonIds` 精确等于当前窗口无 primary 入边的节点集合,secondary 入边不取消入口身份;入口人物 `entryReason` 为 `GENEALOGY_ROOT/WINDOW_CUT/DISCONNECTED_COMPONENT` 且恰有零条 primary 入边,非入口 `entryReason=null` 且恰有一条 primary 入边。全谱根只由 overview 的可见根/隐私根计数与 locator 的根可见性分支表达;旧 `rootPersonIds/rootReason` 不再属于窗口合同。
-- Node 以 `visibility` 为 discriminator 使用 `oneOf`。VISIBLE 精确包含可见身份字段,稳定人物 ID 不得以 `redacted:` 开头,`sex` 固定为 `MALE/FEMALE/UNKNOWN`;REDACTED 只允许 `id,generation,displayName,order,visibility,entryReason`,名称固定为“隐私成员”,opaque ID 精确使用 `redacted:{treeVersion}:{token}` 并仅在该版本内作当前图内部引用,不得进入 FOCUS、locator、搜索、写接口或任何 `focusPersonId/targetPersonId`,也不得泄漏头像、性别或支系字段。
-- `FamilyUnit` 必含 `id,anchorPersonId,partnerRelationship,partners,order`;一个单亲成员或一对伴侣组成一个家庭单元。`partnerRole` 只允许 `ANCHOR/PARTNER`;双人关系对象包含稳定 `relationshipId、relationshipKind=PARTNER、relationType、status`,伴侣 `relationType` 为 `MARRIAGE/PARTNERSHIP/UNKNOWN`、`status` 为 `ACTIVE/ENDED/UNKNOWN`,单亲为 `null`,多配偶拆为不同家庭单元。
-- `ParentChildEdge` 必含 `id,familyUnitId,childId,lineageParentId,parentRelations,primary,order`;每项父母关系包含稳定 `relationshipId,relationshipKind=PARENT_CHILD,personId,parentRole,relationType`。`parentRole` 为 `FATHER/MOTHER/PARENT/GUARDIAN/UNKNOWN`,`relationType` 为 `BIOLOGICAL/ADOPTIVE/STEP/GUARDIAN/UNKNOWN`;所有父子关系都检查循环,不能只校验 primary。
-- boundary 必含稳定 ID、锚点、方向、原因、隐藏数量和 cursor;WINDOW 锚点的 `anchorId=null`,其他锚点引用对应实体;`hiddenCount` 为非负整数或 `null`,cursor 只在 UNLOADED 时非空。窗口内匿名人用 `Node.visibility=REDACTED`,窗口外隐藏拓扑用 boundary REDACTED,同一对象不得重复表达;运行时网络 FAILED 不写进后端枚举。
-- 所有实体、关系和引用 ID 使用非空字符串;`avatarOssId` 只允许非空字符串或 `null`。
-- cursor 绑定 `genealogyId/treeVersion/boundaryId`;版本变化返回 HTTP `409` 和 `TREE_VERSION_CHANGED`。
-- overview 只接受必填 `treeVersion`,版本变化返回 `409 TREE_VERSION_CHANGED`;响应以 `state=EMPTY/POPULATED` 使用 `oneOf`。EMPTY 精确为 `genealogyPersonCount=0、genealogyRootPersonIds=[]、redactedGenealogyRootCount=0、generationRange=null、buckets=[]`;POPULATED 要求正数总量、非空范围和 buckets,并满足可见根数加隐私根数至少为 1、全部 bucket 三类计数之和等于总量。可见根与 bucket `focusPersonId` 只能使用 VISIBLE 稳定 ID,隐私根只计数不返回 opaque ID。locator 将 `rootVisibility=VISIBLE/REDACTED` 与 `pathCompleteness=COMPLETE/REDACTED_GAPS` 独立建模;`ancestorPathSegments` 用 VISIBLE 人物 ID 段与不含 ID 的 REDACTED gap 段表达任意中间隐私,支持可见根但中间祖先隐藏,任何路径都不得包含 opaque ID。
-- 世系写接口携带 `If-Match`,成功返回新 `treeVersion` 以及受影响人员、家庭和关系 ID;关系 PATCH 以不可变 `relationshipKind` 为 discriminator 使用 `oneOf`,PARTNER 只更新 `relationType/status`,PARENT_CHILD 只更新 `relationType/parentRole`。每个分支至少提交一个可修改字段,省略字段保持原值;只有 `relationshipKind` 的空更新返回 `422 RELATIONSHIP_PATCH_EMPTY`,不得偷换参与人。
-- 客户端 Scene 根固定为 `{ sceneVersion, treeVersion, focusPersonId, bounds, items }`;`utils/lineage/scene.js` 唯一生成 `sceneVersion`,缺失版本或相同版本对应不同 payload 均拒绝原子替换。瞬时 `selectedId` 不进入 Scene 或版本摘要,renderjs 只用它在同一 Canvas 动态重绘光晕。
-- 四条操作统一声明 `200/400/401/403/404/422/429/5XX`;tree、overview、relationship PATCH 另声明 `409`。错误响应根层唯一业务码字段为必填字符串 `businessCode`,稳定码必须在对应响应 `oneOf` 分支中用单值 enum(OpenAPI 3.1 可用 `const`)表达;关键词、description、example 和无关 metadata 都不算证明。非空 `generationRange` 固定为关闭额外字段的 `{ minGeneration, maxGeneration }`,两项均为大于等于 1 的整数,大小顺序交给运行时 validator。
-- 旧 v1 树路径保持原合同;App 只实现上述四条固定 `/genealogy/app/v2/...` 路径,不双读、不运行时探测版本。
-
-**关闭条件:** 用户从更新后的 Apifox 重新导出 JSON/YAML;两份文件同时通过 `tests/lineage-openapi-contract.ps1`;三人逐字段复核后,客户端才能开始规范化、布局和 Canvas 实施。
-
-### 5.3 后端问题单 API-GENEALOGY-WORKSPACE-001—003
-
-**优先级:** P1;阻塞 G01/G05 切到 remote 和正式上线,不阻塞继续审查无依赖业务域。
-
-**唯一 owner:** `GET /genealogy/app/genealogies/mine`/`appListMyGenealogies` 持有当前账号可访问集合;`GET /genealogy/app/genealogies/{genealogyId}/overview`/`appGetGenealogyOverview` 持有 G05 只读展示。两个 operationId 全局唯一,路径只开放 GET、无 body;首批不接语义重复的 `GET /{genealogyId}`,不让两个详情响应互相补字段。
-
-**当前线上证据:** `RListAppGenealogyVo/RAppGenealogyVo/AppGenealogyVo` 均无 `required`;`AppGenealogyVo.genealogyId` 为 `integer/int64`,`roleType/status/memberStatus` 无 enum,且没有 `canView`。最大合法 int64 经 JavaScript JSON 解析会失真,解析后再转字符串无法恢复。无令牌调用 `/mine`、`/1` 和 `/1/overview` 均实测返回 HTTP 200、`application/json;charset=UTF-8`、`{code:401,msg,data:null}`;线上文档却只列 200/401,401 schema 为 `*/* string`,也没有有效 security 声明。无令牌行为已经拒绝访问,因此不能仅凭注解缺失断言已发生公开泄漏;对象级授权仍没有有效账号反例证据。
-
-**API-GENEALOGY-WORKSPACE-001:无损身份与最小 schema 闭包。** `/mine` 的 200 响应固定为 `RListAppGenealogyVo`,`/overview` 固定为 `RAppGenealogyVo`;两个 envelope 都关闭额外字段且精确 required `{code,data}`、code=200,列表 data 为 `AppGenealogyVo[]`,详情 data 为单个 `AppGenealogyVo`。首批实体必填字段固定为 `genealogyId/genealogyName/canView/canManage/canEditContent/roleType`:响应字段和 overview path 都引用词法 `GenealogyId`,名称引用 `GenealogyName`,三项 capability 为 boolean,角色为至少两个稳定非空值的正式 enum。地点、堂号、人数、简介等实体字段可选,`AppGenealogyVo` 不强制关闭未知额外字段。
-
-**API-GENEALOGY-WORKSPACE-002:可访问集合与能力投影。** `/mine` 用 `x-current-account-viewable-only=true` 明确只返回当前账号仍可查看的家谱,并以 `OMIT_ONLY_AFTER_CONFIRMED_ACCESS_LOSS` 约束仅在成功确认失权时省略;G01 不能从未声明的 status 或 role 猜可访问性。`canManage/canEditContent` 是管理与内容入口的授权 UI 投影;真正写接口仍须后端逐次鉴权,capability 不能替代服务端授权。`roleType` 只拥有 G01 分组和角色标签,不替代 capability。
-
-**API-GENEALOGY-WORKSPACE-003:typed HTTP、缓存与对象级授权。** 两条读取都 required SaToken 和非空 clientid;`/mine` 精确 200/401/429/500,overview 精确 200/400/401/404/429/500,不再允许 HTTP 200+业务错误。400 固定 `GENEALOGY_ID_INVALID`,401 为 `AUTH_REQUIRED`,对象无权/撤权/不存在以 `NON_DISCLOSING_GENEALOGY_NOT_AVAILABLE` 统一 404,429/500 分别为 `RATE_LIMITED/GENEALOGY_WORKSPACE_UNAVAILABLE`。全部只允许 JSON;每个响应必须含固定单值 private/no-store,429 另有 Retry-After;只允许非语义 tracing header:`traceparent/tracestate/x-request-id/x-correlation-id`,禁止 ETag 与其他语义 header。parameter/response/header/schema 只接受 exact local component ref;四种 tracing header 的引用也必须 exact local,内联 Header Object 必须 allowed-key 关闭并带非 null 的 string schema。clientid、code/data/businessCode、实体字段和 role 枚举以 allowed-key 集拒绝 `nullable`、readOnly/writeOnly、冲突组合和额外验证关键字;全局扫描全部 `/genealogy/app/` GET 的 200 schema 闭包并合并 allOf 属性,除 overview 外返回单谱实体的旁路详情一律失败,不把 `/mine` 数组误算为单谱读取。至少用两个账号执行无凭证、跨账号、撤权、删除、限流、服务异常和正常访问反例;G01 只在成功列表确认 ID 消失时写 tombstone,网络/5xx 保留现场,G05 不回退 fixture 权限。
-
-**展示取舍:** 当前 G05 fixture 还显示 `source/manager/certification/ancestorName/parentName/branchName/updatedAt/activeCount`,线上没有等价字段。首批允许把这些区域隐藏或使用明确“待补充/待同步”的非业务降级;若产品要求继续把它们作为可信首屏信息,后端需另补字段或明确组合接口。不能为了复刻 mock 把 22 个字段全部列为当前硬门禁,也不能把 mock 值带进 remote。
-
-**关闭条件:** 后端从同一版本重新导出 JSON/YAML,`tests/genealogy-workspace-openapi-contract.ps1` 通过;三人复核 enum 与页面消费后,才实现专属 adapter、G01 `onShow` 刷新和 G05 `/overview` 接线。随后完成有效账号行为矩阵和 MuMu 原生状态矩阵;缺少任一层证据都不能把工作区称为可上线。
-
-### 5.4 后端问题单 API-M06-001—003
-
-**优先级:** P1;阻塞 M06 切到 remote 和帮助内容上线,不阻塞继续审查其他无依赖页面。
-
-**唯一 owner:** 当前 M06 只使用 `GET /genealogy/app/help-articles`。线上 `HelpArticleVo` 已携带完整 `helpContent`,所以手风琴展开直接使用同一列表快照;不调用 `GET /{helpId}`,不建立文章深链、详情缓存或第二正文 owner,也不让 `helpId` 进入页面模型。
-
-**当前线上证据:** 列表返回 `RListHelpArticleVo`,列表项含 `helpId/helpCategory/helpTitle/helpContent/coverOssId/sortOrder/viewCount/status/remark`,但 wrapper 与 VO 都无 `required`,正文无格式语义,分类 query 无正式值域。受保护双导出更旧,只引用通用 `ListResult/RList`,没有专用 Help schema。匿名调用列表、带任意分类列表和详情均为 HTTP 200、`application/json;charset=UTF-8`、`{code:401,msg,data:null}`;线上文档则声明 HTTP 401 string 且 operation 无有效 security。
-
-**API-M06-001:专用响应与最小 schema 闭包。** 列表 200 固定引用 `RListHelpArticleVo`;envelope 的 `code/data` required,`code` 为整数,`data` 为允许空数组的 `HelpArticleVo[]`。每行只把 `helpCategory/helpTitle/helpContent` 设为 required、`minLength >= 1` 的字符串;不要求当前页面不消费的 ID、封面、浏览量、状态和排序字段。后端必须从同一版本重新导出 JSON/YAML,不允许客户端手工补 schema。
-
-**API-M06-002:展示标签、正文格式与发布范围。** `helpCategory` 是去边界空白后可直接展示的标签,不是需要客户端猜字典的内部代码;“全部”只由客户端拥有。`helpContent` 首版明确为 plain text,客户端只按字面显示,不解释 HTML、Markdown、图片或外链。用户侧列表只返回当前可展示的已发布文章,响应数组顺序就是页面展示顺序。若未来需要富文本、文章深链或详情,则另立内容安全和词法字符串 `helpId` 合同,不能偷偷扩张当前批次。
-
-**API-M06-003:认证和错误承载一致性。** 后端可选择规范 HTTP 401,也可继续 HTTP 200+稳定业务 `code=401`,但 SaToken/security、JSON 媒体、OpenAPI 响应、部署行为和客户端 validator 必须一致。有效/失效令牌、空列表、畸形列表、5xx、超时和取消都要有集成反例;失败不得被解释成服务端空列表,也不得回退本地 FAQ 冒充线上成功。
-
-**客户端关闭后的唯一形状:** adapter allowlist 输出 `{renderKey,category,title,content}`,其中 key 只由当前 response generation 与映射前 ordinal 组成;输入即使含 unsafe 或重复 `helpId` 也必须完全丢弃。筛选作用于已映射数组,搜索/分类/刷新前清空展开,旧 generation 迟到响应不得替换新列表。页面必须区分加载、服务端空、搜索无结果、错误重试和认证失效,并用原生按钮、`aria-pressed/aria-expanded/aria-controls`、状态播报及至少 44dp 目标完成无障碍闭环。
-
-**关闭条件:** 后端同版本 JSON/YAML 通过 `tests/help-center-openapi-contract.ps1`;三人复核后才写专属 adapter 和页面异步状态。任务 23 关闭认证门禁后,完成有效账号部署矩阵及 MuMu 的系统字号、TalkBack、焦点、长正文、Android 返回和 M06→M07 验收。详情端点不属于本关闭条件。
-
-### 5.5 后端问题单 API-PROFILE-READ-001—003
-
-**优先级:** P1;阻塞 M01/M02/M03 使用真实资料和正式 remote 发布,不阻塞继续审查通知等其他只读域。
-
-**唯一 owner:** `GET /genealogy/app/auth/profile` 持有当前登录账号资料。M01 身份卡、M02 表单初值和 M03 绑定手机号行都调用同一个窄 adapter,但不建立跨账号缓存、不通过路由传 PII。M05 当前手机号在 remote 发布前也必须消费同一脱敏结果或隐藏;这不等于提前接入换绑写接口。
-
-**当前线上证据:** 200 已返回 `RAppProfileVo → AppProfileVo`,实体含 `userId/tenantId/userNo/phone/nickName/realName/avatar/sex/birthday/email/registerSource/loginIp/loginDate/status/clientKey/deviceType`,但 wrapper 与 VO 无 required,phone 无 pattern,姓名/邮箱无 length/format。受保护双导出仍为通用 `ObjectResult/RObject`。匿名 GET 实测 HTTP 200、`application/json;charset=UTF-8`、`{code:401,msg,data:null}`;线上文档则声明 HTTP 401 string,operation 只有“需要登录”文字而无有效 security/clientid。
-
-**API-PROFILE-READ-001:专用响应与最小字段闭包。** 200 固定引用 `RAppProfileVo`,envelope 的 `code/data` required,`data` 引用 `AppProfileVo`。实体只 required `phone`,其值必须匹配 canonical `^1[3-9]\d{9}$`。`nickName/realName/email` 都是声明过的可选属性;出现时必须为非空且去边界空白的字符串,姓名长度 1—30,邮箱长度 1—100 且 `format: email`。不要求当前页面不消费的 ID、头像、状态、设备和登录审计字段。
-
-**API-PROFILE-READ-002:可选值与隐私投影。** 三项可选字段唯一未设置形态是属性省略,不再并行接受 null、空串和缺失。adapter 固定输出 `{maskedPhone,phoneAccessibleLabel,nickName,realName,email}`,真正缺席的可选值规范为内部空串;出现但非法则整份失败。明文手机号只在函数局部校验后立即变为掩码和“绑定手机号,尾号 xxxx”读屏标签,不得进入页面模型、缓存、路由、日志或错误。`userId/avatar` 即使是 unsafe int64 也通过 allowlist 完全丢弃,不做 `String(number)`。
-
-**API-PROFILE-READ-003:认证、配置与错误一致性。** 后端可选择规范 HTTP 401 或 HTTP 200+稳定业务 401,但 required clientid、SaToken/security、JSON 媒体、OpenAPI 与部署必须一致。客户端运行模式经 `resolveRuntimeMode()` 校验,错误 remote 配置不得静默回 fixture;读取使用严格 envelope、15 秒超时、取消和 generation 防迟到。账号失效交给 session owner,network/timeout/5xx/畸形数据是可重试读取失败,不存在写请求 uncertain。
-
-**页面与后续写边界:** M01 资料失败只替换身份卡,菜单和底栏保持;查询参数假错误、fixture“创建者”和 remote 下伪通知数删除。M02 异步填表后才建立 baseline,GET 不证明 PUT;未来写批次必须验证省略字段保持、dirty-only payload、清空语义和并发。M03 仅手机号行局部失败,密码入口保持。头像、M04/M05 写入和设备管理不混入本批。
-
-**关闭条件:** 后端从同一版本重新导出 JSON/YAML 并通过 `tests/profile-openapi-contract.ps1`;三人复核后才实现唯一 normalizer、三页局部状态与 M05 脱敏展示迁移。随后以不同资料完整度账号验证掩码、401、畸形响应、5xx、超时、账号切换和取消,并在 MuMu 完成系统字号、TalkBack、焦点、键盘、长昵称和返回流程。
-
-### 5.6 后端问题单 API-NOTIFICATION-READ-001—003
-
-**优先级:** P1;阻塞 N01/N02、M01/G01 未读数使用真实通知和正式 remote 发布,不阻塞继续审查其他业务域。
-
-**唯一 owner:** `GET /genealogy/app/notifications` 不带 `readStatus` 时持有当前账号完整活动通知集合;`GET /genealogy/app/notifications/unread-count` 持有同一集合的未读数量。当前没有详情端点,N02 只消费列表成功响应形成的不可变内存快照,不建立第二正文 owner。
-
-**当前线上证据:** 线上列表为 `RListNotificationVo → NotificationVo[]`,未读数为 `RLong`;两者和实体都无 required。`NotificationVo` 的 `notificationId/genealogyId/senderUserId/bizId` 是 int64,`readStatus` 无 enum,标题/正文无长度与格式,列表无分页、容量、完整性和排序。受保护双导出列表仍引用通用 `ListResult/RList` 且完全没有 unread-count。匿名 list/count 均实测 HTTP 200、`application/json;charset=UTF-8`、`{code:401,msg,data:null}`,而线上文档声明 HTTP 401 string,operation 无有效 security/clientid。
-
-**API-NOTIFICATION-READ-001:专用响应与最小字段闭包。** 列表 200 固定 `RListNotificationVo`,未读数 200 固定 `RNotificationUnreadCount`;两层 `code/data` required,`code` 为 integer。列表 data 是允许为空且 `maxItems` 不超过 200 的 `NotificationVo[]`;实体 required `noticeTitle/noticeContent/publishTime/readStatus`。标题为 1—50 字符;正文为 1—1000 字符、完整未截断 plain text;时间是带 `Z` 或显式 offset 的 RFC3339 date-time;状态只允许 `READ/UNREAD`。计数是 0—200 的 int32。
-
-**API-NOTIFICATION-READ-002:完整活动集合与快照。** 服务端活动集合本身最多 200 条;列表无筛选时完整返回该集合并按最新优先,未读数精确等于同一集合中 `readStatus=UNREAD` 的数量。两个请求之间并发变化允许瞬时差异,不要求客户端强行相等。adapter 公开 `{snapshotKey,title,content,publishedAt,unread}`,key 为成功响应 generation+映射前 ordinal;筛选不重编号。成功刷新原子替换快照,退出/账号切换清空且不落盘;N02 无 key 时提示“请返回消息中心重新打开”。
-
-**API-NOTIFICATION-READ-003:认证、错误与内容安全。** 后端统一 required clientid、SaToken/security、JSON 媒体、HTTP 401 或业务 401 的文档与部署行为。客户端拒绝无时区时间、未知状态、空/超长标题正文和畸形 envelope;失败不得回退 fixture。首批丢弃所有 ID、sender、`noticeType/bizType/bizId`,不解释 HTML/Markdown/URL,不执行目标跳转;未知业务通知仍完整显示内容。
-
-**客户端关闭后的唯一行为:** N01 摘要最多 160 个 Unicode 字素并可换行,N02 显示同一快照完整正文;M01/G01 共同调用 count owner,文案为“未读消息”,可见 `99+` 但读屏播报真实数。读取批次原子删除 fixture 未读数、本地已读 mutation、通用 G10/审核 CTA、N02 目标按钮和假重试;写能力等待 5.7。
-
-**关闭条件:** 后端同版本 JSON/YAML 通过 `tests/notification-read-openapi-contract.ps1`;三人复核后才实现读取 adapter 和四页局部状态。认证门禁关闭后完成 0/1/99/100/200、并发、畸形响应和账号切换反例,再在 MuMu 验证系统字号、TalkBack、键盘/焦点、长文本、刷新、N01→N02 和 Android 返回。
-
-### 5.7 后端问题单 API-NOTIFICATION-STATE-001—003
-
-**优先级:** P1;阻塞真实单条/全部已读和四页状态收敛。必须在 5.6 读取批次之后独立实施,不能与读取代码混成一个不可验证批次。
-
-**唯一 owner:** `POST /genealogy/app/notifications/{notificationId}/read` 持有单条已读,`POST /genealogy/app/notifications/read-all` 持有全部已读。两者无 request body,成功精确返回 `RVoid`;页面只把 `snapshotKey` 交给 notification controller,由 controller 私有解析服务端 ID。
-
-**当前线上证据:** 两条 POST 已存在且返回 `RVoid`,但 path 和 `NotificationVo.notificationId` 都是 int64;最大值进入 JavaScript 会失真。`RVoid.code` 未 required,操作没有正式幂等、重试、超时未知、当前账号作用域、跨账号/不存在、read-all 截止点、并发新消息或刷新收敛语义。
-
-**API-NOTIFICATION-STATE-001:无损身份和响应闭包。** `NotificationVo.notificationId` 与 path 参数必须同为 required 的 1—128 位 URL-safe opaque string,pattern 固定 `^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$`;禁止 int64 双读或解析后转字符串。`RVoid.code` 为 required integer,两个 POST 都要求 SaToken 和 required string clientid。
-
-**API-NOTIFICATION-STATE-002:幂等与并发截止点。** 两个操作均对当前账号幂等,重复调用成功且没有重复副作用。read-all 以服务端接收请求时当前账号已存在的活动通知为截止集合,之后并发到达的通知保持未读;成功后客户端重取列表和 count。超时、断网、408/5xx 或畸形响应属于结果未知,允许依靠服务端幂等安全重试或先读取状态收敛,不能本地递减计数猜结果。
-
-**API-NOTIFICATION-STATE-003:对象隔离和错误一致性。** 无效会话使用稳定 401;单条 ID 不存在或属于其他账号时统一返回 404 `NOTIFICATION_NOT_AVAILABLE`,避免暴露存在性。文档、部署、错误 envelope 与客户端 validator 必须一致,并以两个账号、删除消息、多端并发和迟到响应做反例。
-
-**客户端迁移与关闭条件:** 写合同通过后,controller 才能私有保留 server ID,并原子删除读取首版“内部也完全丢弃 ID”的实现以及 N01/N02 的 clone mutation;公开页面模型、路由、日志和持久存储仍不得出现 ID。后端同版本 JSON/YAML 必须通过 `tests/notification-read-state-openapi-contract.ps1`,随后完成真实账号与 MuMu 的重复点击、提交中、失败/未知播报及 N01/N02/M01/G01 收敛矩阵。
-
-### 5.8 后端问题单 API-PROFILE-UPDATE-001—004
-
-**优先级:** P1;阻塞 M02 真实保存和 profile 正式 remote 发布。Task28 的 GET 是前置依赖;头像、相册权限、OSS、性别、生日、密码和手机号均不属于本问题单。
-
-**唯一 owner:** 继续使用 `PUT /genealogy/app/auth/profile`,不再增加 PATCH。operation 必须把自身定义为字段级原子 merge update:出现的可编辑属性更新,省略的可编辑属性保持不变;重复相同字段集只设置同一状态,不产生重复通知等额外业务副作用。请求专用 owner 命名为 `AppProfileMergeUpdateBody`,避免旧 `ProfileUpdateBody/AppProfileUpdateBody` 被误当资源替换。
-
-**当前双版本证据:** 受保护双导出的 PUT 使用 `ProfileUpdateBody`,只有 nickName、avatarOssId、sex、birthday 和省市区,没有 realName/email;示例又含 schema 外 `regionCode/addressDetail`,成功返回 generic `RObject`。线上变为 `AppProfileUpdateBody`,含 nickName/realName/avatar/sex/birthday/email,但无 required、`minProperties`、关闭额外字段、merge/clear/version;200 为 `*/* → RAppProfileVo`,实体与 envelope 无 required,operation 无 security/clientid,只列 200/401。两者都不能证明安全写入;未发送真实 PUT。
-
-**API-PROFILE-UPDATE-001:最小 dirty command。** `AppProfileMergeUpdateBody` 是 `additionalProperties:false`、`minProperties:1/maxProperties:3` 的对象,属性集合精确为 nickName/realName/email 且均非 required。nickName 出现时为无边界空白的 1—30 字符,空串/null 非法;realName/email 分别以 `oneOf` 区分精确 `""` clear 命令与非空规范值,非空 realName 1—30,email 1—100 且 format=email。省略保持;纯空白和边界空白拒绝,服务端清库后响应省略该属性。
-
-**API-PROFILE-UPDATE-002:单一版本并发。** `AppProfileVo.profileVersion` required,固定为 1—128 位 URL-safe opaque string;PUT required `If-Match` 采用同形状,body 不重复 version。服务端以当前账号和租户做原子 CAS;成功返回新版本,旧版本固定 HTTP 409 与 `RProfileVersionChanged.businessCode=PROFILE_VERSION_CHANGED`,不得 last-write-wins。H5 正式 origin 的 CORS 必须允许 `If-Match`。
-
-**API-PROFILE-UPDATE-003:typed 响应、认证、错误与隐私。** 200 精确 `application/json → RAppProfileVo`,envelope `code/data` required,data 是完整 canonical profile;400/401/409/422/429/500 均进入同版本文档。operation required SaToken 和 string clientid;GET/PUT 资料响应声明并实测 `Cache-Control: private, no-store`。422 只返回 nickName/realName/email 的结构化字段错误。客户端及服务端日志、路由、持久缓存、遥测和异常不得含真实姓名、邮箱或请求/响应 payload。
-
-**API-PROFILE-UPDATE-004:结果未知与账号隔离。** timeout、network、408/5xx、取消和畸形 200 均视为 outcome unknown;客户端先 GET 对账本次脏字段,全匹配确认成功、仍为旧 baseline 才允许重试、第三值或无法归因版本进入 conflict。session generation 变化时清草稿并拒绝迟到响应;RequestTask 取消不表示服务端未写。
-
-**页面迁移与关闭条件:** 首次 GET 后才建立 baseline,clean 不发请求,saving 冻结三输入和返回;成功应用响应并重置 baseline,失败/unknown/conflict 保留草稿。原子删除 `currentUser.name` 同时冒充昵称/实名、500ms 假保存、API 禁用旧测试断言、假头像按钮和“邮箱用于接收通知”无依据承诺。后端同版本双导出通过 `tests/profile-update-openapi-contract.ps1` 后,才依次实现 normalizer、API、M02 状态机;再用两个账号/多端并发、超时对账和正式 H5 CORS 验证,最终在 MuMu 检查键盘、TalkBack、错误聚焦、长文本、冲突与返回。
-
-### 5.9 后端问题单 API-LOGOUT-001—003
-
-**优先级:** P1;阻塞 M10 服务端撤销和正式 remote 退出闭环。现有本机 `session.clear()` 仍保留为任何网络状态下的安全底线,但不能冒充服务端成功。
-
-**唯一 owner 与当前证据:** `DELETE /genealogy/app/auth/logout` 无 body。受保护双导出有 required clientid、SaToken 和 200 `RVoid`,但只列 200、RVoid 无 required,未定义 scope/幂等/撤销传播。线上只有 200 RVoid 与 401 string,媒体为 `*/*`,operation 无 security/clientid;同样没有 scope、复用和其他设备反例。页面当前只执行一次本地清理并根跳转,相关测试没有远端请求、迟到 A/B 账号竞态或离线状态。
-
-**API-LOGOUT-001:当前凭证族范围与撤销传播。** DELETE 只撤销 bearer 所属当前设备 credential family,包括同一登录会话的 refresh 能力;同账号其他设备 token 保持有效。200 必须表示撤销已传播至所有鉴权节点:旧 access 不能访问任一受保护接口,旧 refresh 不能换新 access。已经鉴权通过的并发业务请求不属于可回滚范围;全设备退出必须另接口。
-
-**API-LOGOUT-002:唯一幂等成功和拒绝。** 能验证为该 client 历史签发的 active、revoked、expired credential 重复 DELETE 都返回相同 200 RVoid且无额外副作用。伪造、格式非法或 client 不匹配才返回 HTTP 401 `RLogoutRejected`,required `code/businessCode`,businessCode 只允许 `TOKEN_INVALID/TOKEN_CLIENT_MISMATCH`;这些拒绝不算远端撤销成功。不得长期并存 200 业务 401、HTTP 401 string 和 typed JSON 三种合同。
-
-**API-LOGOUT-003:安全、媒体、缓存和反例。** operation required SaToken 与非空 string clientid,并验证 clientid 与 token client 绑定;200/401 为 application/json,`Cache-Control: private, no-store`,RVoid required integer code,另声明 400/429/500。以同账号两设备 token A/B 验证:A 删除后全受保护接口拒绝 A,重复 A 仍 200,B 保持有效;再验证 expired、伪造、client mismatch、跨鉴权节点传播、弱网/超时和正式 H5 Authorization/clientid CORS。服务端日志不得记录 bearer。
-
-**客户端关闭后的唯一流程:** `logoutCoordinator` 同步捕获 A token/clientid/epoch,立即经 session owner bump epoch 并清全部账号态,再用显式 A 创建后台 RequestTask且立即 `goRoot(A01)`;M10 不持 token,请求不绑定页面 controller。coordinator 仅保存 attemptId/logoutEpoch/status,绝不在异步 finally 再 clear;A01 只在 session 为空且 epoch 未变时消费一次状态,B 登录后丢弃 A 迟到结果。所有分支都承诺“已从本机退出”,再区分 confirmed/unconfirmed/not-revoked;不持久 token、不跨重启重试、不阻塞重新登录。
-
-**关闭条件:** 后端同版本 JSON/YAML 通过 `tests/logout-openapi-contract.ps1`;三人复核后才实现 session epoch、coordinator、严格 API 和 A01 提示,并原子替换 M10/导航/NM 旧静态断言。随后完成两设备部署矩阵和 MuMu 的确认、双击、系统返回、网络异常、状态播报、快速重新登录与根导航失败验收。
-
-### 5.10 后端问题单 API-PASSWORD-001—005
-
-**优先级:** P0;同时阻塞 A01 密码登录、A04 注册、A05 找回后的新密码验证、M04 登录态改密与正式 remote 模式。当前 M04 本地预览不得冒充修改成功。
-
-**当前三方证据:** 受保护双导出的 `PasswordLoginBody/PasswordRegisterBody/PasswordResetBody/PasswordChangeBody` 都把密码写成静态 32 个十六进制字符 MD5;改密虽有 SaToken/clientid,却只有 200 RVoid,RVoid 无 required。线上相应 `AppPassword*Body` 仍接受大小写 MD5,M04 只有 200 `*/* → RVoid` 与 401 string,operation 无 security/clientid;live server 还发布 HTTP URL。现有 M04 只有 500ms 本地定时器,旧测试正确禁止提前导入 API;未发送 PUT。
-
-**API-PASSWORD-001:唯一 raw wire 与策略 owner。** 新增 `CurrentPasswordSecret` 和 `NewPasswordSecret` 两个共享 schema。登录 password 与改密 oldPassword 只能引用前者,1—64 Unicode code point、原样不 trim;注册、找回和改密 newPassword 只能引用后者,NFC 后 15—64 code point,允许空格/Unicode/粘贴/密码管理器且无组成规则。四条入口在同一版本删除 MD5 与任何 raw/hash oneOf fallback;服务端执行常见/泄露密码 blocklist、账号限速、新旧不同与带独立盐的 Argon2id,无法使用时才选合规 scrypt/PBKDF2。confirm 永不出端。
-
-**API-PASSWORD-002:重新认证、ALL session 与原子 CAS。** M04 以当前密码重新认证,TAC 不能替代;严格 200 前在同一安全事务中写入新 verifier、递增账号 credentialEpoch,并跨节点撤销所有设备/所有 client 的既有 access、refresh 与 renewal session,包括调用者。两个同旧密码并发请求至多一个 200,另一个 typed 409 `CREDENTIAL_VERSION_CONFLICT`。不返回新 token,不保留旧 bearer。
-
-**API-PASSWORD-003:typed 错误与确定未写边界。** PUT 声明 200/400/401/409/422/429/500;409/422 的 `RPasswordChangeRejected.businessCode` 精确为 `CREDENTIAL_VERSION_CONFLICT/CURRENT_PASSWORD_INCORRECT/NEW_PASSWORD_SAME_AS_CURRENT/PASSWORD_POLICY_VIOLATION`。400/422/429 明确保证未修改;401/409 进入重新登录;network/timeout/取消/畸形 2xx/5xx 均为结果未知,客户端不得自动重试或解析 msg。
-
-**API-PASSWORD-004:鉴权、媒体、缓存与秘密卫生。** required SaToken、与 token client 绑定的非空 clientid、关闭额外字段的 JSON body;所有响应 application/json 且 `Cache-Control: private, no-store`,429 required `Retry-After`,RVoid integer code required。OpenAPI server 和实际重定向全程 HTTPS。反向代理、应用日志、APM、分析、崩溃报告与错误 body 不记录 old/new/confirm、MD5、Authorization 或完整请求。
-
-**API-PASSWORD-005:账号能力和客户端崩溃边界。** 后端明确所有 App 账号是否都已配置密码;若不是,profile 返回稳定 `passwordConfigured` 并让无密码账号进入独立 step-up 设置流程,M04 不猜。客户端 session owner 在 dispatch 前只持久化 `{sessionEpoch,startedAt}` 的 `credentialChangeInFlight`;确定未写清 marker,200/401/409/unknown 清同 epoch 账号态并回 A01。冷启动同 epoch marker 在任何缓存渲染前 fail closed,新登录 bump epoch,迟到旧响应不得清新账号。禁止持久 token、密码、摘要、body、operation 状态或自动重试。
-
-**关闭条件:** 后端同版本 JSON/YAML 通过 `tests/password-change-openapi-contract.ps1`,并先关闭密码登录 TAC 门禁;三人复核后按共享策略→四条 API wire→session epoch/marker→M04 状态机顺序原子实施,删除 `calcMD5` 生产消费者、8—32 旧规则和 NM preview 断言。最后以两设备全部 access/refresh 撤销、并发/fault injection、秘密日志扫描、正式 CORS/HTTPS 和 MuMu 的密码管理器、系统字号、TalkBack、44dp、错误聚焦、Android 返回与跨根提示验收。
-
-### 5.11 后端问题单 API-PHONE-001—005
-
-**优先级:** P0;阻塞 M05、全活动短信码生产强度及正式 remote 模式,并依赖 M04 raw-password 和认证/TAC 门禁先关闭。当前 M05 只做本地 4 位码校验,不得冒充换绑。
-
-**当前三方证据:** 本地 `PhoneChangeBody` 要求 `clientId/phone/smsCode`,线上 `AppPhoneChangeBody` 只要求 `phone/smsCode`;两边都是 4 位码,都没有 currentPassword、号码占用、并发、会话撤销、outbox 或结果未知语义。线上 PUT 无有效 security/clientid且返回完整 `RAppProfileVo`,错误只有 401 string;共享发码 operation 在线上明确忽略权限,当前客户端方法也固定不携 bearer。页面使用脱敏 fixture、70rpx `view role=button` 和 500ms 定时器,未调用 API/TAC;未发送 POST/PUT、短信,未操作 MuMu。
-
-**API-PHONE-001:专用受保护发码 operation。** 新增 `POST /genealogy/app/auth/phone/sms/code`,required SaToken 与非空 clientid,闭合 `PhoneChangeSmsCodeBody` 只含 `phone/validToken`;服务端固定 scene=`APP_PHONE_CHANGE`,不接受 sceneCode/clientId/tenantId/grantType。公共 `/auth/sms/code` 删除该 scene。两个 operation 复用同一 OTP 服务 owner;匿名专用调用必须 401,公开登录/注册/找回发码仍可匿名。validToken 必须绑定当前账号/session、tenant、client、scene 与规范化新号并单次消费。
-
-**API-PHONE-002:唯一六位 OTP wire 与生命周期。** 新增 `SmsCodeSecret`:CSPRNG 生成恰好 6 位 ASCII 数字、保留前导零、writeOnly、无示例;5 分钟 TTL、60 秒重发、最多 5 次失败、单次消费,重发废止旧 generation且不重置累计失败次数。同一复合键只有一条 active generation。A01/A04/A05/M05、`AccountDeactivateBody` 及同源生成器、短信模板、双导出、validator、页面和测试同版删除全部 4 位规则,不保留 4/6 fallback。
-
-**API-PHONE-003:existing-factor 与闭合最终 PUT。** `PUT /genealogy/app/auth/phone` required SaToken/clientid,`PhoneChangeBody` 只含 required `currentPassword/phone/smsCode` 且关闭额外字段;密码引用 `CurrentPasswordSecret`,新号引用 11 位 `NewBoundPhone`,短信引用 `SmsCodeSecret`。当前密码是既有因子再认证,TAC 不能代替;无密码账号返回 `STEP_UP_UNAVAILABLE` 进入独立恢复,不能降级为 bearer+新号 OTP。不要求旧号 OTP,成功后改用旧号安全通知。
-
-**API-PHONE-004:原子换绑、唯一约束与会话。** 在一个事务中验证 currentPassword/active OTP、执行 `(tenantId,canonicalPhone)` 唯一约束、消费 OTP、CAS 更新号码、递增 credentialEpoch、撤销包括当前在内的全部 access/refresh/renewal session,并持久化旧号通知 outbox;严格 200 只返回 `RVoid`。并发至多一笔成功;通知投递失败不回滚换绑,但 outbox 必须重试并告警。不得在证明新号控制权前泄露号码是否已绑定。
-
-**API-PHONE-005:typed 错误、传输与客户端恢复。** POST/PUT 都声明 200/400/401/409/422/429/500 JSON、`private, no-store`,429 有 `Retry-After`;409/422/429 使用 required `RPhoneChangeRejected.code/businessCode`,稳定覆盖 current password、同号/占用、验证码错误/过期/尝试耗尽、credential 冲突、step-up 不可用、验证重做与限流,客户端不解析 msg。最终 PUT dispatch 前复用无秘密 `{sessionEpoch,startedAt}` marker;200/401/409/unknown 清同 epoch 账号态回 A01,不自动重试。HTTPS、Authorization/clientid CORS 和密码/手机号/OTP/TAC/token 全链路日志脱敏必须实测。
-
-**关闭条件:** 同版本 JSON/YAML 通过 `tests/phone-change-openapi-contract.ps1`,且认证、密码和 profile 读取前置门禁全部通过;三人复核后按全活动六位码→专用发码 API→共享 credential marker→M05 状态机原子实施,替换旧四位/preview 断言。最后完成匿名/错场景/TAC 重放、前导零、重发/过期/限流、号码唯一与枚举、两设备并发、全部 session 撤销、fault injection、旧号 outbox 和 MuMu 的输入法、TalkBack、44dp、系统返回与结果未知矩阵。
-
-### 5.12 后端问题单 API-G03-001—005
-
-**优先级:** P0;阻塞 G03 真实创建、创建后 G01/G05/context 闭环及 APP 家谱访问规则唯一化。当前同页两步是明确本地预览,不得把 `local-created-*` 或 fixture mutation 当作后端成功。
-
-**当前三方证据与方案结论:** 本地 `GenealogyCreateBody` 和线上 `AppGenealogyCreateBody` 都只创建家谱,通用人物 POST 另写始祖;创建响应未形成 required 词法 ID/OWNER/READY 回执。页面缺可信 regionCode,默认男性、硬限 1800 年、把“一世”混入 generationName;成功不安装真实 context。三人先设计 `ROOT_REQUIRED` 两写及恢复,再确认没有跨库或保存空谱需求,最终否决这类客户端 saga:它只会新增半成品配额、可见性、删除/过期、版本、G01 恢复卡和第二次未知结果。唯一最小生产方案是最终按钮一次原子 bootstrap,第一步零网络写。
-
-**API-G03-001:闭合 bootstrap 与领域事务。** `POST /genealogy/app/genealogies` 唯一 body 改为 additionalProperties=false 的 `AppGenealogyBootstrapBody`,字段精确为 `genealogyName/surname/ancestralHall/regionCode/accessPreset/rootPerson`,除堂号外全部 required;rootPerson 只含 `name/sex/birthDate/biography` 且前两项 required。sex=`MALE/FEMALE/UNKNOWN`,生日 format=date,服务端固定 generation=1、唯一首根且不接收账号/编号/父母/字辈/状态。严格 200 前一个事务完成 quota、谱、OWNER、根、READY 和幂等回执,失败全回滚;通用人物 POST 仅用于 READY 后普通人物。同名不是冲突,重复提醒只做建议。数据库 bootstrap-root marker 是身份权威:根 PUT 可编辑白名单精确只有 `name/sex/birthDate/biography`,status/personStatus、账号绑定、世代、父母、根标记及任何白名单外字段一律 422;collection POST、人物 DELETE 和 parents mutation 也不能创建第二根、删除根或给根重挂父母。
-
-**API-G03-002:幂等键、控制事务、结果和稳定错误。** required `Idempotency-Key` 引用 `GenealogyBootstrapOperationKey`,精确格式为 `gcb.{13位 issuedAt 毫秒}.{22—43位 base64url CSPRNG}`,随机量至少 128 位;固定 `acceptUntil=issuedAt+10 分钟`,以 server time 判定,未来超过 5 分钟返回 400 `OPERATION_KEY_INVALID`,并以 600/300 秒 extension 锁定。窗口内首次 POST 用短控制事务按 account/tenant/client/path/key 唯一 CAS 认领 PENDING、canonical digest、fencing lease 与 `resolveBy<=claimedAt+2 分钟`,以 120 秒 extension 锁定;相同作用域/key/body 的已存在操作在截止后仍返回同一结果,不同 digest 返回 409 `IDEMPOTENCY_KEY_REUSED`,过期且不存在的 key 返回 409 `OPERATION_KEY_EXPIRED`。业务事务才原子处理 quota、谱、OWNER、唯一根、READY 和 SUCCEEDED;失败回滚后 CAS FAILED_NO_COMMIT,watchdog 同样用 fencing CAS,旧 worker 不能迟交。`GenealogyBootstrapResult` required 词法字符串 genealogyId/rootPersonId、setupState=READY、roleType=OWNER、canView=true;成功防重记录至少覆盖实体生命周期。POST 声明状态专属、`code` 与 HTTP 状态单值一致的 400/401/403/409/422/429/500 typed JSON、private/no-store,429 有 Retry-After。
-
-**API-G03-003:无 PII operation-status 与迟到竞态。** 新增 required SaToken/clientid 的 `GET /genealogy/app/genealogy-bootstrap-operations/{operationKey}`,有效参数只有 operationKey/clientid且没有 request body,响应集精确为 200/400/401/404/429/500,禁止泄漏性 403/default。响应以带显式 mapping 的 discriminator `oneOf` 关闭为 `PENDING{resolveBy,retryAfterSeconds}`、`SUCCEEDED{result}`、`FAILED_NO_COMMIT`,三个 status 均为单值 string;`x-state-transitions` 精确登记 `ABSENT→PENDING→SUCCEEDED/FAILED_NO_COMMIT`,两个终态无出边且 `x-terminal-immutable=true`,FAILED 同时固定 `x-domain-effects=NONE/x-quota-consumed=false`。PENDING 的 retryAfterSeconds 为 1—30,200 不强制 Retry-After。GET 必须纯读且始终无副作用:acceptUntil 前无记录返回 typed 404 `BOOTSTRAP_OPERATION_NOT_AVAILABLE`、服务端 acceptUntil 和 Retry-After,客户端保持 unknown;截止后无记录按 key 可计算地返回 FAILED_NO_COMMIT,不写 tombstone,迟到 POST 永久拒绝。PENDING 最迟 claimedAt 后 2 分钟终结;SUCCEEDED 记录至少保留实体生命周期,FAILED 至少 30 天;跨 account/tenant/client 统一不泄漏 404。响应不含原请求或人物 PII,operation 不进 `/mine`、不占业务 quota;GET 零写与 FAILED 零领域提交仍必须另以 DB 观测测试证明。
-
-**API-G03-004:APP 访问预设单一 owner。** 新 `GenealogyAccessPreset` 只允许 MEMBER_ONLY/PUBLIC_APPLY,并在同一版本成为 `AppGenealogyBootstrapBody`、实际 `/mine`/overview 读取所用 `AppGenealogyVo` 和闭合 `AppGenealogySettingsUpdateBody` 的唯一访问字段。删除 `GenealogyCreateBody/AppGenealogyCreateBody/GenealogyUpdateBody/AppGenealogyUpdateBody` 旧入口以及 visibility/joinMode;不保留 oneOf fallback、数字 pair 或邀请码 mode 的暗中映射。validator、runtime、双导出、fixture 迁移、G03/G05/G11 测试和文档同批更新。这里只关闭共享字段迁移;G11 写入仍须另行完成 If-Match、版本/CAS、权限刷新和结果未知门禁。
-
-**API-G03-005:可信地区、始祖不变量、认证与部署反例。** `GenealogyRegionCode` 是 1—32 位 URL-safe 词法标识;唯一地区 owner 改为 required SaToken/clientid 的 `GET /genealogy/app/region/search`,同版删除旧公共 `/genealogy/region/search`。keyword required 且 minLength=1/maxLength≤50;`RListRegionSelectVo.code/data` 和 `RegionSelectVo.regionCode/label/selectable` required,leaf 不等于 selectable,不强制层级;页面只展示 label、提交 code,POST 在业务事务中复验仍可选。通用人物写入以 typed 409 `GENEALOGY_NOT_READY` 和 422 `BOOTSTRAP_ROOT_IMMUTABLE` 覆盖 collection/PUT/DELETE/parents;PUT operation 以 `x-bootstrap-root-editable-fields=[name,sex,birthDate,biography]` 和 `x-bootstrap-root-noneditable-policy=REJECT_422_BOOTSTRAP_ROOT_IMMUTABLE` 精确锁定仅四项可编辑,其余字段一律 422。create/status/settings/region及相关人物私有响应必须是 JSON+private/no-store;同一后端模型重导后先由 `openapi-yaml-json-parity-runtime-smoke.js` 以无损任意精度数字和严格 YAML mapping 语法深比较完整 JSON/YAML,再递归检查组合 schema 字段。以匿名、错 client、跨账号 status、unsafe 数字 ID 差一、地区失效、quota race、同 key 并发、control/business/terminal 各写点 fault injection、GET 零写、根 PUT 白名单及其他绕过、超时/5xx/畸形响应和正式 HTTPS/CORS 验证文档与部署一致。
-
-**客户端关闭后的唯一流程:** 第一步只校验并进入页内始祖步骤;最终校验后冻结 canonical snapshot,先持久 `{sessionEpoch,operationKey,startedAt}` 再 POST。本地校验或可证明零发出的 request-build 失败不留 marker;服务端在 claim 前返回的 400/401/403 清 marker,401 同时清会话;`IDEMPOTENCY_KEY_REUSED` 进入 fatal/quarantined,不查装 status、不自动换 key,只有用户看到警告并显式放弃才清;确定未提交的 limit/expired/422 可清。429 保持同 key/body并先查 status;500/network/timeout/408/发出后取消/意外 2xx/3xx/畸形 200 都保持 marker按 unknown 查询。status 截止前 404 保持,400 清损坏 marker,401 走会话失效,429/500/network/cancel/unexpected/malformed 保持退避,FAILED_NO_COMMIT 才允许新 key。冷启动只查 status,不保存姓名/生日/生平、完整 body或可逆日志。SUCCEEDED 唯一次序为 committed receipt → 失效或定点更新 `/mine` → 安装 context → G05;context/导航失败不重发创建。落地时删除 local preview/mock create 与旧禁止 API 断言,不能长期并存两个创建 owner。
-
-**页面与关闭条件:** 地区搜索、PENDING、unknown、fatal/quarantined、committed、context/导航失败必须可见;默认 UNKNOWN,删除 1800/UTC 日期错误;label、radio、aria-invalid/describedby、首错聚焦、至少 44dp 原生按钮、AppDialog 焦点与状态播报同批实现。后端同版本 JSON/YAML 必须通过 `tests/g03-bootstrap-openapi-contract.ps1`,客户端实现必须另行通过会实际执行状态机套件的 `tests/g03-bootstrap-client-release-gate.ps1`;它们只是 G03 自身两门禁,真实开放还要求 Task26 workspace 读取门禁、聚焦/全量回归和 MuMu 原生字号、TalkBack、键盘、慢网、双击、杀进程及 Android 返回矩阵全部通过。
-
-当前其余已知但尚未核实的重点依赖包括:微信登录、公共行为验证、完整短信状态机、邀请码验证与直接加入、结构化亲属关系、上级家谱与支系权限、管理员授权与功能开关、上传与系统权限、消息业务目标、系统分享、订单支付与退款。它们只表示审查重点,不预判后端一定缺失。
-
-### 5.13 后端问题单 API-JOIN-001—006
-
-**优先级:** P0;阻塞 G06/G08/G09/G10 普通申请、撤回和审核的真实闭环。邀请码直入不属于本问题单。
-
-**API-JOIN-001:七个稳定 owner、词法身份与 cursor。** 发布设计 23.10 的七个 operationId;三个列表分别返回专用 page/item,不返回 total,limit 1—50,cursor 绑定 tenant/account/client/filter;搜索按 updatedAt+genealogyId,mine/pending 按 submittedAt+applyId 稳定排序。genealogyId/applyId 均引用 1—128 位 URL-safe string owner;搜索 viewerState 只允许 NOT_JOINED/MEMBER/PENDING/REJECTED/FORMER_MEMBER/OWNER,不另发 canApply。
-
-**API-JOIN-002:闭合投影与文本。** 申请体仅 `applicantName/relationDesc/applyReason?`,前两项 required;审核体仅 APPROVE 或 REJECT+required rejectionReason 两分支。三项申请文本和拒绝原因共用 `JOIN_APPLICATION_TEXT_V1`。mine 使用四状态 discriminator且拒绝分支必有可见原因;pending 精确五字段并递归禁止手机号、用户、邀请人和审核人。删除旧 APP join DTO 和通用响应引用。
-
-**API-JOIN-003:幂等、恢复、零写与准入协调。** request key 为 `gja.{issuedAt}.{CSPRNG}`,600/300/120 秒边界;canonical identity 覆盖 method/path/genealogyId/tenant/account/client/body。parameter/response 只允许 exact local 分区引用;幂等 scope、活动唯一 scope、事务 effects、重验字段、状态迁移和 cursor 扩展必须是真实 JSON 数组,逗号字符串不能伪装集合。数据库唯一约束保证同账号同谱一个 PENDING;POST 在事务内重验 READY、PUBLIC_APPLY 与 applicationEligibility,并与 G11 设置 PUT 共享 `x-public-apply-coordination=ATOMIC_SINGLE_WINNER`,关闭公开申请与新准入竞态只允许一方提交。申请行与 SUCCEEDED receipt 同事务。新增纯读 status GET,三态转换和终态不可变;窗口内 404、窗口后零写 FAILED、跨主体非泄漏 404、迟到 POST 拒绝,客户端只持久无 PII marker。
-
-**API-JOIN-004:撤回。** DELETE 以 PENDING CAS 决定唯一赢家;相同撤回只重放 WITHDRAWN typed 200,审核或其他终态获胜时返回 typed 409+最小 current state,不存在或越权统一 404。key 复用、key 过期与活动 PENDING 冲突不强制返回不存在的申请 current。
-
-**API-JOIN-005:审核。** PUT 在事务内重验权限、READY、PUBLIC_APPLY,执行 PENDING CAS、唯一成员关系和终态;相同决定只重放 APPROVED/REJECTED 原 200,绝不返回 WITHDRAWN;相反决定或不同规范化拒绝理由返回 409。POST 的 409 精确引用 `RJoinApplicationKeyConflict`,DELETE/PUT 的 409 精确引用 `RJoinApplicationStateConflict`,不得共享会接纳跨操作业务码的宽联合 owner。无 applicationVersion、If-Match 或详情端点。
-
-**API-JOIN-006:安全与发布。** 所有响应精确 typed JSON、private/no-store,429 和 status 窗口内 404 带 Retry-After;禁止 default、3xx、`*/*`、200 包认证错误、int64 和通用 RList/RObject/RVoid。后端以真实账号、数据库观测、并发与 fault injection 证明 cursor、唯一约束、fencing、零写、事务、跨主体不泄漏和正式 HTTP/CORS;OpenAPI 静态扩展不替代实现证据。
-
-**关闭条件:** 同版本双导出通过 `tests/join-application-openapi-contract.ps1`;再完成后端运行时反例、客户端 marker/status/CAS 收敛测试、旧 adapter/手机号/消息承诺/LOCAL_WITHDRAWN 原子删除、全量回归和 MuMu 320/360/412、系统字号、TalkBack、键盘、返回、双击、慢网、断网、杀进程矩阵。当前门禁输出 `JOIN-APPLICATION-OPENAPI-CONTRACT BLOCKED`,页面保持本地预览。
-
-### 5.14 后端问题单 API-INVITE-001—006
-
-**优先级:** P0;阻塞 M08 邀请签发、G06 邀请码解析与直接加入。普通申请继续由 API-JOIN 唯一拥有。
-
-**API-INVITE-001:六个专用 owner 与流程隔离。** 发布 23.11 的 list/issue/revoke/resolve/redeem/redemption-status 六 operation,required SaToken/clientid、词法 genealogy/ticket/membership ID、operation-specific typed responses。G06 直接确认兑换,G08 只保留普通申请;普通申请 body 反向禁止 inviteCode/ticket/token。禁止平行旧入口、通用 promotions、礼仪邀请或普通申请 POST 承担本域。
-
-**API-INVITE-002:单次秘密票据。** 原码固定版本前缀+26 位 Crockford Base32 随机量、至少 128 位熵、24 小时单次使用;HMAC 查找,KMS 密文仅保留 600 秒幂等恢复窗。列表只返回最多 20 个活动元数据;原码只允许 issue 200 指定位置,redemption token 只允许 resolve 200 指定位置,并对所有响应 `$ref/oneOf/allOf/items` 递归检查秘密与 PII 闭包。
-
-**API-INVITE-003:签发、权限与撤销。** issue 无 body,`gii` key 按 method/path/genealogy/tenant/account/client 唯一;已存在 key 不受首次接受窗影响,不同 digest 优先冲突,600 秒内返同码、窗后返同 ticket metadata+`ISSUED_SECRET_UNAVAILABLE` 且不新建。ticket、HMAC、KMS 密文与 request receipt 原子提交。workspace `canInviteMembers` 唯一映射服务端 `INVITE_MEMBER`;list/issue/revoke 均重验并只管理 actor 自己签发的票据,跨 issuer 404;活动上限由数据库约束。DELETE 以 ACTIVE→REVOKED CAS,相同撤销重放 200,CONSUMED/EXPIRED typed 409 current;撤销与兑换只有一个赢家。
-
-**API-INVITE-004:安全解析与原子兑换。** resolve 的原码只在 JSON body,不消费票据或建立成员但可轮换唯一短时 grant 摘要,并统一 `INVITE_TICKET_NOT_AVAILABLE`、多维限流与时间侧信道控制;返回最多五分钟且绑定 actor/client/ticketVersion/genealogy/authorizationEpoch 的敏感 token。redeem 无 body,事务谓词包含 token、版本、数据库时钟过期、unused、READY、功能、签发者权限、账号资格和容量;票据消费、唯一 MEMBER 与回执同事务。ALREADY_MEMBER、活动普通申请、账号禁用或票据失效均不得消费票据。
-
-**API-INVITE-005:幂等与 unknown 恢复。** `gir` key 的 canonical identity 包含 token identity/ticket/genealogy/actor/client;同 key 不同 identity typed 409。600/300/120 秒边界、control claim、fencing/watchdog 和纯读 status 固定 PENDING/SUCCEEDED/FAILED_NO_COMMIT;窗口内 404 带 acceptUntil/Retry-After,窗口后零写计算 FAILED,跨主体统一 404。已存在终态优先,终态回执至少保留 30 天且晚于 30 天客户端 marker 清理;清理后不得据 absence 否定领域写。客户端只持久无秘密 marker,成功后只重试 workspace/context/导航本地收口。
-
-**API-INVITE-006:安全、无障碍与发布。** 所有响应 JSON+private/no-store,429 带 Retry-After;URL/query/storage/log/APM/分析/崩溃报告/自动测试和发布证据截图零秘密,用户主动显示、复制或系统分享必须先提示风险且不得自动触发。后端以真实数据库并发、fault injection、权限降级、猜码、两人同码、同人两码、撤销竞态、日志审计与 HTTP/CORS 证明实现,静态扩展只登记意图。客户端原子删除 `JP2026`、fixture target、invite→G08 与 G08 invite 分支;补原生按钮、44dp、tab/label/aria、状态播报、长码换行、冻结和 MuMu 全矩阵。
-
-**关闭条件:** 同版本双导出通过 `tests/invite-ticket-openapi-contract.ps1`,再通过后端运行时反例、客户端 coordinator 测试、Task36 普通申请隔离、workspace/context 收口、全量回归及 MuMu 320/360/412、1.3 倍字号、TalkBack、键盘/粘贴、双击、慢网/断网、杀进程、Android 返回和系统分享取消。当前输出 `INVITE-TICKET-OPENAPI-CONTRACT BLOCKED`,页面不得接假接口。
-
-### 5.15 后端问题单 API-SETTINGS-001—006
-
-**优先级:** P0;阻塞 G11 家谱设置真实读取、并发写入、访问规则切换与发布。
-
-**API-SETTINGS-001:唯一 read/write 与共享字段 owner。** 保留全局唯一 `appUpdateGenealogySettings` PUT,递归拒绝旁路 settings 写、任一 `genealogyName/intro/accessPreset` 单字段第二 body owner以及外部/错分区同名 `$ref`;`/genealogy/app/genealogies...` 写 body 根层 `intro` 明确保留给设置,子域使用自身字段名。删除 generic GET 且不新增 PATCH;overview 是 G11 canonical baseline 唯一读取 owner,并由 workspace 门禁以 schema 闭包与 allOf 合成排除旁路详情。发布共享非 null `GenealogyName/GenealogyIntro/GenealogySettingsVersion`:名称拒绝换行/控制字符,简介只允许内部 LF并拒绝 CR/tab/其他控制字符,让 bootstrap、settings body 与 `AppGenealogyVo` 引用同一 24/80/版本合同;`GenealogyAccessPreset` 继续由共享 owner 唯一持有且禁止 nullable。200 复用关闭额外字段的 `RAppGenealogyVo`,不建重复 snapshot。
-
-**API-SETTINGS-002:原子 dirty-only merge。** body 关闭额外字段、1—3 个出现字段,省略保持、intro 精确空串清空、null/空白/旧 pair/其他设置全部早失败。事务内锁定并重验 tenant、资源、权限,只应用出现字段;任一字段或迁移前置失败整笔零写。canonical no-op 保留版本且不产生额外领域副作用。
-
-**API-SETTINGS-003:版本 CAS 与非泄漏权限。** `AppGenealogyVo.settingsVersion` 和 If-Match 共用 1—128 位 opaque owner,并以 `x-version-scope-fields`/`CANONICAL_SETTINGS_CHANGE_ONLY` 限定只在 canonical 设置实际变化时更换;旧版本精确 409+current,不发布 412/ETag 双轨。只有仍有权限者可得到版本/current;跨主体统一 404,权限撤销 403。冲突 precedence 为 version→READY→active pending,409 wrapper 只含 discriminator/oneOf 且分支均为 exact local ref,正式 H5 CORS 允许 If-Match。
-
-**API-SETTINGS-004:访问迁移与申请串行化。** 活动 PENDING 只阻断真实 PUBLIC_APPLY→MEMBER_ONLY,返回无 PII 的 `ACTIVE_PENDING_APPLICATIONS` 并让客户端引导 G10;不阻断其他字段/no-op,不自动拒绝或撤回,不改变邀请合同。设置 PUT 与任务 36 新申请 POST 都在事务内重验 genealogyState/accessPreset,申请另验 eligibility,并共享 `x-public-apply-coordination=ATOMIC_SINGLE_WINNER`;竞态只允许一方提交,不把合同绑死为某种数据库隔离级别。
-
-**API-SETTINGS-005:typed 响应、unknown 与缓存。** 精确 200/400/401/403/404/409/422/429/500,只允许 JSON;每个 response 必须含单值 enum private/no-store,429 另有 Retry-After;只允许非语义 tracing header:`traceparent/tracestate/x-request-id/x-correlation-id`,禁止 ETag 与其他语义 header,所有 component `$ref` 必须 exact local。四种 tracing header 若内联,只接受 allowed-key 关闭且带非 null 的 string schema 的 Header Object。标量、引用字段、成功/错误 envelope 与 fieldErrors 以 allowed-key 集关闭 `nullable`、readOnly/writeOnly、冲突组合和额外验证关键字;409 使用纯 businessCode discriminator 三分支,422 只返回三个字段错误,500 明示 outcome unknown。后端与客户端用真实账号、数据库观测、并发和 fault injection 验证零部分写、版本、权限与申请竞态;unknown 只以 fresh overview 对账,成功失效 mine/overview/search/preview 并重验 context。
-
-**API-SETTINGS-006:客户端、无障碍与发布。** 同版双导出绿后,客户端首写先建可执行生产模块的纯 Node 失败测试,再实现 adapter/coordinator 并原子删除 fixture pair、timer、本地成功和 API 禁用旧断言;禁止恒红、token 扫描或测试内参考实现冒充行为证据。G11 覆盖原生 button/radio、label、aria-invalid/describedby、首错聚焦、busy/live、44dp、长文换行、返回冻结和冲突/unknown 草稿保留。OpenAPI、workspace/shared owner、客户端行为门禁、全量回归及 MuMu 原生矩阵任一未绿都不得接远端。
-
-**关闭条件:** 后端从同一版本重导 JSON/YAML 并同时通过 workspace、join 与 `tests/g11-settings-openapi-contract.ps1`,再完成真实权限/版本/待审竞态/fault injection/HTTP/CORS;客户端随后按测试先行完成可执行 coordinator、页面/缓存/context 原子迁移,最后通过聚焦/全量和 MuMu 320/360/412、1.3 倍字号、TalkBack、软键盘、双击、慢网/断网/杀进程、Android 返回、权限撤销与版本竞态。当前输出 `G11-SETTINGS-OPENAPI-CONTRACT BLOCKED`,48 项缺口;受保护 OpenAPI 未修改。
-
-### 5.16 后端问题单 API-POEM-001—006
-
-**优先级:** P0;阻塞 G12 字辈集合真实读取、原子保存、并发恢复、T01 正式消费与发布。
-
-**API-POEM-001:唯一 owner 与 canonical 模型。** 发布唯一 `GET/PUT /genealogy/app/genealogies/{genealogyId}/generation-poems` 和 `appGetGenerationPoemSet/appUpdateGenerationPoemSet`,删除 collection POST、逐行 PUT、batch preview/save、management 及旧 DTO/response;不新增 preview token/status。GET/PUT 200 共用 closed `RGenerationPoemSetSnapshot → GenerationPoemSetSnapshot`,精确 required genealogyId/poemSetVersion/items,ACTIVE-only 且按 generationNo 升序;GET 重验 canView,PUT 事务内重验 tenant/canEditContent/READY。
-
-**API-POEM-002:完整候选、软停用与原子写。** body 唯一为 closed required `AppGenerationPoemSetUpdateBody {items,disableMissing}`。items 0—500 严格 generationNo 升序;已有 ID 只允许 baseline ACTIVE 且可显式 move,新行省略 ID,disabled/unknown ID 失败,重复文本允许。false 保留遗漏 baseline,true 软停用;empty false no-op,empty true 停用全部。先校验声明严格升序,再构造声明目标与完整 merged candidate,随后按固定步骤验证唯一/slot/连续/最终容量、分配并校验新 ID,最后原子写;`GENERATION_SLOT_CONFLICT` 与所有校验失败零写,swap 必须显式声明全部受影响行,历史绝不物理删除。
-
-**API-POEM-003:版本 CAS 与 Unicode。** `GenerationPoemSetVersion` 是 1—128 位 opaque、不可解析、永不复用的 ACTIVE 语义版本,PUT required If-Match,body 无版本,禁止 ETag/412;no-op 保持版本,实际变化生成新版本。poemId/version 均保持词法字符串。`GenerationPoemText` 为 NFC、1—50 Unicode code point、well-formed UTF-16、无边界空白,拒绝控制字符、CR/LF/tab、bidi override/isolate/mark、zero-width/BOM/word joiner、行段分隔符和孤代理;generationNo 是 1—2147483647 的唯一排序 owner。
-
-**API-POEM-004:typed HTTP、security 与部署 CORS。** GET 精确 200/400/401/404/429/500,PUT 另有 403/409/422;全部 typed `application/json`、private/no-store,429 带 Retry-After,禁止 default/3xx/`*/*`/通用 envelope/200 包业务错。SaToken 精确为 Authorization header apiKey,operation security 是数组且 scopes 为空,clientid required 非空。顶层 closed `APP_GATEWAY_PREFLIGHT` policy 精确允许四个请求头、GET/PUT/OPTIONS、部署 allowlist 与 600 秒;GET/PUT 引用它。后端必须用正式 H5 origin 的真实 OPTIONS/preflight、凭证、拒绝 origin/header/method 反例证明 gateway 实现。
-
-**API-POEM-005:冲突、unknown 与缓存收口。** 409 只含版本变化+current 与 READY 两分支,422 只含可达请求/候选错误。网络、超时、408、取消、5xx 和畸形 2xx 是 unknown;客户端冻结 baseline/version/declared/disableMissing/sessionEpoch,构造 effective target 后 fresh GET。existing/NEW、同基数、无额外行和版本策略必须按 `FRESH_GET_THREE_WAY_NO_AUTO_PUT` 执行;current==target 优先且不归因,current==old 才可由用户明确重试,其他进入 divergent,不自动 PUT。成功 canonical 回填并失效字辈消费者缓存;权限、READY 或账号变化失败关闭。
-
-**API-POEM-006:客户端、无障碍与发布。** 同版双导出通过主门禁、zero issues 对抗合同和 Unicode Node 冒烟后,客户端首写先建直接执行生产 normalizer/coordinator 的失败测试,再实现唯一 adapter/coordinator,并原子删除 fixture、timer、本地成功、旧 preview/save 断言与兼容分支。页面覆盖清空确认、loading/empty/editing/saving/saved/unknown/conflict/no-permission、live region、首错聚焦、44dp 和返回冻结;MuMu 覆盖 320/360/412、字号、TalkBack、键盘、0/1/500×50、swap、双击、断网/杀进程、权限撤销、READY 与账号切换。
-
-**关闭条件:** 后端同版本重导 JSON/YAML 并通过 `tests/g12-generation-poem-openapi-contract.ps1`、对抗合同、真实 DB/并发/fault injection/HTTP/CORS;客户端随后通过生产行为测试、页面原子迁移、聚焦/全量回归与 MuMu 矩阵。当前输出 `G12-GENERATION-POEM-OPENAPI-CONTRACT BLOCKED`、`Issues: 72`;`G12-GENERATION-POEM-OPENAPI-ADVERSARIAL-CONTRACT PASS` 和 `G12-GENERATION-POEM-UNICODE-RUNTIME-SMOKE PASS` 只证明门禁质量,不解除后端红灯。受保护 OpenAPI 未修改。
-
-### 5.17 后端问题单 API-FEED-READ-001—006
-
-**优先级:** P0;阻塞 F01 动态列表和 F03 动态详情/一级评论的生产读取。发布、点赞、评论/回复写及媒体读取不属于本问题单。
-
-**API-FEED-READ-001:三个稳定 owner 与旧入口删除。** 发布谱内嵌套的 `appListFamilyFeeds/appGetFamilyFeed/appListFamilyFeedRootComments`,全局各唯一;删除两个 `/page` GET,collection GET 使用 cursor。保留 `(genealogyId,feedId)` 复合资源边界,不新增可枚举的全局 feed 路由,不用写方法或 replies 冒充读取 owner。
-
-**API-FEED-READ-002:词法身份与无 PII 最小 projection。** GenealogyId/FamilyFeedId/FamilyFeedCommentId 均为 opaque string。Feed 只含 `feedId/feedContent/authorDisplayName/publishedAt/hasMedia`,root comment 只含 `commentId/commentContent/authorDisplayName/publishedAt`;closed、required、非 null、有界。排除手机号、账号/业务用户 ID、tenant、status、remark、审核字段、parent/level、删除占位、内部媒体 ID 与持久化字段。`hasMedia` 只触发诚实占位;title/tag/like/count 不从 fixture 或正文猜测。
-
-**API-FEED-READ-003:对象级授权与非泄露 404。** 每次/每页 fresh 验 tenant、genealogy、membership;详情和评论再验 feed 属于 path genealogy 且可见,评论只读正常 root。未知、错谱、删除/隐藏、撤权、跨主体或 cursor 跨 scope 统一 `FAMILY_FEED_NOT_AVAILABLE`,禁止 403 分流资源存在性;未认证才返回 401。
-
-**API-FEED-READ-004:keyset cursor 与读取窗口。** `cursor? + limit?`,默认 20、1—50,无 total/pageNum;nextCursor 缺席即结束。feed 用 publishedAt/feedId 倒序,root comment 用 publishedAt/commentId 正序,时间不可变、ID ordinal tie-break。cursor 绑定 actor/session/client/scope/projection/order/limit/windowUpperBound/lastTuple,篡改或过期 typed 400。`UPPER_BOUND_KEYSET_LATEST_VISIBLE` 排除刷新前新增,后续删除/隐藏省略、编辑返回最新可见内容,不伪称严格 snapshot。
-
-**API-FEED-READ-005:typed HTTP、安全与部署。** 三 GET 精确 200/400/401/404/429/500,只允许 closed typed application/json、private/no-store;429 Retry-After。SaToken 必须是数组且空 scopes,clientid required 非空;禁止 int64、通用 RList/RObject/PageResult、default/3xx/`*/*`/HTTP 200 业务错。复用 `APP_GATEWAY_PREFLIGHT`,正式 OPTIONS/preflight 与拒绝反例由部署证明。
-
-**API-FEED-READ-006:证据与客户端激活。** 主门禁先以 zero issues 合法种子和 ref/大小写/HTTP 方法/PII/int64/offset/404 分流对抗变异证明自身,再要求后端同版本 JSON/YAML/live、真实权限撤销/跨谱 cursor/并发可见性/HTTP/CORS。后端绿后首写必须是执行生产 read normalizer/coordinator 的 Node 失败测试,再原子迁移 F01/F03,删除 fixture 锁、嵌入 comments、伪重试和旧 fixture 断言;远端失败不回退 mock。完成 sessionEpoch、局部错误、媒体占位、焦点/滚动、无障碍和 MuMu 矩阵后才可发布。
-
-**关闭条件:** `tests/family-feed-read-openapi-contract.ps1`、对抗门禁、后端运行时反例、同版本三份接口证据、客户端生产行为测试、聚焦/全量回归与 MuMu 矩阵全部通过。当前输出 `FAMILY-FEED-READ-OPENAPI-CONTRACT BLOCKED`、`Issues: 85`;`FAMILY-FEED-READ-OPENAPI-ADVERSARIAL-CONTRACT PASS MUTANTS=58` 只证明门禁质量,不解除后端阻塞。受保护 OpenAPI 与 F01/F03 页面未修改。
diff --git a/docs/视觉资产与构建基线.md b/docs/视觉资产与构建基线.md
deleted file mode 100644
index 556bbd6..0000000
--- a/docs/视觉资产与构建基线.md
+++ /dev/null
@@ -1,100 +0,0 @@
-# 视觉资产与构建基线
-
-> 状态:当前有效
-> 更新日期:2026-07-22
-> 适用范围:正式运行时图片、可重建视觉资产、构建清单、质量报告与 MuMu 视觉验收
-
-## 一、所有权边界
-
-视觉资产分为两类,不能用同一套字段混写:
-
-1. 已提交二进制:由业务域运行时清单锁定路径、像素尺寸、透明度、字节数与 SHA-256;它们的 `provenance` 必须为 `committed-binary`,且 `rebuildable` 必须为 `false`。
-2. 可重建资产:由 schema v3 生成清单锁定母版、处理参数、物理输出尺寸和质量阈值;运行时清单只导入它,不复制物理规格。
-
-schema v3 注册入口是 `design-pipeline/manifests/runtime-assets.json`。任何新增的 `runtime-asset-inventory` 或 `asset-build-manifest` 都必须进入该注册表的导入闭包;未注册 owner、重复资产 `id` 与重复正式输出都会被拒绝。当前 `static/assets` 中的每个文件都必须恰好属于一个正式 owner,并至少存在一个真实运行时消费者。
-
-导航任务 3 删除了无活动消费者的通用页面旧入口,并同步删除两张仅靠该入口人工补数的 notification frame。当前注册表闭合 `77` 个正式 `static/assets` 输出;family/profile/records 的同名 frame 仍有真实专项 mixin 消费,`ModulePageBackground` 仍有活动页面消费者,均继续保留。`tests/retired-module-page-contract.ps1` 是这次退役边界的防回归所有者。
-
-认证直接资产由 `design-pipeline/manifests/auth-runtime-assets.json` 管理,其余无法重建但仍被产品消费的直接二进制由 `design-pipeline/manifests/application-runtime-assets.json` 管理。四张共享卷轴、六张长页面背景和 G01 空态边框的生成事实依次只属于 `design-pipeline/manifests/shared-scroll-skins-v3.json`、`design-pipeline/manifests/page-backgrounds-v3.json` 与 `design-pipeline/manifests/g01-state-frame-v3.json`。
-
-页面、组件、样式、数据映射和工具代码本身是消费者关系的唯一事实源。生成清单不得保存槽位、Vue 组件、选择器、`uni-app mode`、消费者列表或其他运行时渲染语义;这些规则只能由实际消费者源码及对应合同拥有。
-
-## 二、schema v3 生成清单
-
-生成清单只允许以下职责:
-
-- `source`:仓库内可追溯母版;
-- `processing`:实际由构建器消费的色键、端帽、调色板等处理参数;
-- `output` 与 `outputPixels`:正式输出路径和像素尺寸;
-- `alpha`、`edge`、`quality`:由质量分析器真实执行的透明边、边缘污染、体积和色彩空间约束。
-
-清单、资产及其嵌套对象均拒绝未知字段。不能用近似字段名重新塞入旧合同,也不能声明构建器或质量分析器没有执行的规则。
-
-## 三、Python 与依赖
-
-Python 依赖由 `design-pipeline/requirements.txt` 锁定,当前 Pillow 版本为 `12.3.0`。唯一解释器解析逻辑位于 `design-pipeline/scripts/python-runtime.mjs`,顺序为:
-
-1. 显式 `PYTHON`;
-2. `design-pipeline/.venv`;
-3. Windows Python Manager 的真实入口;
-4. 可实际执行的系统命令。
-
-所有 Python 构建和测试都通过统一执行器加入 `-B`,禁止在源码目录生成 `__pycache__` 或 `.pyc`。不透明缩放、居中 cover 裁切与暖金边框提取统一由 `design-pipeline/scripts/build_raster_assets.py` 实现,Node 入口只负责严格清单校验、解释器编排和质量审计,不再保留 G01、模块背景或 Sharp 专用分支。
-
-## 四、当前验证命令
-
-在 `design-pipeline/` 目录运行:
-
-```powershell
-npm.cmd test
-npm.cmd run validate:shared-scroll-skins
-npm.cmd run validate:page-backgrounds
-npm.cmd run validate:g01-state-frame
-npm.cmd run validate:runtime-assets
-npm.cmd run build:shared-scroll-skins
-npm.cmd run build:page-backgrounds
-npm.cmd run build:g01-state-frame
-npm.cmd run verify:shared-scroll-skins
-```
-
-其中 `npm.cmd test` 同时执行 Node 和 Python 测试。质量报告只允许保存工作区相对路径;同一母版与相同参数连续构建必须产生相同字节哈希和相同报告。
-
-在项目根目录运行:
-
-```powershell
-powershell -ExecutionPolicy Bypass -File tests/runtime-assets-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/retired-asset-removal-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/retired-module-page-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/a01-retired-pipeline-removal-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/a01-no-photoshop-pipeline-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/mumu-visual-acceptance-boundary-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/project-responsive-layout-contract.ps1
-powershell -ExecutionPolicy Bypass -File tests/compile-audit.ps1
-```
-
-## 五、视觉验收
-
-- 当前只维护用户确认的浅色国风主题;深色与跟随系统延期到后续独立版本,不能在页面内散落未生效的主题入口或覆盖样式。
-- 内部响应式基线为 `320×568`、`360×640`、`360×800`、`412×915`;G01 连续长背景另做 `412×1000` 压力检查。这些内部尺寸不能替代最终 MuMu 证据。
-- 浏览器截图只可用于逻辑调试,不能作为视觉通过证据。
-- 仓库不再维护自动浏览器截图助手、联系表或截图自证合同;浏览器运行时测试只保留 CDP、DOM、状态、溢出和内容可达性断言,不写入截图。确需临时截图调试时应使用仓库外命令,不能提交为长期证据。
-- 最终视觉复核只能使用用户当前在线的 MuMu 安卓模拟器,不得由代理启动、关闭或调整模拟器。
-- 生成成功和像素质量通过不等于页面视觉通过;相关页面仍需在 MuMu 检查默认、错误、取消、完成和重复进入等实际状态。
-- 不通过压缩字号、行高、控件尺寸或单设备补丁掩盖布局问题。
-- 普通页面、卡片、表单和说明由内容自然撑高;只有弹窗和明确独立滚动区域可以使用视口 `max-height` 与内部滚动。
-- 九宫格和 `border-image-slice` 的唯一所有者是 `styles/adaptive-frame-profiles.scss`;Vue 页面和组件只能消费其公开混入,不能直接重复声明。
-- 响应式扫描范围只属于 `tests/responsive-layout-coverage.json`,固定尺寸例外只属于 `tests/responsive-layout-allowlist.json`。
-- 安全区、软键盘、约 `1.3` 倍系统字号、长文本和 Android 返回手势必须在对应页面验证;主要触控目标不小于约 `44dp`。
-- G 系列共享连续家谱背景,T、F、R、N、M 使用各自模块背景;具体消费者、渲染方式和当前视觉数值只由源码及机器合同拥有,本文件不复制尺寸、哈希、透明度或选择器。
-- G 系列背景映射只由 `components/GenealogyPageBackground.vue` 消费,当前正式运行图是 `static/assets/modules/genealogy/opaque/genealogy-page-background-long.png`;T、F、R、N、M 的映射只由 `components/ModulePageBackground.vue` 消费。等比、裁切、贴底和透明度等渲染数值继续由这两个组件拥有。
-- 复杂水墨、品牌装饰和完整视觉面使用正式位图;文字、布局、状态与交互由代码承担。整页截图不得成为运行时资产,可变高度装饰不得绕过共享九宫格所有者。
-- 用户可见示例姓名统一使用“某某某”等通用表达;fixture 和 mock 数据可以保留真实感测试样本,但不能把样本姓名写成产品提示。
-
-## 六、参考图与正式资产边界
-
-以下两张图片是用户已批准的 A01 选型证据,只用于后续人工视觉复核,标记为 `reference-only / non-runtime`,不进入运行时注册表,也不能因零代码引用被删除:
-
-- `docs/design/assets/a01-vnext/A01-shared-scroll-skins-with-dialog-approved.png`
-- `docs/design/assets/a01-vnext/A01-shared-skin-family-option-2-selected.png`
-
-G01 的 A/B/C 方向候选、无确定变换的 add-sheet/close 色键源、重复的旗舰 ImageGen 源、旧 `static/icons` 和阶段 0 当时存在的未接入 TAC 旧批次已经退役。`static/tac/` 当前共 5 个文件:4 个后端提供的供应商文件保持原字节,项目只新增 `static/tac/js/jiapu-tac-adapter.js` 作为唯一协议适配层。A01/A04/A05 已通过 `components/TacVerification.vue` 形成真实运行时消费者;这组供应商资产不是视觉构建管线的可再生输出,不进入 `runtime-assets.json`,其存在性、精确文件集合、消费者和哈希由 `tests/auth-tac-integration-contract.ps1` 唯一拥有。受保护哈希分别为 `tac.css=181694518971a9f991d551b6a6e6dab2bf750f940bfc1673a158213f92eedbe0`、`tac.min.js=505f73c051908d7b805db458990790be3e91f792c4001cec0ea9377d7d302b55`、`icon.png=53e37ffc5bb81c46e6306b7d61d2eaa3de57e47ca6cdb8d5210022ae815c21c2`、`dun.jpeg=d9178a8c4cca36e3df6c3acd7e895ce9d34dd60ef3f1cf4a70c94d4324ed96e7`;不得修改、格式化、覆盖或以重新下载文件替换。正式 add-sheet 与 close 位图作为 `committed-binary` 由 `application-runtime-assets.json` 锁定;六张长背景及 G01 空态边框则保留可执行母版和 schema v3 构建链。不得重新引入候选入口、虚构可重建关系或复制第二套 TAC 资产所有权。
diff --git a/docs/迭代进度记录-2026-07-31-完成70%.md b/docs/迭代进度记录-2026-07-31-完成70%.md
deleted file mode 100644
index ae0c14a..0000000
--- a/docs/迭代进度记录-2026-07-31-完成70%.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# 家谱 App 迭代进度记录(完成 70%)
-
-日期:2026-07-31
-当前分支:`main`
-
-## 本轮已完成
-
-- 完成全项目字体可读性与长文本换行治理,优先保证手机端、长辈用户的阅读体验。
-- 调整公共页头:项目名称“代代相传”以“Logo + 名称”组合呈现,页面功能标题保持居中;认证页与“我的”页同步使用该品牌组合。
-- 接入默认头像:男性使用男童国风头像,女性使用唐装女性头像;未选择性别时默认使用男性头像。
-- 完善成员资料展示,隐藏不应面向普通用户展示的业务用户与内部人物编号信息。
-- 修复“我的”、家谱、家族、人物录、通知等模块中已发现的文字截断、状态提示与空/错误态表达问题。
-- 保留 T02 世系谱的参考项目结构,仅做兼容性和可读性处理,未改变其核心展示逻辑。
-- 新增并通过默认头像、个人资料、消息中心等重点契约检查。
-
-## 当前状态
-
-- 整体功能与视觉治理进度:约 70%。
-- 页面入口已完成全局品牌标识覆盖;业务页面仍可继续在真机/模拟器逐页复核细节。
-- 相册图片是否能展示取决于接口是否返回可访问的图片地址;当前不伪造图片链接。
-
-## 在另一台电脑运行
-
-1. 拉取 `main` 分支的最新代码。
-2. 使用 HBuilderX 导入项目根目录 `jiapuapp`。
-3. 等待 HBuilderX 完成编译后,选择“运行到 Android App 基座”并连接 MuMu 或真机。
-4. 项目所需头像和页面静态资源已随代码提交,不需要单独拷贝资源文件。
-
-## 后续建议
-
-- 在目标设备尺寸上复核页头品牌组合、表单按钮与底部导航的间距。
-- 继续覆盖未登录、空数据、接口异常和超长文本等状态。
-- 按接口返回能力补充相册图片的真实访问地址或签名 URL。
diff --git a/docs/项目当前总览.md b/docs/项目当前总览.md
deleted file mode 100644
index 1377da4..0000000
--- a/docs/项目当前总览.md
+++ /dev/null
@@ -1,317 +0,0 @@
-# 项目当前总览
-
-> 当前阶段:导航任务 1—10、TAC 认证客户端、领域上下文基础与 M07 反馈客户端已经完成;任务 36 普通加入、任务 37 邀请码直入、任务 38 G11 设置和任务 39 G12 字辈集合合同已完成三人审查与失败门禁;任务 40 F01/F03 家族动态读取已完成三方接口定案并建立专项失败门禁,正在收口门禁对抗评审与文档;T01、认证、家谱工作区、G03、加入/邀请/G11/G12、F01/F03 读取、M06、个人资料读写、通知读写、M10、M04 和 M05 后端接口门禁均为红灯,继续逐域关闭真实接口
-> 当前状态:A01/A04/A05 已接入统一 TAC、真实短信和认证请求代码,M07 已接真实反馈提交 owner;G01/G05、G03、普通加入、邀请码直入、G11、G12、F01/F03 读取、M06、个人资料读写、通知域、退出、密码与换绑域均已完成接口审查并建立失败门禁,均未猜测接线;`runtimeConfig.mode` 仍为 `mock`,MuMu 原生矩阵和真实环境联调待执行
-> 当前基准 HEAD:`f1edc6b53320755a8638c99d492250153a8dcb17`(`main`,工作区有任务 36/37/38/39 未提交变更)
-> 更新日期:2026-07-23
-
-## 2026-07-23 换机续作断点
-
-### 总目标与完成定义
-
-本项目的总目标不可缩减为“只写规划”或“只让静态测试通过”:必须在 `main` 工作区内持续推进整个 UniApp 家谱项目,按测试先行和三人交叉评审完成导航、T01 长世代世系树、TAC/认证、家谱领域数据、G/T/F/R/N/M 全量页面与接口、异常恢复、无障碍、构建及上线验证,最终交付能够正常上线使用的项目。若本地可完成的工作全部完成后只剩后端合同重导、有效测试账号、应用签名、发布凭证或 MuMu 人工操作等外部状态,才允许停在明确硬阻塞;每项阻塞必须有失败门禁、复现证据、唯一所有者、解除条件和继续步骤,不能用 mock、fixture、定时器或宽松兼容伪装完成。
-
-协作固定为当前主代理加两位评审者,共三人。三人都必须独立检查接口/字段、页面/业务闭环、交互/异常/视觉,再交叉质询并统一结论;主代理是唯一写入者,不再创建旧专家身份或增加并发评审者。普通技术取舍由三人自行收敛,不反复交给用户。系统目标已经重新固定为整个项目的可上线闭环并处于 active;只有项目真实达到完成定义时才能标记完成。
-
-### 仓库与保护基线
-
-- 当前分支为 `main`,HEAD 为 `f1edc6b53320755a8638c99d492250153a8dcb17`,上游显示 `main...origin/main`。工作区含任务 36/37/38/39 未提交修改和新增门禁,均属于当前连续治理成果;禁止用 `restore/checkout/reset` 清理,也禁止自行改分支或 worktree。
-- 本节仅记录断点,没有执行 `git add/commit/push`。由用户自行上传;换机后必须保留当前完整工作区,而不能只依赖旧远端基线。
-- 后端唯一目标地址是 `https://backend-api.ddxcjp.cn/`。受保护 `APP.openapi.yaml` 的 SHA-256 为 `8964CD583CE172425B63BBFD802F7EB587EB3641EADFD6F9D3B264FAA8090C6C`,`APP.openapi.json` 为 `87DB1DC148C5E6E877815AFF7B3A7FC7C7ECA95A2CEC50A88B42F3908961F31A`;两文件相对 HEAD 无差异。不得修改、格式化、覆盖或删除,只接受后端同一版本重新导出的双文件。
-- 不得启动、关闭或调整 MuMu。浏览器截图和源码检查不能冒充 Android 原生视觉、TalkBack、系统字号、软键盘或返回键验收。
-- 换机后 fresh 基线已重跑:任务 36 门禁前为 PowerShell `126/140`、14 项预期发布红灯;任务 36 后为 `126/141`。任务 37 新增 `tests/invite-ticket-openapi-contract.ps1` 后物理库存为 PowerShell `142`、Node `47`,全量 fresh 为 `126/142`,16 项均为明确发布红灯;任务 38 新增 `tests/g11-settings-openapi-contract.ps1` 后当前物理库存为 PowerShell `143`、Node `47`,全量 fresh 为 `126/143`,17 项均为明确发布红灯。任务 39 新增 G12 主门禁、对抗合同和 Unicode Node 冒烟后,物理库存为 PowerShell `145`、Node `48`,全量 fresh 为 `127/145`,18 项均为明确发布红灯。任务 40 新增家族动态读取主门禁与对抗合同后,当前物理库存为 PowerShell `147`、Node `48`,全量 fresh 为 `128/147`,19 项均为明确发布红灯;Node 语法 `48/48`、纯 Node `20/20`、活动 Vue 脚本 `64/64` 和编译审计均 fresh 通过。
-
-### 已完成到哪里
-
-导航任务 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`,并与状态查询的 requestKey 共用唯一 `GenealogyJoinApplicationRequestKey`:`gja.{13 位毫秒时间}.{22—43 位 base64url CSPRNG}`,随机量至少 128 位;`acceptUntil=issuedAt+10 分钟`、未来偏差最多 5 分钟、`resolveBy<=claimedAt+2 分钟`。canonical digest 唯一覆盖 method、规范 path、genealogyId、tenant、account、client 与规范 body;正文统一执行 NFC、去边界空白、CRLF/CR→LF且不折叠内部空白。同 key、同 canonical request 重放同一结果;同 key、不同 digest 返回 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`。
-- 不引入 `applicationVersion`、`If-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/json`、`Cache-Control: private, no-store`,429 带 `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` 已创建并取得精确 `JOIN-APPLICATION-OPENAPI-CONTRACT BLOCKED`;它成为七个 operation 与 APP 加入 schema 的唯一 owner,旧 `g-series-openapi-contract.ps1` 和 `core-flow-contract.ps1` 不再锁定 `phone/inviterUserId`、数字状态和 `auditRemark`。任务 36 只建立后端合同、权威文档和发布反例,不修改 G06/G08/G09/G10 业务代码;后端门禁通过前页面继续保持诚实本地预览,不写只适配当前宽松线上模型的临时代码。后续客户端批次必须删除 G10 手机号、三处消息中心承诺、`LOCAL_WITHDRAWN` 与遗留 adapter,并以状态机测试和 MuMu 证据完成原子迁移。
-
-任务 36 已完成本地门禁、`126/141` 全量回归和三人终审,后端缺口继续以发布红灯保留。当前已进入独立任务 37;完成后继续 G11 设置写入、G12 字辈真实保存,以及其余 G/T/F/R/N/M 业务域。不得一次混合导航、验证码、领域持久化和无障碍多个阶段;最终仍须完成真实后端联调、构建、签名/隐私配置、MuMu 全流程矩阵和发布终审。
-
-### 当前精确断点:任务 37 邀请码签发与直接加入
-
-三人已对 G06/G08/M08、受保护双导出和 2026-07-23 当前线上 OpenAPI 完成只读审查并交叉反驳。线上 722 条路径中只有通用 promotions 与礼仪邀请,没有家谱邀请码签发、解析、撤销或直接加入 owner。统一结论为六个专用 operation:活动票据列表、无 body 幂等签发、撤销、JSON body 安全解析、无 body 直接兑换、兑换 request-status。
-
-- 真实流程只在 G06 完成“输入原码→resolve(不消费票据、不建立成员,仅允许轮换短时 grant 摘要)→展示无邀请人 PII 的可信目标→明确确认直接加入且不经审核→redeem→status 收敛→刷新 `/mine`→安装 context→G01/G05”。邀请不再进入 G08;真实接线时删除 G06→G08 invite 导航和 G08 全部 invite source,G08 只归普通申请所有。
-- 首版票据固定单次、24 小时和至少 128 位随机量;HMAC 查找,隔离 KMS 密文只保留 600 秒同 key 秘密恢复窗。签发 unknown 只重放原 `gii` POST/key,窗后返回 `ISSUED_SECRET_UNAVAILABLE` 且不新签;客户端不持久原码。
-- resolve 原码只在 JSON body,统一非枚举错误和多维限流;最多五分钟的 redemption token 绑定 tenant/account/client/ticket/version/genealogy/authorizationEpoch,只驻内存。列表、URL/query、导航、storage、日志/APM/分析、错误和除指定成功分支外的响应闭包禁止原码/token。
-- redeem 不提交姓名、关系或理由,不创建申请、审核记录、人物或亲属关系;事务内原子完成 ACTIVE→CONSUMED、唯一 MEMBER 和成功回执。已有普通 PENDING 引导先去 G09 撤回,不由邀请流程暗改任务 36。
-- 兑换 unknown 使用 `gir` key 和 PENDING/SUCCEEDED/FAILED_NO_COMMIT 纯读状态收敛;客户端只持久 `{sessionEpoch,requestKey,startedAt}`。FAILED 保证票据未消费、成员未建,成功后的 workspace/context/导航失败只重试本地收口。
-
-`tests/invite-ticket-openapi-contract.ps1` 已测试先行创建,初次取得 `INVITE-TICKET-OPENAPI-CONTRACT BLOCKED`,经两位评审指出错误 envelope、撤销 CAS、秘密递归闭包、幂等时限、普通申请反向隔离等假绿后已加固到稳定 81 项后端缺口。文档合同、`126/142` 全量 PowerShell、Node `47/47`、纯 Node `19/19`、Vue 脚本 `64/64` 和编译审计均已 fresh 通过预期边界;当前门禁仍保持后端红灯,任务 37 已完成三人终审。后端门禁通过前不修改 M08/G06/G08 业务接线,不用 fixture、定时器或兼容分支伪装邀请码生产闭环。
-
-### 当前精确断点:任务 38 G11 家谱设置版本化写入
-
-三人已核对 G11、任务 26 workspace、任务 35 共享 accessPreset、受保护双导出与 2026-07-23 线上 OpenAPI。当前页面仍从 fixture 读取,保存只更新本页 baseline 并用 1800ms timer 显示“尚未提交服务器”;旧双导出 PUT 是宽 `GenealogyUpdateBody → RObject`,线上仍是含十个字段和 `visibility/joinMode` 的宽 `AppGenealogyUpdateBody`,两者都缺版本 CAS、typed 错误与严格权限/媒体合同。
-
-- 全局唯一写 owner 保留 `PUT /genealogy/app/genealogies/{genealogyId}`,operationId 固定且全局唯一 `appUpdateGenealogySettings`;递归拒绝 PATCH、`/settings` 旁路、任一单字段设置 body/字段写入口,以及用外部或错分区同名 `$ref` 冒充 owner,并删除重复 generic GET。`/genealogy/app/genealogies...` 写 body 根层的 `intro` 明确保留给家谱设置,其他子域必须使用 `albumDesc/articleSummary` 等自身字段名,避免把设置第二写入口伪装成通用简介。workspace 同时递归扫描成功响应闭包,拒绝任何返回 `RAppGenealogyVo/AppGenealogyVo`、allOf 合成或等价实体的旁路详情 GET。G11 只消费 workspace 门禁的 PASS 结论,每次进入 fresh 读取唯一 `/overview` baseline,不信任路由、mine、旧 G05 内存、roleType 或 fixture。
-- 共享 `GenealogyName` 统一 G03/G11/读取为非 null、NFC、无边界空白、无换行/控制字符的 1—24 Unicode code point;`GenealogyIntro` 精确为空串或规范 1—80,正文只允许内部 LF,拒绝 CR/tab/其他控制字符,空串清空、省略保持。body 关闭额外字段且只允许 1—3 个 `genealogyName/intro/accessPreset` 脏属性,事务内原子 merge;canonical no-op 保留版本且无领域副作用。
-- 并发与 T01/M02 统一:`AppGenealogyVo.settingsVersion` 与 required `If-Match` 引用同一 opaque owner,以 `x-version-scope-fields` 锁定只随三个 canonical 设置实际变化,body 不重复版本,不另用强 ETag/412。409 根层只含 discriminator/oneOf 且分支为 exact local ref,精确分为版本变化+current、未 READY、活动待审;冲突优先级为 version→READY→active PENDING。
-- 活动 PENDING 只阻断实际 `PUBLIC_APPLY→MEMBER_ONLY`,整笔零写并引导 G10;不自动处理普通申请,不影响邀请码。设置 PUT 与任务 36 新申请 POST 都在事务内重验准入并共享 `ATOMIC_SINGLE_WINNER`,竞态只能一方提交。
-- 200 与 overview 共用关闭额外字段的 canonical `RAppGenealogyVo`;所有 component 解析只接受 exact local ref,标量、envelope、引用字段和错误字段以 allowed-key 集拒绝 `format/min/max/readOnly/writeOnly` 等额外约束、冲突组合关键字与 `nullable` 漂移。每个响应必须包含单值 enum 的 `Cache-Control: private, no-store`,429 另含 Retry-After;只允许 `traceparent/tracestate/x-request-id/x-correlation-id` 四种非语义 tracing header,禁止 ETag 与其他语义 header,避免产生第二套并发或缓存 owner。四种 tracing header 使用 component 时同样只能 exact local;内联时必须是 allowed-key 关闭、带非 null 的 string schema 的 Header Object。任务 36 的幂等、cursor、状态迁移、事务与重验扩展必须是真实 JSON 数组,不能用逗号字符串冒充。网络、超时、408、取消、5xx 和畸形 2xx 都是 outcome unknown;fresh overview 对账只陈述当前事实,不自动 PUT 或冒充本次成功。成功失效 mine/overview/search/preview 并重验 context。
-
-`tests/g11-settings-openapi-contract.ps1` 已测试先行建立,吸收两位评审的全局 owner、workspace 前置、准入反向协调、字符、nullable、exact local ref、固定 header 与纯 discriminator 伪绿反例后稳定输出 `G11-SETTINGS-OPENAPI-CONTRACT BLOCKED`、`Issues: 48`。它接管 PUT、body、settingsVersion/If-Match、409 与响应;workspace/join/G03 门禁分别只保留读取基础、申请准入协调、bootstrap/accessPreset/旧 DTO 删除。本批不创建无法执行生产 coordinator 的占位 client gate;后端同版双导出绿后,客户端第一项写操作必须先建立实际执行生产模块的纯 Node 失败测试,再实现 adapter/page,OpenAPI 绿不等于允许接线。任务 38 完成全量回归与三人终审后继续独立任务 39:G12 字辈真实保存。
-
-### 当前精确断点:任务 39 G12 字辈集合版本化保存
-
-三人已完成 G12 页面、共享字辈夹具/Node 冒烟、受保护双导出及现有 G-series 门禁的只读核对,并统一为唯一 `GET/PUT /genealogy/app/genealogies/{genealogyId}/generation-poems`,operationId 分别为 `appGetGenerationPoemSet`、`appUpdateGenerationPoemSet`。旧 collection POST、逐行 PUT、batch preview/save、management 旁路必须同版删除;不引入 preview token、preview/status 接口或第二写 owner。GET/PUT 200 共用 ACTIVE-only `GenerationPoemSetSnapshot {genealogyId,poemSetVersion,items}`,稳定词法 `poemId` 可随 `generationNo` 移动,重复字辈文字允许,排序只由 1—2147483647 的 generationNo 拥有。
-
-- body 唯一为精确 `{items,disableMissing}` 的 `AppGenerationPoemSetUpdateBody`。声明 items 必须严格递增且最多 500;已有行的 poemId 必须引用 baseline ACTIVE,新行省略 ID。`disableMissing=false` 保留未声明 baseline,`true` 软停用遗漏项;空 false 是 no-op,空 true 停用全部。服务端先构造完整候选集合,再按 generationNo 排序并执行唯一 ID/世代、slot collision、连续性与最终 ACTIVE 容量检查;swap 必须显式提交所有受影响行并原子成功或零写,绝不物理删除历史。候选流程包含 `VALIDATE_FINAL_ACTIVE_CAPACITY`、`ALLOCATE_UNIQUE_NEW_IDS` 及新 ID 非空、唯一、非 baseline 校验,碰撞返回 `GENERATION_SLOT_CONFLICT`。
-- 并发唯一使用 opaque `GenerationPoemSetVersion` 与 required `If-Match`;body 不复制版本,不引入 ETag/412。canonical no-op 保留版本,语义变化生成永不复用的新版本。GET 重验 canView,PUT 在事务内重验 tenant、canEdit、版本与 READY;响应严格 typed JSON、private/no-store,429 带 Retry-After。正式 CORS 唯一声明 owner 为 `x-app-gateway-policies.APP_GATEWAY_PREFLIGHT`,精确允许 Authorization/Content-Type/If-Match/clientid 和 GET/PUT/OPTIONS;最终仍须用真实 gateway OPTIONS/preflight 证明部署 allowlist,导出声明不能冒充运行证据。
-- unknown 恢复采用 `FRESH_GET_THREE_WAY_NO_AUTO_PUT`:以 baseline/version、声明项与 disableMissing 构造 effective target;已有项按 ID+generation+NFC 文本匹配,新项按 generation+文本匹配且服务端 ID 必须新鲜。当前集合与 target 相等时执行 `CURRENT_EQUALS_TARGET_FIRST_NO_ATTRIBUTION`,只确认事实而不归因本次请求;仍等于 old 才允许用户明确重试,其他情况进入分歧处理。比较要求同基数、无额外行,语义等价忽略版本,但已变化 target 必须得到新且未复用版本;任何 unknown 后都不自动 PUT。
-- 字辈文本按 NFC、1—50 Unicode code point、完整 UTF-16 且拒绝边界空白、控制字符、bidi/zero-width 类字符。客户端在后端门禁转绿前继续诚实本地预览,禁止把 fixture、timer 或本地成功接到当前宽松接口。转绿后的第一项客户端写操作必须是直接执行生产 normalizer/coordinator 的失败测试,再原子删除旧 fixture/timer/本地成功和旧合同;随后补 saving/unknown/conflict、清空确认、live region、焦点、44dp 与 MuMu 320/360/412、1.3 倍字号、TalkBack、软键盘、0/1/500×50、swap、断网/杀进程、权限撤销、READY 和账号切换矩阵。
-
-测试先行证据为 `tests/g12-generation-poem-openapi-contract.ps1` 输出 `G12-GENERATION-POEM-OPENAPI-CONTRACT BLOCKED`、`Issues: 72`;72 项只指向受保护旧导出的真实路径/schema/header/CORS 缺口。完整 zero issues 合法种子及多跳 ref、callback、HTTP 方法、typed error、候选/unknown/CORS 变异由 `tests/g12-generation-poem-openapi-adversarial-contract.ps1` 证明为 `G12-GENERATION-POEM-OPENAPI-ADVERSARIAL-CONTRACT PASS`;ECMAScript Unicode 边界由 `tests/g12-generation-poem-unicode-contract-runtime-smoke.js` 证明为 `G12-GENERATION-POEM-UNICODE-RUNTIME-SMOKE PASS`。G-series 已删除旧 G12 owner,三人第三轮终审无 P0/P1;受保护 OpenAPI 和页面均未修改。
-
-### 当前精确断点:任务 40 F01/F03 家族动态读取
-
-本批只治理 F01 动态列表、F03 动态详情和正常一级评论读取,明确排除 F02 发布、点赞、评论/回复写、回复读取和媒体文件读取。三方已统一唯一 owner 为 `GET /genealogy/app/genealogies/{genealogyId}/feeds`、`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}`、`GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments`,operationId 分别为 `appListFamilyFeeds`、`appGetFamilyFeed`、`appListFamilyFeedRootComments`;同版本删除两个 `/page` GET,保留谱上下文嵌套身份,不引入全局 feed 路由。受保护双导出当前仍有 feed list/page 与 comments list/page 双 owner、无 operationId、int64 ID、通用 RList/RObject/PageResult 和开放评论 DTO;2026-07-23 线上 OpenAPI 3.1.0 还显示 `AppFamilyFeedVo/FamilyFeedCommentVo` 无 required,评论投影含手机号和内部审核字段,因此两者都不能接页面。
-
-`API-FEED-READ-001`—`006` 固定词法 `GenealogyId/FamilyFeedId/FamilyFeedCommentId` 与 closed required 最小投影。`AppFamilyFeedReadItem` 只含 `feedId/feedContent/authorDisplayName/publishedAt/hasMedia`;`hasMedia=true` 时,在媒体读取合同落地前客户端必须诚实展示附件暂不可用占位,不能静默伪装为完整纯文字动态。`AppFamilyFeedRootCommentReadItem` 只含 `commentId/commentContent/authorDisplayName/publishedAt`,只返回正常可见一级评论,不返回删除占位、reply、手机号、账号/业务用户 ID、状态或审核字段。标题、标签、点赞数、总评论数和 fixture 展示时间都不是本批服务端合同,adapter 不得猜值。
-
-两个 collection GET 使用 opaque cursor,`limit` 默认 20、范围 1—50,不返回 total/pageNum;feed 按 `publishedAt DESC + feedId DESC_ORDINAL`,评论按 `publishedAt ASC + commentId ASC_ORDINAL`。读取窗口精确为 `UPPER_BOUND_KEYSET_LATEST_VISIBLE`:新插入项等刷新后再出现,删除或变为不可见的项在后续页省略,编辑内容按该页读取时的最新可见版本返回,不能宣传为严格 MVCC snapshot。cursor 绑定 tenant/account/authSession/client、谱/动态、projection/order/limit、windowUpperBound 与 lastTuple;每页重新鉴权,篡改或过期为 typed 400,跨主体、错谱、feed 不属于 path 谱、删除/隐藏、撤权或不可见统一 `404 FAMILY_FEED_NOT_AVAILABLE`,不以 403 泄露存在性。
-
-`tests/family-feed-read-openapi-contract.ps1` 已测试先行取得 `FAMILY-FEED-READ-OPENAPI-CONTRACT BLOCKED`、`Issues: 85`。85 项全部对应受保护旧导出的双 owner、参数、词法身份、closed projection、cursor、安全、typed JSON、private/no-store、Retry-After、严格 Reference Object 与无 PII 缺口;`tests/family-feed-read-openapi-adversarial-contract.ps1` 以完整 zero issues 合法种子和 58 个独立变异取得 `FAMILY-FEED-READ-OPENAPI-ADVERSARIAL-CONTRACT PASS MUTANTS=58`,覆盖旧 owner、大小写、security owner/数组、int64、PII/审核字段、offset/total、cursor scope/order、403 分流、wildcard、缓存头、外部/多跳 ref、HEAD/OPTIONS/callback 与 schema 关键字旁路。受保护 OpenAPI、F01/F03 和 dormant `appApi.getFeeds` 均未修改。后端绿前 F01/F03 继续使用按 `genealogyId + feedId` 失败关闭的 fixture,禁止接当前宽接口或在远端失败后回退 fixture。后端同版本 JSON/YAML/live 文档全部通过后,客户端第一项写操作必须先建立直接执行生产 read normalizer/coordinator 的纯 Node 失败测试,再原子迁移列表、详情和评论分页,删除 fixture 锁、伪重试与旧“必须 fixture”断言,并补 sessionEpoch、切谱/切账号迟到响应、局部评论错误、诚实媒体占位、焦点恢复和 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.json`、`APP.openapi.yaml`
-- schema v3 视觉资产注册表:`design-pipeline/manifests/runtime-assets.json`
-- 九宫格所有者:`styles/adaptive-frame-profiles.scss`
-- 当前预览密码策略所有者:`utils/validation.js`;生产目标 wire/policy owner 等待 `API-PASSWORD-001`—`005` 关闭后原子替换,禁止单页双轨。
-- 响应式覆盖:`tests/responsive-layout-coverage.json`
-- 固定尺寸例外:`tests/responsive-layout-allowlist.json`
-- 活动路由:`pages.json`;项目固定使用 Vue 3,`uni.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:52(Asia/Shanghai)只读获取其 `/v3/api-docs`,线上为 OpenAPI `3.1.0`、`722` 条路径、`858` 个操作和 `507` 个模型;本地 112 条路径中有 109 条仍在线,`/genealogy/app/files/reference`、`/genealogy/app/files/upload`、`/genealogy/pc/files/upload` 三条不在当前线上文档,线上另有 613 条路径。线上模型已把部分 `Genealogy*Body` 重命名为 `AppGenealogy*Body`,`GenerationPoemBatchBody` 也新增了由路径写入的 `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。A01 现以密码登录为默认并接通线上 MD5 wire、`access_token` 持久化与 G01 跳转;默认 mode 仍为 mock。密码联调入口的 static TAC 票据尚未由登录接口消费,因此只是测试性前置,不能冒充服务端强制校验,`API-AUTH-TAC-001` 继续保持发布红灯。
-
-认证后端门禁仍有四组问题:`API-AUTH-TAC-001` 要求密码登录加入服务端可消费的同语义票据;`API-AUTH-TAC-002` 记录线上 `/captcha/challenge` 在 `APP_REGISTER` 实测返回 HTTP 500 且空响应;`API-AUTH-TAC-003` 要求验证请求以 provider discriminator/`oneOf` 严格关闭根对象和各 payload 的额外字段,并补齐必填 `providerCode/captchaType/payload`;`API-AUTH-TAC-004` 要求同一验证中心返回服务端绑定的 verification session、可验证方法和同一类短时单次 `validToken`,`required=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 验证。
-
-家谱工作区只读审查已固定 `/mine`/`appListMyGenealogies` 为可访问集合 owner、`/{genealogyId}/overview`/`appGetGenealogyOverview` 为 G05 唯一详情 owner;首批不同时请求语义重复的 `/{genealogyId}`。门禁已收紧为 GET-only/no-body、required SaToken/clientid、词法 `GenealogyId`、关闭的成功 envelope、typed HTTP、exact local ref 和固定 private/no-store;`/mine` 以 `OMIT_ONLY_AFTER_CONFIRMED_ACCESS_LOSS` 约束失权省略,overview 以 `NON_DISCLOSING_GENEALOGY_NOT_AVAILABLE` 统一对象无权/撤权/不存在,非法 ID 为 `GENEALOGY_ID_INVALID`。线上 `AppGenealogyVo.genealogyId` 仍是 JSON `integer/int64`,相关模型无 required/canView/角色 enum,无令牌部署又使用 HTTP 200+业务 401,均不能通过。问题单 `API-GENEALOGY-WORKSPACE-001`—`003` 与 `tests/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-001`—`003` 与 `tests/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-001`—`003` 与 `tests/profile-openapi-contract.ps1` 已建立;门禁通过前不把 live-only 字段接进页面。
-
-通知三人审查把读取与写入拆成两个原子批次。读取唯一使用 `GET /genealogy/app/notifications` 和 `GET /genealogy/app/notifications/unread-count`:列表必须完整返回当前账号最多 200 条活动通知并按最新优先,未读数精确统计同一集合;页面只消费完整纯文本标题/正文、带时区时间和 `READ/UNREAD`,所有服务端 ID、发送者与业务目标都不进入公开页面模型。N02 没有详情接口,首批只能以当前内存 `generation+ordinal` 的 `snapshotKey` 打开完整快照,重启、账号切换或成功刷新后的旧 key 均提示返回消息中心重新打开。已读写入另由两个 POST 持有,要求无损字符串 `notificationId`、当前账号幂等、read-all 截止点和并发新消息语义;通过前删除伪本地已读而不发请求。当前受保护双导出的列表仍是通用模型且没有未读数路径,线上模型无 required/枚举/容量,所有 ID 仍为 int64,匿名实测又是 HTTP 200+业务 401。问题单 `API-NOTIFICATION-READ-001`—`003`、`API-NOTIFICATION-STATE-001`—`003` 以及两项失败合同已经建立,均不以猜测代码绕过。
-
-M02 资料写入三人审查保留现有 `PUT /genealogy/app/auth/profile` 作为唯一 App owner,但要求后端把它正式定义为原子 dirty-only merge,而非全资源替换或依赖 DTO 惯例猜测。请求只允许脏的 `nickName/realName/email`:省略保持,昵称出现时必须非空,真实姓名/邮箱的精确空串表示清空,null、纯空白和边界空白非法;成功返回完整 canonical `RAppProfileVo`,清空后的可选字段仍省略。并发沿用 T01 的单一版本模型:`AppProfileVo.profileVersion` 是 opaque string,PUT 必带同形状 `If-Match`,旧版本返回 409 `PROFILE_VERSION_CHANGED`,H5 CORS 同步允许该 header。受保护双导出还是旧 `ProfileUpdateBody → RObject`,线上则是无 required/merge/version/security 的 `AppProfileUpdateBody → RAppProfileVo`;当前页面还把同一 fixture 名称同时填入昵称和真实姓名,并用 500ms 定时器伪造本地校验。问题单 `API-PROFILE-UPDATE-001`—`004` 与 `tests/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-001`—`003` 与 `tests/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-001`—`005` 与 `tests/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/code`,scene 由路径固定;公共 `/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-001`—`005` 与 `tests/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 机器保证零领域写与零 quota,PENDING 的 `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 DTO;G11 在本批只取得共享字段形状,其 If-Match、版本/CAS、权限刷新与结果未知仍是独立门禁。客户端仅持久 `{sessionEpoch,operationKey,startedAt}`;`IDEMPOTENCY_KEY_REUSED` 必须进入 fatal/quarantined,禁止查询或安装 status、自动换 key,只有用户明确放弃才能清理;其他分支按可证明未提交与 unknown 分离。成功固定按 receipt→`/mine` cache→context→G05 收口,context/导航失败只重试本地闭环。问题单 `API-G03-001`—`005`、完整双源深比较、后端 `tests/g03-bootstrap-openapi-contract.ps1` 和实际执行状态机套件的客户端 `tests/g03-bootstrap-client-release-gate.ps1` 已建立;G03 两门禁转绿仍不能绕过家谱工作区读取门禁、聚焦/全量回归与 MuMu 原生验收,全部通过前保留诚实本地预览,不接 `appApi.createGenealogy`。
-
-当前 JSON 的 SHA-256 为 `87db1dc148c5e6e877815aff7b3a7fc7c7eca95a2cec50a88b42f3908961f31a`,YAML 的 SHA-256 为 `8964cd583ce172425b63bbfd802f7eb587eb3641eadfd6f9d3b264faa8090c6c`。两份文件均已被 Git 跟踪,当前相对 HEAD 无差异;本轮没有改写、格式化或覆盖接口导出。
-
-## 必须保护的用户文件
-
-- `APP.openapi.yaml`、`APP.openapi.json`:后端接口离线源快照,只接受同一后端版本的双导出替换,不得手工修改。
-- `static/tac/`:当前共 5 个文件,其中 4 个是后端提供且不可改写的供应商文件,第 5 个是项目适配器 `static/tac/js/jiapu-tac-adapter.js`;A01/A04/A05 已形成真实运行时消费者,文件集合与供应商哈希由 `tests/auth-tac-integration-contract.ps1` 唯一保护。
-- 当前五份中文治理文档:长期唯一入口,随已验证进度同步更新,不另建平行计划。
-
-任何清理批次都不得覆盖、恢复或删除以上文件。
-
-## 清理前基线
-
-- 五个核心验证:全部通过。
-- PowerShell 合同:`129` 个,`128` 个通过,`1` 个旧 A01 固定画布合同失败。
-- Vue 覆盖:实际 `66`、清单 `66`、缺失 `0`、陈旧 `0`。
-- Vue 中 `100% 100% no-repeat`:`0`。
-- Vue 中直接声明 `border-image-slice`:`0`。
-- 文档:`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/assets`、`3` 个旧 `static/icons`、`4` 个未接入业务的 TAC 文件和 `8` 个候选或伪母版;两张用户批准的 A01 选型图作为 `reference-only / non-runtime` 视觉锚点保留。
-- 阶段 0 验收时的 MuMu 证据:`emulator-5554` 当时在线,ADB 设备字段为 `model:SDY_AN00`,系统型号为 `SDY-AN00`,物理尺寸 `720×1280`,density `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/sdd` 的 `12` 个过程文件;阶段 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”。
-
-当前物理库存为 `147` 个 PowerShell 合同、`48` 个 Node 文件和 `4` 个 JSON 合同数据文件。最新 fresh 结果为 PowerShell `128/147` 通过;其余 19 项不是可删除的普通回归,而是保留真实外部或发布阻塞的 `tests/lineage-openapi-contract.ps1`、`tests/auth-tac-openapi-contract.ps1`、`tests/genealogy-workspace-openapi-contract.ps1`、`tests/g03-bootstrap-openapi-contract.ps1`、`tests/g03-bootstrap-client-release-gate.ps1`、`tests/help-center-openapi-contract.ps1`、`tests/profile-openapi-contract.ps1`、`tests/profile-update-openapi-contract.ps1`、`tests/notification-read-openapi-contract.ps1`、`tests/notification-read-state-openapi-contract.ps1`、`tests/logout-openapi-contract.ps1`、`tests/password-change-openapi-contract.ps1`、`tests/phone-change-openapi-contract.ps1`、`tests/join-application-openapi-contract.ps1`、`tests/invite-ticket-openapi-contract.ps1`、`tests/g11-settings-openapi-contract.ps1`、`tests/g12-generation-poem-openapi-contract.ps1`、`tests/family-feed-read-openapi-contract.ps1` 和缺少 MuMu 人工证据时必须失败的 `tests/auth-android-accessibility-release-gate.ps1`。十九个输出分别为 `LINEAGE-OPENAPI-CONTRACT BLOCKED`、`AUTH-TAC-OPENAPI-CONTRACT BLOCKED`、`GENEALOGY-WORKSPACE-OPENAPI-CONTRACT BLOCKED`、`G03-BOOTSTRAP-OPENAPI-CONTRACT BLOCKED`、`G03-BOOTSTRAP-CLIENT-RELEASE BLOCKED`、`HELP-CENTER-OPENAPI-CONTRACT BLOCKED`、`PROFILE-OPENAPI-CONTRACT BLOCKED`、`PROFILE-UPDATE-OPENAPI-CONTRACT BLOCKED`、`NOTIFICATION-READ-OPENAPI-CONTRACT BLOCKED`、`NOTIFICATION-READ-STATE-OPENAPI-CONTRACT BLOCKED`、`LOGOUT-OPENAPI-CONTRACT BLOCKED`、`PASSWORD-CHANGE-OPENAPI-CONTRACT BLOCKED`、`PHONE-CHANGE-OPENAPI-CONTRACT BLOCKED`、`JOIN-APPLICATION-OPENAPI-CONTRACT BLOCKED`、`INVITE-TICKET-OPENAPI-CONTRACT BLOCKED`、`G11-SETTINGS-OPENAPI-CONTRACT BLOCKED`、`G12-GENERATION-POEM-OPENAPI-CONTRACT BLOCKED`、`FAMILY-FEED-READ-OPENAPI-CONTRACT BLOCKED` 和 `ANDROID-AUTH-ACCESSIBILITY-RELEASE BLOCKED`。Node 语法 `48/48` 通过,纯 Node 冒烟 `20/20` 通过,活动 Vue 脚本模块语法 `64/64` 通过;导航源码扫描保持 `MIGRATION-DEBT=0`。依赖 `127.0.0.1:9222` 调试页的浏览器运行时文件本轮只做语法检查,没有执行;这不能冒充浏览器行为或 MuMu 原生视觉通过。
-
-阶段 0 清理结束时,`static/` 的正式基线为 `79` 个文件、共 `70,414,397` 字节。任务 3 退役两张孤立通知 frame 后,正式 `static/assets` 为 `77` 个文件、共 `69,093,742` 字节;`static/tac/` 当前 5 个文件、共 `68,190` 字节,因而当前 `static/` 物理库存为 `82` 个文件、共 `69,161,932` 字节。4 个供应商文件保持原字节并由哈希合同保护,新增适配器是唯一项目映射层;TAC 已进入 A01/A04/A05 业务运行时,但不属于可重建视觉资产注册表。`tmp/`、`unpackage/` 和 `design-pipeline/generated/` 均不存在;正式生成资产仍由清单和构建器恢复,质量报告不作为长期资料保留。
-
-任务 36 新增门禁后,当前物理库存更新为 PowerShell `141`、Node `47`、JSON 合同数据 `4`;新增门禁已独立验证为 `JOIN-APPLICATION-OPENAPI-CONTRACT BLOCKED`。全量 fresh 复核为 `126/141`,新增加入申请红灯与原 14 项共同构成 15 项明确发布阻塞;上文 `140/47` 与 `126/140` 仅是新增门禁前的换机 fresh 基线,不能把两个时点混写为全部通过。
-
-任务 37 新增邀请码门禁后,当前物理库存为 PowerShell `142`、Node `47`、JSON 合同数据 `4`;全量 fresh 为 `126/142`,新增 `INVITE-TICKET-OPENAPI-CONTRACT BLOCKED` 后共有 16 项明确发布阻塞。任务 36 的 `126/141` 是上一时点证据,不得冒充当前库存。
-
-任务 38 新增设置门禁后,当前物理库存为 PowerShell `143`、Node `47`、JSON 合同数据 `4`;全量 fresh 为 `126/143`,新增 `G11-SETTINGS-OPENAPI-CONTRACT BLOCKED` 后共有 17 项明确发布阻塞,专项门禁稳定为 `Issues: 48`。
-
-任务 39 新增 G12 主门禁、对抗合同和 Unicode 冒烟后,当前物理库存为 PowerShell `145`、Node `48`、JSON 合同数据 `4`;全量 fresh 为 `127/145`,对抗合同转绿而主门禁新增第 18 项发布阻塞。专项结果为 `G12-GENERATION-POEM-OPENAPI-CONTRACT BLOCKED`、`Issues: 72`、`G12-GENERATION-POEM-OPENAPI-ADVERSARIAL-CONTRACT PASS` 和 `G12-GENERATION-POEM-UNICODE-RUNTIME-SMOKE PASS`。
-
-任务 40 新增家族动态读取主门禁与对抗合同后,当前物理库存为 PowerShell `147`、Node `48`、JSON 合同数据 `4`;全量 fresh 为 `128/147`,主门禁新增第 19 项发布阻塞,对抗合同本身通过。专项结果为 `FAMILY-FEED-READ-OPENAPI-CONTRACT BLOCKED`、`Issues: 85` 和 `FAMILY-FEED-READ-OPENAPI-ADVERSARIAL-CONTRACT PASS MUTANTS=58`;它没有修改受保护 OpenAPI 或页面,也没有把线上宽松 DTO 当作可用合同。
-
-## 当前规划结论
-
-### 导航栈
-
-- 迁移前 52 个活动页面只读统计为 `navigateTo 59`、`navigateBack 11`、`redirectTo 14`、`reLaunch 7`,活动页面合计 91 次;活动组件另有 4 次,封存 A06 另有 2 次。任务 3—9 已依次迁移共享组件、认证、G、T、F、R、N/M,任务 10 删除最后一个无消费者旧表单组件并关闭门禁。当前 pages/components 中 `navigateTo`、`navigateBack`、`redirectTo`、`reLaunch`、`getCurrentPages` 和业务页面路径字面量均为 `0`,`switchTab` 全项目为零;五种 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;生产目标由后端 `SmsCodeSecret` 和 `tests/phone-change-openapi-contract.ps1` 锁定为严格 6 位,门禁通过时必须一次替换所有活动消费者并删除旧 owner 的四位规则。`components/TacVerification.vue` 是验证浮层与 renderjs 生命周期 owner;`static/tac/js/jiapu-tac-adapter.js` 是 TianAi challenge/proof/verify 映射 owner;`utils/api.js` 是严格 HTTP 200 envelope、15 秒超时、离页中止、认证会话写入和反馈 wire payload 的唯一 owner。旧认证专用请求控制器入口、占位验证、伪验证码、宽松令牌兼容和 M07 假提交均已删除。
-- A01 默认密码登录,线上 wire、TAC 前置、token 保存和 G01 跳转已有可执行纯 Node 状态机证据;默认 mode 仍为 mock,且密码登录未消费 `validToken`,故 `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。
-- 搜索与筛选只作用于已投影数组;筛选后不得重新编号。搜索、分类和刷新先收起正文,新请求以 controller+generation 拒绝迟到响应,离页取消请求;空列表、搜索无结果、加载失败和认证失效必须分别表达。
-- M06 现有分类和问题标题使用 `` 且触控高度不足;真正接线时改为原生按钮语义,补 `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 baseline,GET 不冒充 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.ps1` 与 `tests/notification-read-state-openapi-contract.ps1`。当前分别输出 `NOTIFICATION-READ-OPENAPI-CONTRACT BLOCKED` 和 `NOTIFICATION-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、性别和生日全部留到独立批次;当前 `` 假头像动作在写入实施时删除。邮箱没有验证与送达合同,页面不得继续承诺“用于接收通知”。
-- `tests/profile-update-openapi-contract.ps1` 当前输出 `PROFILE-UPDATE-OPENAPI-CONTRACT BLOCKED`。后端关闭 `API-PROFILE-UPDATE-001`—`004`、同版本双导出通过、读取 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-store`;RVoid 的整数 code required,另声明 400/429/500。线上仅有文字“需要登录”和 `*/*`,本地虽有 security/clientid 但 RVoid 无 required、只列 200,均未达到发布合同。
-- `logoutCoordinator` 是唯一跨页 owner:同步捕获 token/clientid 与 logoutEpoch,立即调用 session owner 清 token、家谱上下文和账号缓存并 bump epoch,再以显式 A 快照创建 RequestTask;整个同步段不 await,M10 页面拿不到 token。创建失败也不恢复;请求不绑定页面 controller,reLaunch/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.password` 与 `PasswordChangeBody.oldPassword` 只引用 `CurrentPasswordSecret`;注册、找回和改密的新密码只引用 `NewPasswordSecret`。生产入口不再接受 MD5、十六进制摘要或两套兼容分支;确认密码只留客户端。
-- `CurrentPasswordSecret` 是原样、不 trim 的 1—64 Unicode code point;`NewPasswordSecret` 是 NFC 后 15—64 code point,允许空格、Unicode 和密码管理器粘贴,不强制字母/数字组成。服务端才是策略权威,必须执行常见/泄露密码 blocklist、当前密码验证、新旧不同、账号级限速和带盐慢哈希;页面校验只是即时提示。
-- PUT required SaToken、非空 clientid 与关闭额外字段的 JSON body;200/400/401/409/422/429/500 均为 typed JSON、`private, no-store`,429 带 `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-001`—`005`、原子重导双文件、密码登录 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-001`—`004`、提供同版本双导出并修复 challenge 500;随后才允许把 `runtimeConfig.mode` 从 `mock` 切为 `remote`,执行正式 H5 CORS、真实票据重放/限流和 MuMu Android 流程。
-3. 并行推进非交互风控的限时 POC 与文字/中继人工兜底合同;只有 POC、服务端原子消费和 `ANDROID-AUTH-ACCESSIBILITY-RELEASE` 全部通过,才可宣称认证达到上线门槛。
-4. 新图合同通过后,按规范化与校验、布局、Scene 与空间索引、单 Canvas、页面交互、接口回流的顺序实施 T01。
-5. 家谱工作区三人审查和失败合同已经完成;等待后端关闭 `API-GENEALOGY-WORKSPACE-001`—`003` 并提供同版本双导出。门禁通过后再测试先行实现唯一 adapter、G01 `onShow` 列表现场和 G05 `/overview` 读取,不提前固化字段或枚举。
-6. G03 原子创建三人审查和失败合同已经完成;等待后端关闭 `API-G03-001`—`005`、以同版本双导出交付 bootstrap POST、状态查询、地区选择与统一 accessPreset。通过前不接当前宽松 `createGenealogy`;通过后先实现严格 coordinator、无 PII 恢复 marker、地区选择器、context/G05/G01 闭环,再独立完成 MuMu 表单与无障碍矩阵。
-7. M06 三人审查和失败合同已经完成;等待后端关闭 `API-M06-001`—`003` 并提供同版本双导出。通过后测试先行实现 list-only adapter、加载/空/失败/重试、动态分类、纯文本手风琴和无障碍语义,不接详情或文章 ID。
-8. 个人资料读取三人审查和失败合同已经完成;等待后端关闭 `API-PROFILE-READ-001`—`003` 并提供同版本双导出。通过后测试先行实现唯一掩码 adapter 与 M01/M02/M03 局部状态,M05 当前手机号展示随同一只读 owner 原子迁移但不接换绑写接口。
-9. 通知读取与已读写入已分别完成三人审查和失败合同;等待后端关闭 `API-NOTIFICATION-READ-001`—`003` 与 `API-NOTIFICATION-STATE-001`—`003`。读取通过后先实现无 ID 的内存快照和 M01/G01 未读数;写入另批迁移私有 ID、删除伪本地写并验证并发收敛,不恢复不可信目标 CTA。
-10. M02 个人资料 PUT 已完成三人审查和失败合同;等待后端关闭 `API-PROFILE-UPDATE-001`—`004`。读取与写入门禁都通过后,按 normalizer、严格 API、M02 状态机和 MuMu 表单矩阵独立实施,不混头像或账号安全。
-11. M10 服务端退出已完成三人审查和失败合同;等待后端关闭 `API-LOGOUT-001`—`003` 后,再测试先行实现 session epoch、唯一 logoutCoordinator、A01 一次性提示和两设备撤销矩阵。
-12. M04 登录态改密与四条密码 wire 已完成三人审查和失败合同;等待后端关闭 `API-PASSWORD-001`—`005` 后,才原子迁移共享密码策略、MD5 调用、session marker、M04 状态机和全设备撤销矩阵。
-13. M05 手机号换绑三人审查和失败合同已经完成;等待后端关闭 `API-PHONE-001`—`005`,且 M04 raw-password 与认证/TAC 前置门禁同时通过后,再原子迁移全活动 OTP、实现专用受保护发码、共享 credential marker 与 M05 状态机。
-14. 继续审查下一个不依赖现有红灯的业务域;按 G/F/R 逐域推进。随后逐批完成文字层级与无障碍,不混合验证码、账号写入、领域数据或支付。