Skip to content

[Decision] Permission model for duty review in the open edition — field-level write grant, platform action, or hook? #130

Open

Description

@os-warren

Part of #127 (A — permissions in the open edition). Decision card — not dispatchable until ruled.

The question

#116 was ruled "D — demo-usable is the bar" on 2026-09-02, with the open question deferred: in a real deployment, which permission model lets a reviewer approve a duty (review_status → approved / returned) without being able to rewrite its cadence, owner or catalog link? The object-level edit bit cannot distinguish the two. Under the template positioning the bar moves from "demo" to "a customer installs it and the permissions are right", so the deferred question is now on the path.

Governing text: docs/product/design-principles.md §8 (managers have exactly one write action: assign — review is the one addition #107 made); docs/deployment/security.md; ADR-0057 depth scopes (resolved only by @objectstack/security-enterprise; open edition is owner-only).

Options

Option What it takes Trade-off
A Keep D: review_status is an ordinary field write; document that a reviewer can also edit cadence nothing honest but weak; a template ships a known hole
B Field-level write permission on duly_duty: reviewer set may write review_status + review_note only, owner set may write everything except those two measure first whether 17.3.0 permission sets carry field-level write grants and whether the console honours them on the edit form; then author two sets cleanest if the platform supports it; unknown until measured
C Approval as a platform-provided action (server-side handler flips review_status after checking the caller is the owner's manager), edit of review_status on the form removed depends on objectstack-ai/objectui#7234 (app-declared actions do not render) — blocked today correct boundary, but blocked on a platform fix with no date
D Make review_status writable only from a hook that checks current_user against the duty's manager chain, refuse otherwise app code; hook has the pre-image and the caller works on any edition; moves a security check into the app, which the platform is supposed to own

四维分析(中文)

  • 实际业务需求:真实部署里审定人和负责人是不同的人,审定人不该改周期和负责人。清单审定在真实部署里没人能推进:需要一个不等于「编辑整条职责」的审批写权限 #116 实测:现有权限集做不到这个区分。模板客户第一件事就是建权限,这是真需求,不是推测。
  • 项目长远合理性:权限边界应由平台承担(声明即强制)。B 若平台支持字段级写权限,是契约优先的正路;C 是最终形态但被 objectui#7234 卡住;D 把安全检查放进应用 hook,是 workaround,长期要还。A 不是方案。
  • 防 AI 写代码犯错:B 在元数据里声明,平台拒绝越权写,AI 写错权限集会被 validate 或运行时响亮拒绝;D 的 hook 逻辑是 AI 最容易写出漏洞的地方(谁是"经理链"、空值、批量写)。
  • 创业阶段不扩散需求:B 不新增能力面,只用已有权限模型;C 等平台;D 新增一段应用侧安全代码。

推荐:先测 B,B 可行即定 B;B 不可行则 A 加明确文档,并把 C 挂在 objectui#7234 上等,⛔ 不做 D。 前提(可证伪):@objectstack/spec 17.3.0 的权限集 schema 是否有字段级写权限、console 编辑表单是否按它禁用字段。派发令要求 dev 先验这两条再动手;前提不成立即报 fork,不得退回 D。

工作量:B 约 1–2 天(含测量与两套权限集 + 测试);A 半天;C 阻塞;D 2–3 天。

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    Seat note at 2026-11-02T06:53Z (duly lane seat, session session_011HyoSXGRy6L13mYq1Hp4n1): two measurements from the #178 card thread bear on this decision. They were taken on main 94419c6, @objectstack 18.2.0, live pnpm demo; the report is in the project file duly-178-duty-provenance/step0.md.

    1. A duly_admin can approve a duty alone. A duly_admin who is not a platform admin can write a duty naming another person as owner, then move it to to_review and approved, with both writes answering 200. The approve option's visibleWhen (record.owner != current_user.id) is satisfied because the owner is someone else. A member can create a duty with source catalog, another person as owner and a foreign business unit #178 locks owner for member and manager only, so this stays open for duly_admin. The gap is owner versus owner_id: who wrote the duty is not the person the check compares against.
    2. The owner's confirm step is unreachable for its owner. Members and managers have no allowEdit on duly_duty, so the owner cannot move their own to_confirm duty to to_review (a PATCH to to_review answers 403). Today only an admin can move a duty past to_confirm.

    Neither is changed by #178. Both depend on which permission model this card chooses.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions