Uh oh!
There was an error while loading. Please reload this page.
Record who can customize a view: no Duly permission set can - #93
Conversation
Answers the question #84 was blocked on. Measured against a live `pnpm demo` with three self-registered accounts, each bound to exactly one Duly permission set through `sys_user_permission_set`: anonymous 401 UNAUTHENTICATED duly_member 403 FORBIDDEN — requires the `manage_metadata` capability duly_manager 403 FORBIDDEN — same duly_admin 403 FORBIDDEN — same platform admin 200 — Saved customization overlay (org=…) `sys_metadata` stayed at total: 0 across every refused attempt. So the org-wide overlay is reachable only by a platform admin (`admin_full_access`), which is what the original observation was made as — not by any identity our security model hands out. This is the "note, not p0" branch of the card: no security change is warranted, and none is made. The note also says why the obvious hardening is wrong. `systemPermissions` is an additive list with no deny form, so denying `manage_metadata` in `src/security/permission-sets.ts` would add a declared-and-unenforced key to the one file whose credibility rests on every line in it being live. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SqkTcrxUFci7nqXdbBSe2p
os-warren
commented
Sep 1, 2026
Reviewed — merging. The answer is "note branch", and the reason not to write the fix is better than the fix.Gates on the head merged with current The question this card was blocked on is answered, with controls rather than a single reading:
And the permission-set binding was verified by A/B rather than assumed — a bound Declining to write the contingent fix is the right callMy card said: if members can do it, deny the capability to The section is well-judged generally: verdict, result table, method, and the boundary of what remains true. Recording how it was measured is what stops this being re-derived in three months by someone who finds the same On your open question — file it, and I willYour recommendation B is right and your reason for not doing it yourself is also right: I conditioned the upstream filing on the member branch, and that branch did not happen, so writing into another repository's tracker was outside what you were authorized to do. Declining on scope while saying plainly that the merit is unchanged is the correct shape for that. Consider it authorized retroactively in spirit — but it is mine to file, and I am filing it now with your result table. The claim is smaller than the p0 this card was written against, and still real: an administrator demoing the app can freeze Cleanup verified — overlay deleted, Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#84
#84 was blocked on one question: the org-wide view overlay was measured as the dev admin, and the severity turned entirely on whether an ordinary member could do the same thing. #73 (
pnpm demo) unblocked it. It is measured now, and the answer is no — so this is the card's "note, not p0" branch, and there is no security change.What was measured
Against a live
pnpm demoon@objectstack/rest17.2.0. Three accounts were created by self-registration (POST /api/v1/auth/sign-up/email, which yieldspositions: ["user","org_member"],isPlatformAdmin: false) and each bound to exactly one Duly permission set throughsys_user_permission_set— nothing beyond whatsrc/security/permission-sets.tsgrants.The binding was verified live rather than assumed: a bound
duly_memberreadsduly_task200, an unbound self-registered account reads it403. So the sets really do resolve for these callers.Each then issued the request the grid issues — the declared
duly_task.defaultconfig withsortswapped tostatus asc:PUT /api/v1/meta/view/duly_task.default401 UNAUTHENTICATEDduly_member403 FORBIDDEN—Saving a metadata item requires the `manage_metadata` capability.duly_manager403 FORBIDDEN— sameduly_admin403 FORBIDDEN— same200—Saved customization overlay (org=org_mtik8rkleytx3x6b, state=active)sys_metadatareadtotal: 0after every refused attempt.Three things make the negative result trustworthy rather than a mis-shaped request:
200and lands the row finding: clicking a column header persists an org-wide view overlay — one person's sort silently rewrites the view for everyone #84 describes —type: view, name: duly_task.default, scope: platform, owner: null, organization_id: org_…, state: active. The 403s are a capability refusal, not a malformed payload.PUT /api/v1/meta/duly_task/views/default) andDELETE /api/v1/meta/view/duly_task.defaultcarry the identical gate — checked, because gating one door and not its twin is the usual bypass.Also swept for a second persistence route a member might reach instead: the org-wide
sys_view_definitionanswers403, and the one member-writable store,sys_user_preference, requiresuser_idand is per-person by construction — which is the right affordance, not an org-wide overlay.Cleanup: the control overlay was reset with
DELETE, and the end state was verified —sys_metadatatotal: 0, andduly_task.defaultback to the shippedsort: [{"field":"due_date","order":"asc"}]with_provenance: package. The dev database lives in the task worktree and goes with it.What this PR changes
One section in
AGENTS.md. No code. It records the verdict, the table above, and how it was measured, so nobody re-derives it — plus two things a future reader would otherwise get wrong:manage_metadatainsrc/security/permission-sets.ts.systemPermissionsis an additive list with no deny form. The entry would not be enforcement; it would be a declared-and-unenforced key of exactly the kind ADR-0049 exists to remove, sitting in the one file whose credibility depends on every line in it being live. The card's contingent fix is not just unnecessary — it is not expressible.objectstack-ai/objectuiconditional on members being able to do it, so it is deliberately left unfiled here and flagged for the maintainer instead — see the report on finding: clicking a column header persists an org-wide view overlay — one person's sort silently rewrites the view for everyone #84.Gates
All four green on
67c670e, the head of this branch, with a clean tree:validate's one warning is thehierarchy-securitycapability-provider notice thatAGENTS.mddocuments as this repo's expected state.No changeset — this repo has no changeset mechanism.
Generated by Claude Code
Generated by Claude Code