Summary
The console decides whether to show the Edit button (record page header, drawer header) from the object-level permission set only — allowEdit + writeScope. Record-level grants from the sharing service (sys_record_share rows with access_level: 'edit', produced by sharing rules) are not consulted. A user whose permission set says writeScope: 'own' but who holds an edit share on a record owned by someone else therefore sees no Edit entry at all, while the same user's PATCH /api/v1/data/<object>/<id> succeeds — the server honours the share, the UI does not.
This is the exact shape of a "department reporter" role: sheets are generated by the system (owner = the publishing admin), and the reporter is granted edit on their own department's rows through a sharing rule. They can write via REST and via import, but the page offers them nothing to click.
Minimal reproduction
Platform 17.2.0, objectstack dev, SQLite, single tenancy, requires: ['sharing'].
- Permission set for position
reporter on object kpi_entry_line:
{ allowRead: true, allowCreate: true, allowEdit: true, allowDelete: true, readScope: 'own', writeScope: 'own' }.
- Records of
kpi_entry_line created by the admin (owner_id = admin).
- A sharing rule (
sys_sharing_rule, object_name: 'kpi_entry_line', criteria matching the reporter's department, recipient_type: 'business_unit', access_level: 'edit', active) — materialised sys_record_share rows exist for the reporter.
- Sign in as the reporter.
Observed:
GET /api/v1/data/kpi_entry_line/<id> → 200 (visible through the share)
PATCH /api/v1/data/kpi_entry_line/<id> {"actual_value": 5000} → 200, value saved, hooks ran
/_console/apps/<app>/kpi_entry_line/record/<id> → header has NO 「编辑」 button (admin sees it)
list view「行内编辑」 → cells do not enter edit mode for this user
Control: the same user on a record they own (owner_id = reporter) → Edit button shown.
Expected
- The affordance check should ask the same authority the write path asks: object-level permission or an effective record-level grant (
sys_record_share / sharing rule) with edit. The metadata API (or the record API) could expose the resolved per-record capability (_permissions: { edit: true }) so the console never re-derives it from the coarse writeScope.
- At minimum, when
allowEdit is true and writeScope is own, the console should not hide Edit for records the sharing service marks editable for the caller.
Environment
@objectstack/* 17.2.0 (runtime, console) · Node 22 · better-sqlite3 · single tenancy · SharingServicePlugin active. App: objectstack-ai/kpi (src/security/index.ts reporter set, src/services/sharing-service.ts grants edit while the sheet is not frozen).
Summary
The console decides whether to show the Edit button (record page header, drawer header) from the object-level permission set only —
allowEdit+writeScope. Record-level grants from the sharing service (sys_record_sharerows withaccess_level: 'edit', produced by sharing rules) are not consulted. A user whose permission set sayswriteScope: 'own'but who holds aneditshare on a record owned by someone else therefore sees no Edit entry at all, while the same user'sPATCH /api/v1/data/<object>/<id>succeeds — the server honours the share, the UI does not.This is the exact shape of a "department reporter" role: sheets are generated by the system (owner = the publishing admin), and the reporter is granted edit on their own department's rows through a sharing rule. They can write via REST and via import, but the page offers them nothing to click.
Minimal reproduction
Platform 17.2.0,
objectstack dev, SQLite, single tenancy,requires: ['sharing'].reporteron objectkpi_entry_line:{ allowRead: true, allowCreate: true, allowEdit: true, allowDelete: true, readScope: 'own', writeScope: 'own' }.kpi_entry_linecreated by the admin (owner_id= admin).sys_sharing_rule,object_name: 'kpi_entry_line', criteria matching the reporter's department,recipient_type: 'business_unit',access_level: 'edit', active) — materialisedsys_record_sharerows exist for the reporter.Observed:
Control: the same user on a record they own (
owner_id= reporter) → Edit button shown.Expected
sys_record_share/ sharing rule) withedit. The metadata API (or the record API) could expose the resolved per-record capability (_permissions: { edit: true }) so the console never re-derives it from the coarsewriteScope.allowEditis true andwriteScopeisown, the console should not hide Edit for records the sharing service marks editable for the caller.Environment
@objectstack/*17.2.0 (runtime, console) · Node 22 · better-sqlite3 · single tenancy · SharingServicePlugin active. App: objectstack-ai/kpi (src/security/index.tsreporter set,src/services/sharing-service.tsgrantseditwhile the sheet is not frozen).