DEMO · 接口/状态机/错误码照抄后端,卷宗为演示数据 未登录 · 请机构登录

工单总览

列表来自 GET /api/v1/lawfirm/cases?status=,可见范围是本所已认领 + 未认领抢单池(law_firm_id == null 的工单任何律所可见,先到先得;review PASS 或 execute 时才落 law_firm_id 完成认领)。不是"只显示本所"。

0本会话可见本所 + 未认领
0本所已认领law_firm_id = 本所
0未认领抢单池先到先得
0待补件 / 核验中 / 执行中硬关卡未闭环
0已办结COMPLETED + closed_at

工单列表(过滤:全部)

工单号状态材料数登记数开单时间归属操作
列宽就是 toSummary 的全部字段:caseNo | status | openedAt | closedAt | materialCount | recordCount。 列表里没有案由、没有长辈姓名、没有承办/复核人 —— 这不是遗漏:律所会话拿不到用户身份资源,最小可见面是设计约束。承办/复核只在明细与命令响应里出现。

可见性与越权:三条真实折叠

① 律所会话访问用户资源 → 2003 FORBIDDEN。
currentUserRef() 见 userRef=null 直接拒。
② 他所已认领工单 与不存在的工单折叠为同一 1004 CASE_NOT_FOUND,措辞一模一样 —— 错误差异不得成为跨所探测工单存在性的预言机。
用 CY-2026-0071(他所已认领)试。
ROLE_LAWYER /api/v1/lawfirm/** 门禁 可见范围 本所 ∪ 未认领 1004 他所/不存在折叠 2003 用户资源拒绝 scope=lawfirm 登录节流独立计数

工单作业台 · 三道硬性关卡

ADR-01:EXECUTING 没有任何自动化路径,只能由律师带着第二人复核推过去。关卡 1 = review;关卡 2 = 资产全覆盖;关卡 3 = FAILED 必填 remark(2、3 都在 execute)。

—状态 —承办(本会话) —复核人落库 —登记 —

选择工单

工单号状态归属

材料(materials[],闭枚举 4 类)

类型文件审核审核人
材料由归属用户提交(CASE_MATERIAL_SUBMITTED,actorType=user),律所只审不传。类型受 ExecutionMaterial.TYPES 约束,越界即 1001 MATERIAL_TYPE_INVALID。

进度与卡点(GET …/progress)

点左侧工单加载。

办理导航(GET …/checklist,只指路不代办)

点左侧工单加载。

执行登记表单(assets[] 全量覆盖 = 关卡 2)

未选择工单。
资产(platformCode / category)处置remark
assets = 该用户全部有效资产(isDrill=false 且 revokedAt is null)。提交的 items[].assetId 集合与之不等 → 3009 CASE_ASSET_COVERAGE_INCOMPLETE。

动作

手工升级走的是委托流水线,不改工单状态:POST …/escalate → escalateManually 只创建下一个 DelegationStep,返回 {escalated:true, stepKey:"…"};已在最终兜底环节则 {escalated:false, reason:"已在最终兜底环节"}。幂等靠 existsByCaseRefAndStepKey。升级终点是 LAWFIRM_AGENT —— HUMAN_REVIEW 不由本端点抵达,只有 routeToHuman 会建那一步。

遗嘱机构工作台

端点 /api/v1/lawfirm/will-cases/**:docs/15 §9 写的是 /api/v1/org,实现复用了已绑定 ROLE_LAWYER 的 /lawfirm 前缀,零改动获得角色门禁与双身份纪律。状态机真源是 WillCaseStatus.TRANSITIONS。

本机构工单(GET /lawfirm/will-cases → {cases:[caseView]})

工单号capability状态承办执照号报价区间授权 scope操作
工单号真实格式 WC-{年}-{0001 四位递增}(按年取数值最大 +1,纯字典序进位后会失真)。列表不含委托人姓名 —— caseView 里没有用户身份字段。

阶段管线 · —

合法链:REQUESTED → ASSIGNED → CONSULTING → DRAFTED → SIGNING → COMPLETED;DRAFTED → CONSULTING 是有意保留的回边(改稿重议)。越链(如 REQUESTED → COMPLETED)→ 4008 WILL_CASE_ILLEGAL_TRANSITION,措辞"工单不能从 X 转到 Y"。 只有 complete 需要双人复核(reviewerLicenseNo 必填、须命中本所在职律师、且 ≠ handlerLicenseNo,复用 3008;这里是字符串闸门,不要求批准令牌 —— 身后执行的 review/execute 才上真签名);accept/consult/draft/schedule-signing 都是单人动作 —— 所以"约签署"不能把工单置成已完成。

INV-28 草案闸门(GET …/draft?scope=)

闸门是双向的:既要有未过期的 will_case_access_grant 行,其 scope 还得覆盖所请求的档位。任一不满足都是 3014 WILL_ACCESS_NOT_GRANTED,且两种情形措辞不同但都不泄露拿到了多少:无授权行 →"用户尚未授权查看该遗嘱内容";有行但档位不够 →"当前授权范围不足以查看该内容"。
选一单后点档位读取。

主体与纪律

律所主体以 ROLE_LAWYER 登录,复用既有 HttpSession,会话 userRef = null(双身份纪律)。这一屏写清"后端确实拦了什么",也写清"后端目前没拦什么"。

当前律所主体(LawfirmProfileResponse)

尚未登录。点右上角「机构登录」用三要素(机构账号 + 执业证号 + 口令)登录。
字段就这些:lawyerId | lawFirmId | lawFirmName | loginName | licenseNo | lawyerName | role。不含口令哈希;律师名 DEMO 期输出原文,pre-production 走 SM4 解密链路。

纪律红线(真实后端行为)

① 三要素登录 POST /api/v1/lawfirm/login:身份 = 机构账号|执业证号(小写归一)查 status=1 的律师行 + SM3 口令校验,任一不符 → 2006 CREDENTIAL_INVALID,审计落 LAWFIRM_LOGIN_FAILED(subjectRef=null,不暴露是哪一类失败)。失败滑窗 5 次/身份、25 次/IP,窗口与锁定各 15 分钟;scope=lawfirm 与用户端分开计数,互不顶包;超限 2007 LOGIN_THROTTLED → HTTP 429。

② 机构 id 不取会话自报:会话 principal 只有 accountId;requireProfile() 从库内还原 lawFirmId,再 resolveOrgIdByLawFirm() 桥接 partner_org。桥不到 → 1004 PARTNER_ORG_NOT_LINKED「该机构尚未接入遗嘱服务,请联系平台运营」。

③ 双身份纪律:userRef=null 的会话访问用户资源 → 2003;角色不是 LAWYER 打律所端点 → 2003 LAWYER_CONTEXT_REQUIRED;会话对应的律师行被删 → 1001 段 UNAUTHENTICATED LAWYER_NOT_FOUND。

④ 双人复核 = 两道关,第二道是真签名:review / execute 除 result/items 外,必须携带 reviewerApproval 令牌 —— 由复核人自己的设备用其 K-签 私钥对七元组 REVIEW_APPROVAL⏎caseNo⏎action⏎handlerLicenseNo⏎reviewerLicenseNo⏎issuedAt⏎nonce 签的 SM2(DER) 签名。服务端先做身份闸门(复核人须在册、同所、在职、≠承办,四种不合格折叠为同一 3008 措辞),再验签:deathCertVerifiedBy/reviewer 落的是验签通过的那个人,不是承办人敲的字符串。will-cases/complete 仍是存在性 + 同所 + ≠承办的字符串闸门(未上令牌,界面不假装)。

④ 的边界(校验顺序与错误码,缺一不可):reviewerApproval 缺失 → 1001 REVIEWER_APPROVAL_REQUIRED;令牌字段不齐 → 1001;issuedAt 非整数毫秒 → 1000 APPROVAL_ISSUED_AT_MALFORMED;身份不合格(不存在 / 已离职 / 属他所 / 同人)折叠为同一 3008 REVIEWER_MUST_DIFFER,不给出可枚举执照号的差异;绑定校验(caseNo / action / handlerLicenseNo 任一不符)先于 nonce 消费 → 2002 REVIEWER_APPROVAL_MISMATCH,贴错的令牌不会被烧掉;然后才验签:超 ±5 分钟时钟窗 → 2004 APPROVAL_EXPIRED,复核人名册无在用 K-签 → 2001 REVIEWER_SIGN_KEY_ABSENT,签名非合法 Base64/DER → 2002 SIGNATURE_MALFORMED,SM2 验不过(伪造)→ 2002 REVIEWER_SIGNATURE_INVALID,同 nonce 二次使用 → 2002 SIGNATURE_REPLAY。须如实标注:一张批准只对其所签工单 + 动作生效(复核通过 ≠ 复核驳回 ≠ 执行登记),不能被复制到别的工单复用。

⑤ 验签真相:SignedRequestFilter 已收口(产品迭代 P2):律所会话(role=LAWYER,userRef=null)不再被直接放行,而是走 verifyLawyer —— 三要素登录登记本设备的 K-签 公钥(lawyer_key_ref,撤旧存新),复核 / 执行登记 / 遗嘱流转的每个写请求都带 X-Cunyi-Signature 逐字节验签并消费 Nonce 防重放(缺头 2001·验签不通过或重放 2002·时间戳超窗 2004)。仅 /api/v1/lawfirm/login 仍豁免(登录时尚无律所主体可验)。两套签名是两回事:请求签名证明"这条写请求出自承办人本人",复核批准令牌证明"另一名复核律师在自己设备上点了头",服务端按复核人的在册公钥验签 —— 承办人没有复核人的私钥,伪造不出这张批准。须如实标注:这两把 K-签都是软件密钥(私钥只存浏览器 IndexedDB),证明的是"经三要素鉴权的当前设备",非硬件级不可否认身份;复核人换设备重登即换钥匙,旧批准随即不再验得过。

审计与归因

audit_event 是 SM3 哈希链、仅追加,与 proto-hub 同一条链。下面的动作名是后端字面量,可 git grep 对上。

律所侧会写入的动作(真实字面量)

LAWFIRM_LOGIN_OK (actorType=lawyer,actorRef=律师 id)· LAWFIRM_LOGIN_FAILED(actorType=platform —— 把尝试登录的账号名归到人头上会让"哪些账号存在"变成可回读的枚举面)
CASE_OPENED (actorType=system,监测 ALERTED 联动开单,幂等)
CASE_MATERIAL_SUBMITTED (actorType=user —— 是用户提交,不是律所)
CASE_REVIEW_PASS · CASE_REVIEW_REJECT · CASE_EXECUTED (actorType=lawyer,actorRef=承办律师 id —— 双人痕迹进链,detail 记承办+复核两照号)
CASE_ABANDONED_BY_OWNER_ALIVE (user —— 本人打卡复活作废)
CASE_STEP_CREATED · CASE_ROUTED_TO_HUMAN (system / delegation_step —— 升级链)
WILL_CASE_ASSIGNED · _CONSULTING · _DRAFTED · _SIGNING · _COMPLETED · _REJECTED (actorType=lawyer,actorRef=承办律师 id;无主体的内部/测试直调才回落 platform)
CASE_ESCALATED_BY_OPS (运营端升级入口)
⛓ CASE_ESCALATED (上链锚定事件,TriggerPublisher)

锚定的真相:上链 CASE_ESCALATED 只在超时自动升级进到 LAWFIRM_AGENT 那一步时发(escalateFrom)。律所端点的 POST …/escalate(escalateManually)只落 CASE_STEP_CREATED,不上链。

本次演示新增(仅追加)

(尚无动作 —— 去作业台推一单)

归因(P1 已收口 · 本屏如实标注)

Actors 已补 lawyer。律所经手的关键动作(LAWFIRM_LOGIN_OK、CASE_REVIEW_PASS、CASE_EXECUTED、WILL_CASE_*)现记 actor_type=lawyer + actor_ref=lawyer.id,双人复核与遗嘱流转到链上可归因到承办律师;CASE_REVIEW_PASS / CASE_EXECUTED / WILL_CASE_COMPLETED 的 detail 里同时写承办与复核两个执照号,且 detail 参与哈希链(audit_event 仅追加,改一个字即断链)。

仍如实标注两处不为:登录失败仍记 platform 而非律师 —— 把尝试登录的账号名归到人头上,会让"哪些账号存在"变成可回读的枚举面;内部/测试直调(无律所主体)也回落 platform,不假装是人。

⌨ API 实况— 三要素登录 / 状态机 / 错误码逐条落终端(律所写操作已带 SM2 端侧验签,复核环节另有复核人独立签名的批准令牌,见 §4 ④⑤)
辽ICP备2026024171号-1