Repository navigation
Description
② Maintainer decision (filing gate category ②). Part of #127 (A — a permission model that is correct in the open edition). Found by the #132 card thread on a fresh clone (PR #141, docs/template-checklist.md item 7).
维护者速读
模板最核心的一步是"把你自己的职责清单导进来"。实测(17.3.0,全新克隆):管理员把职责导入、指给张三之后,张三自己登录看不到这条职责,它生成的任务也看不到;张三自己建的职责他能看到。原因是平台的"只看自己的"按记录的创建人(owner_id)判断,而 Duly 的"负责人"是另一个字段(owner)。导入的人是管理员,所以记录归管理员。这是安全边界上的选择,所以呈你裁:A 等平台支持"声明哪个字段是归属字段";B 在 Duly 里写 hook 把两个字段保持一致;C 只写文档;D 用平台已有的共享规则按 owner 字段共享(要先测平台是否已支持)。推荐 D,前提不成立则 A,不做 B。一字即可:A / B / C / D。
The problem in one sentence
A duty or task that someone else created for you — by import, or by an admin — never appears in your own lists, so the import path the template is built around produces a tenant in which every member's week is empty.
Measured (17.3.0, pnpm dev, fresh clone; from the #132 report)
GET /api/v1/data/duly_dutyas an imported duty's owner,duly_memberbound:total 0. The same person's self-created duty:total 1.- The imported row's
owner_idis the importing admin; itsownerfield is the member. duly_dutyandduly_taskaresharingModel: 'private';duly_membergrantsreadScope: 'own'(src/security/permission-sets.ts). For a private object the sharing layer's read filter is the owner match OR the caller'ssys_record_sharegrants, and an RLS policy can only narrow it (src/security/sharing-rules.tsheader).
Governing text: AGENTS.md rule 9 (metadata first; a platform gap is filed, not worked around) and the product invariant "one task has exactly one owner"; src/security/sharing-rules.ts (fail closed; a grant that reaches the wrong people is the worse failure); ADR-0057 (depth scopes); epic #127 decision rule (a security boundary goes to the maintainer).
Premises, each with its re-check
- Record-relative sharing recipients exist on the installed platform. Sharing rules cannot name a RECORD-RELATIVE recipient (the owner's manager; the value of a user field on the matched record), and no other declarative surface can widen a private object either objectstack#14103 ("Sharing rules cannot name a RECORD-RELATIVE recipient … the value of a user field") closed
completed2026-09-03. Re-check:grep -rn "ShareRecipientType\|recipientField\|record_field" node_modules/@objectstack/spec/src/security/sharing.zod.ts(positive control:business_unit, which must hit). Not verified here. - Dispatched tasks inherit the same problem only when their
owner_idis not the assignee. Re-check: onpnpm demo, read one member'sduly_taskrows and compareowner_idwithowner. Not verified here.
Options
| Option | What the customer sees | Work | |
|---|---|---|---|
| A | Platform: an object declares which user field is its ownership field for own scope; Duly names owner. Filed upstream, Duly waits. |
Correct and declarative once it ships; until then imports stay invisible to their owners. | Duly: one line after the platform ships; platform card: no precedent measured. |
| B | Duly hook keeps owner_id equal to owner on duly_duty and duly_task. |
Works today on any edition. | ~1 day; new security code in the app. |
| C | Document only; every owner creates their own duties. | The import path is useless for its main purpose. | half a day |
| D | Declarative criteria sharing rule: share each duly_duty / duly_task with the user in its owner field (premise 1). |
Works today if the platform carries it; fails closed if not. | ~1 day incl. measurement; no precedent in this repo. |
四维分析
- 实际业务需求:导入是 M4 的核心路径("装上、导入自己的清单、不用我们也能跑")。今天导入后每个成员的"我的本周"都是空的,这是确定会撞上的,不是推测。
- 项目长远合理性:归属与可见性应由平台声明并强制。D 用平台现成的共享规则(若 #14103 已交付),A 是更根本的平台形态;B 把一条安全规则写进应用 hook,长期要还,而且和平台的归属模型并行存在两份事实。
- 防 AI 写代码犯错:D 和 A 都是声明式,写错会被 validate 或运行时拒绝、并且失败时关闭;B 的 hook 要处理批量写、空值、系统上下文写入,是 AI 最容易写出漏洞的地方,漏了就是静默越权或静默不可见。
- 创业阶段不扩散需求:D 不新增能力面;A 在平台新增一个声明键;B 新增应用侧安全代码;C 最省但等于放弃导入。
推荐 D;D 的前提 1 不成立则 A(上游立卡,Duly 写明缺口并等待),⛔ 不做 B。 只看①选 D;②③④ 是否翻转:否。置信缺口:没有实测 #14103 交付的具体形状,也没有核实派发出来的任务是否同样受影响(前提 2)。
裁后执行
D:派一张 duly 卡,先验前提 1、2,再写两条共享规则和对应测试(导入的职责与派发的任务对负责人可见、对他人不可见);前提不成立即报 fork,不得退回 B。A:席位在 objectstack 立平台卡,本卡转 pm:blocked 挂上它,getting-started 第 8 步保留缺口说明。
os-decision-facets
- ① 项目长远合理性:D/A 收窄特例(归属由平台声明),B 增加应用侧特例。
- ② 实际业务拉动:今天导入后的每个成员都撞上。
- ③ 防 AI 犯错:声明式共享规则失败时关闭,优于 hook 的静默容错。
- ④ 创业阶段不扩散:D 零新增能力面,优于 B 的新安全代码。
Prior rulings read: owner visibility, readScope own, sharing rule recipient → 0 hits in duly issues; ADR none; thread: none
Dedupe: duly issues (all states) with owner / visib / import / readscope in the title, 2026-10-26 → 3 hits: #110 (the import feature itself, closed), #96 and #70 (unrelated); none on visibility.
Generated by Claude Code
Activity
Refuse a task duty the writer cannot read, on every door (#177)
Lock a task's source, owner and business unit against caller writes w…
objectstack-fleet commentedon Nov 2, 2026
Seat note (2026-11-02T07:30Z), measured in duly#180 Step 0 on main 358c2ca / 18.2.0. This is input for the decision on this card; it changes no ruling.
On today's demo, seeded tasks carry
owner_id= Dev Admin. As a result, Owen Pryce (duly_member) reads 0 of his seeded tasks: 1 task hasowner= Owen and 0 haveowner_id= Owen. Whatever this card decides about which fieldownscopes on, the seed has to stamp that field with the assignee.Generated by Claude Code