Skip to content

A member's task and duty pages show the business unit as a raw id, because Duly members and managers cannot read sys_business_unit #180

Closed

Description

@objectstack-fleet

Found by the #176 card thread on main 94419c6, @objectstack 18.2.0, live pnpm demo. A screenshot is in the project file duly-176-task-provenance/browser/.

What happens

duly_member and duly_manager get 403 on sys_business_unit. So a record that carries a unit (a task, and a duty) renders the lookup as a raw id on the record page and in lists for them, instead of the unit's name.

This predates #176. After #176 every hand-made task carries the writer's unit, so it shows on every member's own task.

What done looks like

  • Measure what each Duly set can read on sys_business_unit and what the console renders for a lookup the viewer cannot read.
  • Decide with a reason what a member and a manager may read. Unit names only, through a field-limited read, are probably enough. Rows outside the viewer's own unit tree may be org-structure information that the product does not want disclosed.
  • Grant the smallest read that makes the name render, or display the name some other way, and pin it.
  • Browser check in en-US and zh-CN: a member's task and duty pages show the unit's name.

area:security because it widens a read grant. Check it against #130 and #143 before granting anything.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 8
    Session: session_011HyoSXGRy6L13mYq1Hp4n1
    Account: os-warren (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-y42kg9 (platform-assigned card-thread branch, at origin/main 358c2ca)
    Worktree: duly-issue-180
    Domain: n/a. objectstack-ai/duly is a single-lane app repo with no domain:*.
    Seat: repo:duly#1
    File surface: src/security/permission-sets.ts (the MEMBER_OBJECTS entry sys_business_unit: { allowRead: true }, its note, one header line), test/security.test.ts (one named exception in the five-objects and duly-namespace invariants: sys_business_unit, read only, no other bit), test/business-unit-read.test.ts (new), docs/deployment/security.md (one row). No fields map, no scope keys, no write bits; no #179 file, no task/duty hook. Stop on any breach until the seat posts a Claim amendment.
    Container & model: M, mode:thread, model: TIER_DEFAULT (hand-derived), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: Members, managers and Duly admins read sys_business_unit (object-level read only) so the unit lookup on task and duty pages shows the unit name, and a non-platform duly_admin can Import duties whose unit is named.
    Thread-read: none
    Premise: Step 0 on 18.2.0 (project file duly-180-unit-name/step0.md): all three Duly sets get 403 on sys_business_unit and the console shows the raw id. The object has no sharingModel so it defaults public. Members already read every colleague's unit id and manager via sys_user. A name-only FLS mask is not shippable: it also masks platform admins holding a Duly set and blanks Setup > Business Units (F1, upstream). Object-level read prototype: names render, create/edit stay 403, admin Setup unchanged, Import as duly_admin goes 0/19 to 19/19 (closes the #178 F5 finding).
    Serial constraints cleared: #179 (another thread) is in src/actions/catalog.*, zh-CN.ts and catalog tests plus test/duty-provenance.test.ts: no shared file. If either needs a file the other holds, the second to land merges main (never rebase) and re-runs the gates.


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions