Skip to content

feat(core): portal SCAR reply, claim confirmation and performance appeal (v0.6 U5) - #91

Merged
marchtian merged 1 commit into
mainfrom
claude/project-thread-7qrptf
Nov 2, 2026
Merged

marchtian merged 1 commit into
mainfrom
claude/project-thread-7qrptf

Conversation

@marchtian

Copy link
Copy Markdown
Collaborator

Requested by 田騏 · project thread

Closes #81.

改了什么

整改单(03 §8 第 2–4 步,FR-603)

  • 门户用户直接在整改单上填 D3、D4–D7、证据并推进状态,替代 SQE 代填(没开通门户的供应商仍由 SQE 代填)。8D 按裁定不建子对象。
  • 三层限制:
    • RLS srm_portal_quality_issue_write:using = 本公司且 status in ['open','containment_submitted'](轮到供应商回复),check = 本公司且停在 open / containment_submitted / action_submitted;两条都读成员键。
    • FLS:门户只能改 containment_action、root_cause、corrective_action、preventive_action、evidence、status,其余全部只读(含 sqe_comment、claim_*)。
    • status 选项的 visibleWhen 按操作人限定(服务端执行):门户只能走 待响应 → 已提交临时措施 → 已提交根因与措施,不能进入效果验证、关闭、撤销或退回。
  • 新 flow srm_scar_containment_notice:供应商提交 D3 时通知负责 SQE(没有 SQE 时通知质量经理);SQE 本人代填时不发(按 updated_by 判断,因为系统身份的 flow 里 current_user 为空)。

索赔(第 6 步,FR-606)

  • 新 screen flow srm_claim_respond「确认索赔」:接受 → supplier_accepted,通知 SQE 与应付会计;异议 → disputed,意见必填,写入新字段 claim_response,通知 SQE。

绩效(FR-704、706)

  • 门户本来就能读已发布 / 申诉中的考评单与评分明细(U2);这次把评分人、回避改派、审定人、审定意见、申诉处理人设为门户不可见(GL-05)。
  • srm_appeal_submit 接受本公司门户管理员提交,内部代录路径保留;appeal_recorded_by 标签改为「申诉提交人」。通知采购总监的节点加了 try/catch(以前没有采购总监时 flow 会在写入之后失败)。
  • 两个对象声明 searchableFields:默认搜索会扫全部文本字段,扫到门户读不到的字段平台会拒绝整个搜索(同 objectstack#25672 的现象,这里直接不扫,不用临时放开字段)。

隔离(红线 2)

  • 系统身份运行的 screen flow 读不到成员键。实测:记录页按钮对不可见记录答「不存在」,但直接触发 flow(REST trigger)能绕过这一步。所以 srm_claim_respond 与 srm_appeal_submit 在 flow 里直接查名册:操作人必须是记录所属供应商的在职联系人(portal_user = 本人、active == true,与成员键条件一致)。
  • test/portal-isolation.test.ts 新增:
    • 越过回复范围:改非回复字段、跳状态、退回、改轮到 SQE 的单,一律拒绝或丢弃;
    • 越权 screen flow:对 B 的整改单确认索赔、对 B 的考评单申诉、联系人停用后申诉,两个入口都试,加上正向对照;
    • 元数据守卫:门户可改的整改单字段集合固定;门户能发起的系统 flow 的名册检查与成员键条件一致,且 gate 的每条边都经过它。
  • 新增 test/portal-response.test.ts:X 在门户回复 → SQE 退回一次 → 改好再交 → 审核通过进入效果验证(07 §2.2 第 1 步);索赔先异议再接受、应付会计标记已扣款;门户看已发布绩效与扣分项、普通门户用户不能申诉、门户管理员申诉一次、处理结果可见。

文档:02 §4.6 / §4.7、03 §8 / §10 / §13、04 §3.2 / §3.7 / §4.2、05 通知表、07 测试清单;体系文件 GL-07 第 7 章加控制点,GL-06 6.7.1 与控制表写明由门户管理员提交(ADR-0005)。

没做 / 留意

  • 两个「提交时间」datetime 字段(裁定里写的是可选)没加,提交时间看字段历史;02 §4.6 已写明。
  • 证据上传测试用的是预先建好的文件记录;external 用户经界面上传附件的路径随 U4 / 出口浏览器测试一起验。
  • 给供应商的通知(新整改单、退回、申诉结果给 admin 联系人)属于 U6(v0.6 U6:供应商侧通知 #82)。

怎么验证的

本地全部通过:pnpm validate、pnpm lint、pnpm typecheck、pnpm i18n:check、pnpm test(26 个文件、309 个用例)、pnpm build,governance/scripts/build.py --check 两种组合。


Generated by Claude Code

…n the portal

v0.6 U5 (#81):
- SCAR: portal users edit D3-D7 and evidence of their own SCARs while it is
  the supplier's turn (open / containment_submitted); status options are gated
  per acting user so the portal can only move open -> containment_submitted ->
  action_submitted. New RLS write policy reads the membership key; every other
  SCAR field is FLS read-only for the portal. No 8D child object (ruling).
- srm_scar_containment_notice tells the SQE when the supplier submits D3.
- Claims: new screen flow srm_claim_respond (accept / dispute with comment,
  new field claim_response), notifies SQE and AP accountants.
- Appeals: srm_appeal_submit now admits the supplier's portal admin. Both
  portal-facing system flows check the contact roster themselves, because a
  direct flow trigger bypasses the record page's read.
- Performance: reviewer, review comment, appeal handler, scorer and
  reassignment fields are hidden from the portal; searchableFields keep the
  portal's list search off them.
- Isolation tests for the new write paths, functional portal test, design
  docs 02/03/04/05/07 and GL-06/GL-07 control points updated.

Claude-Session: https://claude.ai/code/session_017ihL2d8WNqLwcDq2CsfFXY
Co-authored-by: Claude <noreply@anthropic.com>
@marchtian marchtian self-assigned this Nov 2, 2026
@marchtian
marchtian merged commit f12f59c into main Nov 2, 2026
2 checks passed
marchtian pushed a commit that referenced this pull request Nov 2, 2026
srm_change_submit and srm_application_resubmit now name their roster check
load_membership / membership, so the metadata guard from #91 covers them too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2eFDUqnMy95b1fqMKJ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v0.6 U5:门户整改回复、索赔确认与绩效查看、申诉

2 participants