Repository navigation
Conversation
|
/coder-agents-review |
This comment has been minimized.
This comment has been minimized.
|
/coder-agents-review |
There was a problem hiding this comment.
This round reviewed the fixes for round 1 and the new project-deletion behavior. Findings: 1 P1, 3 P2, 9 P3, 3 P4, 12 Nit new; two earlier findings are reopened: use chats can still write memories through their agent, and the list-cap comment. Most round 1 findings are verified fixed, including revocation (memory loss on the next turn), admin binding, canonical UUID keys, foreign users, the owner entry, the 403/404 split, the memory prompt, and the flag help text. The duplicate ACL helper finding is closed on your explanation.
Please split the PR. Commit c0c39cb changes DELETE /chats/projects/{project} for every project, shared or not: it deletes the project's chats, including other users' chats and their sub-chats, instead of detaching them, and adds a 409. Most new findings in this round come from that change (the panic without the AI Gateway, the races, the stale worker_id, the 409 message, missing audit, the long transaction, the UI text), and none of them concern who can see a project.
- This PR: the sharing API, with detach on delete.
- Separate PR: delete chats with their project. Include
Server.DeleteChatProject, the 409 branch,DeleteRemovesChats, the ARCHITECTURE.md note, theGetChatProjectChatsForDeleteandDeleteChatProjectChatsqueries moved out of #30479, and the delete-dialog text inChatsSidebar.tsx:374andProjectHeaderSection.tsx:161.
Out of scope (needs a ticket or explicit acceptance by a human):
coderd/database/queries/chatprojects.sql:56:IsChatProjectAccessibleByUserID(from #30479) is a third copy of the project ACL rules, afterpolicy.regoandGetChatProjectsAccessibleByUserID, and it already differs from the list query (it requiresreador*; the list matches any key). If one copy changes alone, the list, HTTP authorization, and chatd memory access disagree.coderd/database/queries/chatprojects.sql:57: theIsChatProjectAccessibleByUserIDcomment repeats the reason theChatProjectUsableBydoc gives, so the fact lives in both PRs.coderd/rbac/acl/updatevalidator.go:56: the empty-role skip comment still names only workspace and template roles.
Notes:
coderd/x/chatd/memory.go:36: revocation applies from the next turn. A sharee removed during a long turn keeps memory read and write until that turn ends, which matches the PR description.coderd/database/queries/chatprojects.sql:114: when a project is deleted, sharees' automations that target or were created by a chat in it lose that reference (chat_automationsON DELETE SET NULL), with no notice.
site/src/pages/AgentsPage/components/ChatsSidebar/ChatsSidebar.tsx:374
P1 [CRF-35] The project delete dialog still says "Chats in this project will be kept and move back to the Chats list.", but deleteChatProject now deletes those chats. (Netero)
Server.DeleteChatProject (coderd/x/chatd/projects.go:23) deletes every user's root chats and sub-chats, and DeleteRemovesChats shows both the owner's and the sharee's chat return 404 afterward. An owner who confirms this dialog permanently deletes their own and their sharees' chats after being told they are kept. ProjectHeaderSection.tsx:161 has the same string. Moving the deletion change out of this PR (see the split finding on projects.go:23) makes this text correct again; otherwise update both strings here.
🤖
🤖 This review was automatically generated with Coder Agents.
|
Decisions on this round's summary: deleting chats with the project stays in this PR rather than a split (delete dialog text updated in 43b9800), and |
|
/coder-agents-review |
There was a problem hiding this comment.
Further review is blocked until one finding gets a response. The maxChatProjectsPerOwner comment at coderd/chat_projects.go:329 still says the cap "bounds the project list every agents page loads", but the list now includes shared projects and has no limit. Round 2 reopened this in the list-performance thread (it stayed marked resolved because unresolving it failed), and it has no reply. Change the comment to say the cap limits owned projects only, add a limit to the list, or reply with why neither is needed.
The round 2 findings on deletion, the AI Gateway panic, locking, stale leases, audit, watch events, and comments have commits or replies. The panel will check those fixes next round, along with your decision to keep chat deletion in this PR.
You say use chats writing memories through their agents is intended. That needs a human decision, because it lets any use sharee put text into the memory index of the owner's chats. The role doc and PR description now describe the behavior. A maintainer should accept it on the PR or file an issue.
🤖 This review was automatically generated with Coder Agents.
There was a problem hiding this comment.
Review is blocked until the author responds to one finding from the previous round. The other seven are fixed or acknowledged at 1e98984.
No response yet (posted in the previous review's body): [CRF-312] coderd/chat_projects.go:258. Deleting a project detaches every user's chats in one unbounded UPDATE through chats_project_id_fkey ON DELETE SET NULL, which row-locks all of them. On PG13, with 50,000 chats in one project, the FK trigger took 8.9 s, and a concurrent update on one of those chats waited 5.7 s. A project shared with the Everyone group can collect that many chats. A response can be one of these: batch the detach in this PR, record the cost in #30683 (which replaces this delete), or explain why it does not need fixing. If the gap is accepted without a fix or ticket, that needs a human decision.
🤖 This review was automatically generated with Coder Agents.
|
Ignore the delete issue, it is addressed in a followup PR on the stack |
|
CRF-312: Accepted for this PR. The unbounded detach is main's existing delete behavior, kept here on purpose, and #30683 replaces it with a tombstone plus background archive that takes no chat locks in the request. (Coder Agents) |
|
/coder-agents-review |
There was a problem hiding this comment.
This round is the first panel review of head 1e98984. That head merged main, which brought chat project instructions (#30367/#30368). The PR gates resolveProjectInstructions with ChatProjectUsableBy, and subagents check the root chat's owner, so a revoked sharee's chats lose instructions and memory together (Kurapika, Pariston). The HTTP instructions handlers from main did not get the same treatment as the rest of the PR. A use sharee gets 404 instead of the documented 403 (CRF-319), and no sharing test calls those endpoints (CRF-322). CI passed when this round started.
CRF-312 is closed as a human decision: the delete path is handled in #30683.
This round has 1 P3, 8 P4, and 1 Nit.
coderd/chat_project_instructions.go:75
P3 [CRF-319] putChatProjectInstructions (here) and deleteChatProjectInstructions (:188) return 404 to a use sharee. The PR description says use "can't edit them directly (403)", and project PATCH/DELETE and memory create/delete now return 403 through authorizeChatProjectChange. (Netero, Ryosuke, Pariston)
Before sharing, only the owner and role holders could read a project, so this 404 never reached a reader. Now a sharee who just read the instructions with GET gets "Resource not found" from PUT on the same path, and a client treats that as a deleted project (the CRF-12 bug on a sibling endpoint). A scratch test at this head showed use GET returning the owner's text, use PUT and DELETE returning 404, and admin PUT and DELETE succeeding. Call api.authorizeChatProjectChange(rw, r, policy.ActionUpdate, project.RBACObject()) in both handlers. The comments at :135 and :218 ("without read can still save/delete") stop being true once read is checked first, so update them too.
🤖
🤖 This review was automatically generated with Coder Agents.
Database and authorization layer for chat project sharing (experiment `chat-projects`), part 1 of 2. #30439 adds the API on top of it. Nothing here changes behavior: projects start with empty ACLs, no endpoint writes them yet, and deleting a project still detaches its chats. Project deletion is in #30683. - **Schema:** migration `000621` adds `user_acl` and `group_acl` jsonb columns to `chat_projects`, typed as `ChatACL` like chats, with GIN indexes. It also adds the `chat_project:share` API key scope. - **Queries:** - `GetChatProjectsOwnedOrSharedWithUserID`: owned projects plus projects with an ACL entry for the user directly, through a group, or through the Everyone group (whose ID is the organization ID). Entries count only for members of the project's organization. Keys match regardless of actions, so dbauthz filters the rows. - `IsChatProjectAccessibleByUserID`: whether a user owns a project or holds a `read` or `*` grant on it, for code running under a system subject. With sharing disabled, dbauthz answers owner-only. - `GetChatProjectByIDForUpdate`: lets the ACL update read, modify, and write in one transaction. - `UpdateChatProjectACLByID`. - **RBAC:** - New `share` action on `chat_project`. dbauthz requires it to update the ACL. - `ChatProject.RBACObject` attaches the project ACL. Memory objects get a derived ACL: project `read` grants memory read, and `read` with `update` grants memory create and delete. Wildcard grants count. Read sharees change memories through their chats' agents, which #30439 gates. Project instructions authorize through the same object, so a `read` grant reads them and an `update` grant edits them. - `--disable-chat-sharing` also covers projects: ACLs are ignored, the ACL update is rejected, and roles deny `chat_project:share`. The help text and chat sharing docs say so. - **Audit:** `user_acl` and `group_acl` changes are tracked. - **Tests:** - Querier tests run the access queries both raw and through dbauthz (owner, direct user, group, Everyone, wildcard grants, a member of another org, grants without read). - RBAC object and memory ACL tests, with an authorizer check, in both sharing modes. - dbauthz cases including the disabled guards, and the `chat_project:share` negation in the roles test. The generated TypeScript changes only add the new scope value. > Generated by Coder Agents.
Addresses review: use sharees read and write memories directly, the ACL response hides entries outside the project's organization, the access query is renamed IsChatProjectUsableByUserID, and comments and the architecture doc are tightened.
Share the project access gate between memory and instructions, cover sharee instruction access, return 403 to readers who cannot edit instructions, and say that deleting a project deletes its instructions.
|
/coder-agents-review |
There was a problem hiding this comment.
e479ae8 fixes every round 33 finding (CRF-319 to CRF-329); reviewers checked each one against the code and ran the tests. The main merge (c3dea24) also changed behavior: any read grant now gets memory create and delete over HTTP. The codersdk role doc, ChatProjectRoleActions, the ARCHITECTURE table, the tests, and the audit path all agree with that change (Netero, Kurapika, Pariston, Mafuuu, Knuckle), and it matches the CRF-9 decision. The merge also added a filter that hides ACL entries for users outside the project's organization, and those entries still come back into force (CRF-335). The rest are leftovers from the fixes: a doc comment now attached to the wrong function, use sharees shown edit buttons, duplicate subtests, and docs fixed in one place but not its twin. CI was still pending when this round started.
This round has 3 P3, 8 P4, and 2 Nit.
ProjectDetailsPanelView.tsx and the PR description's role table are outside the diff, so CRF-331 is in the body and CRF-333 covers the PR description too.
site/src/pages/AgentsPage/components/ProjectPage/ProjectDetailsPanelView.tsx:130
P3 [CRF-331] A use sharee who opens a shared project sees the Create (line 116) and Edit instructions (line 130) buttons. Saving or deleting then returns 403 (TestChatProjectSharing/User, chat_project_acl_test.go:94-97), and the user sees "Failed to save instructions." Edit and Delete project are already gated on permissions (ProjectActionsMenuItems.tsx:49), and the PR description says the UI hides actions the caller cannot do. Pass project.permissions.update into ProjectDetailsPanel and hide both buttons when it is false. Add a use story like ProjectActionsWithoutUpdateOrDeletePermission. (Netero)
🤖
🤖 This review was automatically generated with Coder Agents.
Drop a user's project grants when they leave the organization, restore 403/404 for instruction edits without breaking update-only roles, hide instruction editing from users who cannot update, and tighten docs, logs, and tests.
|
CRF-331: Fixed in 250489a. Create and Edit instructions are hidden without update permission; story and vitest added. (Coder Agents) |
|
/coder-agents-review |
There was a problem hiding this comment.
250489a fixes all 13 round 34 findings (CRF-330 to CRF-342), and reviewers checked each one. The new trigger in migration 000624 drops a departing member's grants, and its backfill is correct (Netero ran it from migration 623). With the indexes it uses, a membership delete touches only the rows that hold the user's key (Knuckle). Listing groups from other organizations is correct, because those entries still grant access (Kurapika, Pariston, Mafuuu, Kite). CI was pending when this round started.
The main new finding is CRF-348: a race between a PATCH and a membership delete still stores the grant that the trigger exists to remove. Two reviewers reproduced it. The other findings are test gaps and comments.
This round has 1 P3, 6 P4, and 2 Nit.
Out of scope: chats.user_acl has no matching organization_members delete trigger, so chat grants come back when a user rejoins (Kurapika, Kite).
🤖 This review was automatically generated with Coder Agents.
Validates ACL users inside the transaction after locking their memberships, so a concurrent membership delete cannot miss a new grant. Also covers the 000624 backfill, cross-organization trigger scope, foreign group listing, and update-only instruction deletes, and shows full instructions to users who cannot edit them.
|
/coder-agents-review |
There was a problem hiding this comment.
08f500c fixes all 9 round 35 findings (CRF-343 to CRF-351). The CRF-348 fix holds: PATCH locks the memberships (FOR KEY SHARE) and then the project row, the 000624 trigger locks in the same order, and validation now reads through tx. Knuckle, Kurapika, Pariston, Mafuuu, and Razor each traced this, and none found a deadlock or a missed grant. Removal-only PATCHes take no lock, which is correct. The findings are test gaps, comments, and one audit diff. CI was pending when this round started.
This round has 7 P4 and 1 Nit.
ProjectDetailsPanel.test.tsx has no net change against the base, so CRF-352 is in the body.
Out of scope: the shared validateACLOrganization (mcp_acl.go:394, :414) returns database failures as 400 validation errors for skill and MCP server ACL PATCHes (Razor). This PR's copy returns 500 on them, which is correct.
site/src/pages/AgentsPage/components/ProjectPage/ProjectDetailsPanel.test.tsx:103
P4 [CRF-352] Re-raise of CRF-346. Our suggestion to move the test into ProjectDetailsPanelView stories lost the only check of ProjectDetailsPanel.tsx:95 (project.permissions.update ? openEditor : undefined). The View stories pass onEditInstructions: undefined directly. Netero changed line 95 to onEditInstructions={openEditor}, and the unit and storybook suites in ProjectPage/ both still passed. Add a play to WithoutUpdateOrDeletePermission in ProjectPage.stories.tsx:113, which renders the container: wait for the instructions text, then assert there is no "Edit instructions" button. (Netero P3, lowered because the regression would show a button that returns 403, not grant access; Bisky)
🤖
🤖 This review was automatically generated with Coder Agents.
|
CRF-352: added a play function to |
|
/coder-agents-review |
There was a problem hiding this comment.
8829317 fixes all eight open round 36 findings (CRF-352 to CRF-360). Netero checked the new tests by mutation. With the membership lock disabled, TestChatProjectACLMemberRemovalBeforeGrant fails 3 of 3 runs, and it passes with -count=20 -race. The migration, trigger, and container story tests each fail when the code they target is changed. aReq.Old = current is correct on failure: InTx at the default isolation level runs the closure once, so a rolled-back request audits the locked row with no change (Knuckle, Chopper). CI was pending when this round started.
This round has 1 Nit. No findings are open above Nit, so this review approves.
🤖 This review was automatically generated with Coder Agents.
| require.NoError(t, tx.Commit()) | ||
|
|
||
| err = testutil.RequireReceive(ctx, t, patchErr) | ||
| requireSDKError(t, err, http.StatusBadRequest) |
There was a problem hiding this comment.
Nit [CRF-361] The test checks only the 400 status. With only that check, a 400 from any other patchChatProjectACL check would also pass. The sibling validation tests (:282-283, :309-310) also assert sdkErr.Validations. Keep the return value of requireSDKError and assert Len(sdkErr.Validations, 1) and Field == "user_roles". (Chopper)
🤖
API for chat project sharing (experiment
chat-projects). Builds on #30479 (merged).Owners share a project with users, groups, or the whole organization (the Everyone group, ID = organization ID). Chats in a shared project stay private.
useadminOnly the owner, and administrators whose role grants delete, can delete a project.
GET/PATCH .../chats/projects/{project}/acl, same shapes as/chats/{chat}/acl, plus SDK methods. Project responses include the caller'spermissions(update,delete,share); the UI hides edit and delete accordingly.GET /chats/projectsreturns owned and shared projects. RemovesGetChatProjectsByOwnerID.chatd.ChatProjectUsableBy). Role grants don't count. If the grant is removed, existing chats lose memory and instructions on their next turn.000624drops a user's grants when they leave the organization, so rejoining doesn't restore access.Known gap: project deletion still detaches chats, and a sharee's open sidebar keeps showing them until reload. #30683 replaces this.
Not included: share notifications,
/acl/available, sharing UI.Decision log
usegrants memory read/write over HTTP, because agents in a sharee's chats can already write memories. Making the agent read-only for sharees was the alternative (@f0ssel chose sharees changing memories through use).sharecan grant themselves access and then use the project. Accepted to keep access control simple (@f0ssel).