Repository navigation
Description
Blocked-by: objectstack-ai/objectui#12078
Filing gate: ① product defect with reach measured. Class (a), user-visible. reach: REST PATCH /api/v1/data/sys_comment/:id with { reactions }, and the console's reaction button on every comment. Measured on @objectstack/* 17.7.0 by the dev of objectstack-ai/hotcrm#2029 (report 6083534286 there) on a fresh objectstack dev box, persona na.rep (sales_rep + na_sales_team), with sys_comment read, create and edit granted (objectstack-ai/hotcrm#2043).
Who acts on it: the objectstack triage seat routes it. Filed by the repo:hotcrm seat, session_018Mk4tab2eCyY41UTWK7y7V. ⛔ Not a claim. hotcrm has nothing to change for it: its guide content/docs/guides/files-and-comments says "React to a comment with an emoji", which becomes true for members when this is fixed (hotcrm AGENTS.md §2: wait, no workaround).
What happens
- A reaction is stored on the comment's own row:
sys_comment.reactions({ emoji: userIds[] }, the shape finding(plugin-audit):sys_comment.reactionsis described as "JSON array of emoji reaction objects", but its one reader and writer stores{ emoji: userIds[] }#20558 settled). - The platform's
sys_commentupdate floor lets only the row's author update it (created_by;plugin-security, deliberately, per its own comment). So a member's reaction click on someone else's comment is an update of another user's row, and is refused. - The console offers the reaction on every comment regardless.
Measured (17.7.0)
na.rep→PATCH sys_comment/ID{ reactions }on the admin's comment → 403PERMISSION_DENIED, on an account the rep can edit and on a quote and a contract they can read. The server logs "not permitted to update this sys_comment record (row-level security)".- Control: the same rep's edit of their own comment → 200.
So a non-admin member can react only to their own comments; reacting is a social action on other people's comments, so in practice members cannot react at all.
Seam
spec:sys_comment.reactions (a column of the author's row) → runtime:plugin-security sys_comment update floor → renderer:objectui chatter reaction click. The fix's shape (a narrow reaction write path, a separate reaction record, or a column-scoped exception to the floor) is the platform's to decide; ⛔ the author-only edit of a comment's text is correct and must stay.
Duplicate check
Semantic issue search (MCP, this container's REST /search is refused): objectstack "sys_comment reactions non-author…" → #4630 (closed, comment authorization, which introduced the floor); "reactions column on sys_comment cannot be updated by other users" → #20558 (closed, the stored shape), #4630, #4756 (closed, unrelated columns); objectui "comment emoji reaction permission denied…" → objectui#11019 (closed, a click rewriting other users' ids). None is this defect.
Dedupe words: sys_comment reactions 403 · react to comment permission · reactions created_by floor · chatter reaction non-author
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 9, 2026
Triage: first grade,
bug·priority:p2·domain:services·area:records,pm:blockedon the decision card #22505Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-09T15:54Z. ⛔ Not a claim, ⛔ not a dispatch.Why p2: members cannot react to anyone else's comment at all. The console offers the button on every comment, the click fails with 403, and an external app's guide promises the feature.
Why a decision, not a direction. The floor is deliberate: only the author updates a
sys_commentrow (plugin-security, with a moderation alternate). Each fix either loosens that floor, which is the maintainer's call, or changesreactions' published storage shape, which goes to the decision box. Filed as [Decision] comment reactions: members cannot react to another user's comment (the author-only update floor refuses it). Store each reaction as the reactor's own record, add one narrow reaction action, or open the floor for the column #22505:The recommendation is A, with B as the fallback. ⛔ C loosens a security floor, and ⛔ D deletes a published capability.
⛔ The author-only edit of a comment's text stays under every option, as this card says.
Blocked-by: [Decision] comment reactions: members cannot react to another user's comment (the author-only update floor refuses it). Store each reaction as the reactor's own record, add one narrow reaction action, or open the floor for the column #22505 (now in this body). This card closes through the PR that executes the ruling.
objectstack-fleet commentedon Oct 10, 2026
Blocker moved ·
domain:servicesseat 1 (#6021) ·session_013j5gkUCpqQiti4GgPqqmnt· 2026-10-10T01:17Z6091550406, supplement6091621568). A reaction becomes the reactor's ownsys_comment_reactionrecord.sys_comment.reactionsretires, with no aggregate and no data migration. The author-only floor onsys_commentstays.sys_comment_reactionrecord, andsys_comment.reactionsretires with no aggregate and no data migration #22566. This body'sBlocked-by:line was rewritten in this act, from [Decision] comment reactions: members cannot react to another user's comment (the author-only update floor refuses it). Store each reaction as the reactor's own record, add one narrow reaction action, or open the floor for the column #22505 to Comment reactions (ruling A amended on #22505): a reaction is the reactor's ownsys_comment_reactionrecord, andsys_comment.reactionsretires with no aggregate and no data migration #22566. The state stayspm:blocked.Generated by Claude Code
objectstack-fleet commentedon Oct 10, 2026
Blocker moved, and a hand-off for the application grant ·
domain:servicesseat 1 (#6021) ·session_013j5gkUCpqQiti4GgPqqmnt· 2026-10-10T06:25Z#22566 landed (PR #22603,
29a163f571onmain). A comment reaction is now its reactor's ownsys_comment_reactionrecord, one row per comment, emoji and user. A member reacts to any comment they can read, and deletes only their own reaction. The author-only edit rule onsys_commentis unchanged.This card stays
pm:blocked. Line 1 now readsBlocked-by: objectstack-ai/objectui#12078. The console's chatter still writessys_comment.reactionsuntil that card moves it to the new records. The column itself retires in #22573, after the console pin carries objectui#12078.Hand-off to the
repo:hotcrmseat (this session cannot write to hotcrm). The platform'severyonebaseline grants nothing on the new object, by the maintainer's ruling recorded onmember_default(seat answer6093553917on #22566, open to the maintainer's veto). An application that shows reactions grantssys_comment_reactionread, create and delete in the same permission set that grantssys_comment(objectstack-ai/hotcrm#2043 is where hotcrm grantssys_comment). The platform's own-record rule (owner_only_deletes) keeps a delete to the reactor, so the app's delete bit does not let a member remove another member's reaction. Without the grant, a member's first reaction answers a loud403, not a silent half-feature. The grant needs a hotcrm release that consumes the@objectstack/plugin-auditversion carrying #22566.Generated by Claude Code
objectstack-fleet commentedon Oct 10, 2026
Unlock scan: objectstack-ai/objectui#12078 closed (objectui
de302c7315), but the console pin does not carry it yet.pm:blocked→pm:on-holdTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-10T10:55Z. ⛔ Not a claim, ⛔ not a dispatch.Blocked-by: none
mainde302c7315. The chatter reads and writes reactions as the member's ownsys_comment_reactionrecords (objectui PR [finding]CLAIM_COMMENT_MARKERneeds a colon, so 24 of 54 livepm:dispatchedclaims are invisible — H2 reports them as claimless and H20/H27 cannot see them at all #12090)..objectui-shais20c6d351ad(2026-10-09T22:57Z), which does not containde302c7315. The console this repo serves still writessys_comment.reactions..objectui-shacarries objectuide302c7315. Then:completedafter one reading onmain: a member reacts to another member's comment;6094633923(hotcrm'ssys_comment_reactionread, create and delete) stays with therepo:hotcrmseat.objectstack-fleet commentedon Oct 11, 2026
Restart:
pm:on-hold→pm:queue. The console pin onmaincarries objectuide302c7315; what remains is the closing readingdomain:servicesseat 2 (#21118) ·session_013LbZ9MhPp1iriZEtgJqioA· 2026-10-11T18:57Z. ⛔ Not a claim, ⛔ not a dispatch. Thread-read:6096768082.6096768082), "objectstack's.objectui-shacarries objectuide302c7315", run in this act:.objectui-shaonorigin/mainis4997995022(PR feat(spec): the position form picks permissionSets from the permission-set registry (ref-multi:permission), with the console pin moved to 4997995022f8 #22794,ea9fd99dd).git merge-base --is-ancestor de302c7315 4997995022exits 0 on an objectui clone fetched in this act.6096768082); ② no PR referencing this card has merged since that comment (the newest merged reference is PR feat(plugin-audit): sys_comment_reaction, the reactor's own record of an emoji reaction #22603, earlier).main, where a member reacts to another member's comment, and then the card closescompleted. The application grant in6094633923stays with therepo:hotcrmseat.Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
Closed
completed: a member reacts to another member's comment, onmainand in the console the pin servesdomain:servicesseat 2 (#21118) ·session_013LbZ9MhPp1iriZEtgJqioA· 2026-10-11T19:43Z. Thread-read:6112525227.This is the closing reading the hold (
6096768082) and the restart (6112525227) set.mainb1d701b60: a reaction is its reactor's ownsys_comment_reactionrecord (Comment reactions (ruling A amended on #22505): a reaction is the reactor's ownsys_comment_reactionrecord, andsys_comment.reactionsretires with no aggregate and no data migration #22566, PR feat(plugin-audit): sys_comment_reaction, the reactor's own record of an emoji reaction #22603,29a163f571), so a member's reaction no longer updates another user'ssys_commentrow. Two integration pins run in Test Core on everymaincommit, unchanged since29a163f57; Test Core passed onb1d701b60in its merge-queue run:plugin-audit/src/comment-reaction-access.integration.test.ts, "a member reacts to ANOTHER member's comment, and the row is theirs";plugin-security/src/comment-reaction-own-record-floor.test.ts, "a member reacts to another member's comment and removes the reaction again" and "another member cannot delete it".4997995022(an objectui clone read by the seat in this act):RecordDetailView.tsxtakes therecordsstore whenever the deployment declaressys_comment_reaction, which this framework does. A reaction is created as the member's own row and deleted as that row. Thesys_comment.reactionscolumn path stays only where the object is absent (a v17 framework), and that column retires in Retire sys_comment.reactions (ruling A amended on #22505): no aggregate, no data migration, after the console reads reaction records #22573.sys_comment_reactionread, create and delete beside itssys_commentgrant. This was handed to therepo:hotcrmseat in6094633923, and it stays there. Until then, a member's first reaction answers a loud403, never a silent one.pm:queuecomes off and the card closescompleted. No PR references it.Generated by Claude Code