From 0b3fa2d8a0e2a4277efa224acac5be5ed333878f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 10 Sep 2026 11:05:37 +0000 Subject: [PATCH] docs: reconcile the position census with src/sharing/positions.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tree defines seven positions and five permission sets. Four passages across README.md and DESIGN.md stated that census and only two were right. README.md's operator setup table promised "the seven positions" over seven rows whose seventh was `(business requesters)` — a default permission set, not a position — while the seventh real position, `clm_admin`, was absent. The count reconciled arithmetically (6 positions + 1 set row = 7 rows), which is why it survived. Two costs: an operator following it literally never assigns `clm_admin`, and a non-position sat in a column headed `Position` whose values are typed into `sys_user_position.position`. Add `clm_admin` as the seventh row and move the requesters out of the table into a paragraph that names the mechanism they actually use — a `sys_user_permission_set` grant, a different object from `sys_user_position` (`src/profiles/requester.profile.ts` documents the distributed default: `isDefault` cannot be used because the set carries a system permission). The `Position` column now contains only real `CLM_POSITION` values. An operator SHOULD assign `clm_admin`: `src/security/bind-position-sets.ts` binds that position to `AdminSet`, the only set carrying `clm_admin.access`, which gates the app's Administration group (`src/apps/clm.app.ts`), and the only set that may write `clm_contract_type` and `clm_approval_rule`. The dev admin deliberately holds no `clm_*` set, so without this row the demo has no account that can maintain the configuration objects. "The other five positions" follows the table: 7 - 1 exactly-named = six. DESIGN.md §11's M1 row said `8 position / 6 set`; the layout block four lines above it already said `7 position` and `5 permission set` and is untouched. §10's seeding sentence, found by the grep this card mandates, carried the same defect as the README table: `业务承办 ×3` listed inside a position enumeration with `clm_admin` absent. DESIGN.md §01-§04 and §09 are untouched: the only changed lines are 327 and 352. No gate reads either file, so none can have moved. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01R3n3GGzobdegM4HUzah1iR --- DESIGN.md | 4 ++-- README.md | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index a46454c..e2c21ef 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -324,7 +324,7 @@ Dataset(语义层): | clm_obligation | 200 | 未来 30 天内到期 40 条,逾期 10 条 | | clm_payment_plan | 300 | 本月到期 30 条,逾期 12 条 | -用户不可种子;各岗位账号在 Setup 建用户后分配 position(法务经办 ×2、法务负责人、财务负责人、分管领导、总经理、档案与记录管理员、业务承办 ×3)。 +用户不可种子;各岗位账号在 Setup 建用户后分配 position(法务经办 ×2、法务负责人、财务负责人、分管领导、总经理、档案与记录管理员、CLM 管理员);业务承办 ×3 不是 position,`clm_requester` 是全员默认集,在 Setup 直接授予。 ## 11 仓库与里程碑 @@ -349,7 +349,7 @@ docs/backlog/ 派发卡片 | 里程碑 | 内容 | 验收 | |---|---|---| -| M1 数据与权限骨架 | 11 对象 · 状态机守卫 · 8 position / 6 set · 共享与 FLS · 配置域种子 | `validate`/`lint`/`typecheck` 绿;业务承办经 REST 看不到他人合同;财务看不到 `in_review` 合同 | +| M1 数据与权限骨架 | 11 对象 · 状态机守卫 · 7 position / 5 set · 共享与 FLS · 配置域种子 | `validate`/`lint`/`typecheck` 绿;业务承办经 REST 看不到他人合同;财务看不到 `in_review` 合同 | | M2 发起与审批 | F1 · F2 · F5 · F6 · F7 · 法务工作台 · 详情页 · 全量种子 | 走通 发起→受理→偏离→会签→签署与执行形式→生效,审批记录与审计齐全 | | M3 签后与分析 | F9–F14 · 履约与收付款 · 4 dataset · 3 看板 · zh/en | 演示数据下无空图;到期、逾期提醒在收件箱可见 | | M4 集成与可发布 | F8 电子签 · F15 CRM 交接 · S1–S6 与审批备忘录 · MCP 工具面 · 导入映射 · 文档 · 截图 · marketplace 发布 | 陌生人 clone 一条命令跑起;marketplace 一键安装;需求书逐条对应 feature-inventory 与测试 | diff --git a/README.md b/README.md index 35535b2..5bfff00 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,15 @@ accounts in **Setup → Users** and assign the seven positions: | `clm_executive` | 1 | Rung 4, and reads every contract with `route_executive` | | `clm_general_manager` | 1 | Rung 5, and reads every contract with `route_gm` | | `clm_records_manager` | 1 | Execution formalities, the executed copy and the archive number | -| (business requesters) | 3 | The default `clm_requester` set — launches contracts, sees their own | +| `clm_admin` | 1 | Maintains the configuration objects and holds full reach over every CLM object: the only position that may write `clm_contract_type` and `clm_approval_rule`, and the only one the app's **Administration** group is served to | -**Five of these accounts have to be named exactly**, because the fixture +**Three more accounts are business requesters, which is not a position.** +`clm_requester` is every employee's default set ([DESIGN.md](./DESIGN.md) §04), +so a requester holds no position at all: the set is granted in Setup as a +`sys_user_permission_set` row — a different object from the `sys_user_position` +rows above. They launch contracts and see their own. + +**Five of the accounts above have to be named exactly**, because the fixture references them by name: | Name it exactly | Give it | It receives | @@ -109,7 +115,7 @@ to tell" edge when there is none — the demo keeps exactly one unowned row, due seven days after boot, so that edge stays exercised. `src/data/plan-children.ts` proves it reachable and says why one is both the minimum and the maximum. -The other five positions are named however you like; they are reached through +The other six positions are named however you like; they are reached through the position, not by name. The dev admin is deliberately none of them: it holds no `clm_*` permission set,