Repository navigation
[PLT-4662] Add, remove and list user group members, and read the group audit log - #2091
Merged
Merged
Conversation
Gabefire
requested review from
StepanTytaLabelbox,
carl-l-chua,
gmadaan-hue,
gramos-lb,
ikerr,
mnoszczak and
vikram-kharvi
October 21, 2026 15:10
pablito25sp
approved these changes
Oct 21, 2026
…p audit log UserGroup.add_members, remove_members and list_members change or read one group's members without replacing the whole group the way update() does. UserGroup.audit_events and UserGroup.get_audit_events read the group audit log: who added, removed or changed the role of a member, attached a group to a project or detached it, or deleted a group, and whether a person or an automation did it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gabefire
force-pushed
the
gu/plt-4662-group-members-audit
branch
from
October 21, 2026 15:14
218823f to
2a47bfa
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Reviewed by Cursor Bugbot for commit 2a47bfa. Configure here.
| ], | ||
| "notifyMembers": notify_members, | ||
| }, | ||
| )["addUsersToGroupsV2"]["results"][0] |
There was a problem hiding this comment.
add_members crashes on missing resources
Medium Severity
add_members indexes the execute result immediately without raise_return_resource_not_found=True. A GraphQL RESOURCE_NOT_FOUND for a missing group or expired batch job returns None, so the subscript raises TypeError instead of ResourceNotFoundError. remove_members already passes the flag, and list_members treats None as missing.
Additional Locations (1)
Triggered by learned rule: execute returns None on RESOURCE_NOT_FOUND
Reviewed by Cursor Bugbot for commit 2a47bfa. Configure here.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


SDK half of PLT-4662. The API and MCP half shipped in Labelbox/intelligence#31630.
Airbnb runs vendor access through one group of ~490 people attached to ~230 projects, and could not tell who removed people from it. This lets them manage members from a script and read who changed what.
Added
UserGroup.add_members(members, notify_members=False): adds people with their group roles, without touching other members or projects (unlikeupdate(), which replaces the whole group). DrivescontinueAddUsersToGroupBatchto completion for large additions. UsesaddUsersToGroupsV2.UserGroup.remove_members(users, notify_users=True, reason=None, notification_reason=None): usesremoveUsersFromGroupV2.UserGroup.list_members(): reads current members with their group roles, without overwriting unsaved fields the wayget()does.UserGroup.audit_events(...)for one group andUserGroup.get_audit_events(client, ...)across every group the caller can manage. Filters: member, actor, actor kind (person or automation), event types, project, time range. Return aPaginatedCollectionofUserGroupAuditEvent. UsesuserGroupAuditEvents.UserGroupAuditEvent,UserGroupAuditEventType,UserGroupAuditActorKind,UserGroupAuditChannel, exported fromlabelbox, with a docs page. Unknown enum values from the server are kept as strings, as inLabelVersion.Changes made through these methods are recorded in the audit log as
channel=API, for the API key's owner.Testing
tests/unit/schema/test_user_group_members_audit.py. All 303 tests intests/unit/schemapass locally.add_membersandaudit_eventsbefore release.🤖 Generated with Claude Code
Note
Medium Risk
Changes affect access-control workflows (group membership and project access) via new GraphQL mutations; behavior is gated on server APIs and batch-job completion loops, with solid unit coverage but staging integration not yet run per PR notes.
Overview
Adds incremental user group membership APIs and a queryable audit log to the Python SDK, so scripts can add/remove/list members without replacing the whole group via
update(), and investigate who changed membership or project attachments.UserGroupgainsadd_members(viaaddUsersToGroupsV2, with automaticcontinueAddUsersToGroupBatchpolling for large adds),remove_members(removeUsersFromGroupV2, with notify/reason options), andlist_members(server read that does not overwrite other unsaved fields likeget()).UserGroup.audit_eventsandUserGroup.get_audit_eventsexpose filtered, paginateduserGroupAuditEvents(member, actor, type, project, time range).New module
user_group_auditdefinesUserGroupAuditEventplus enums for event type, actor kind, and channel; unknown server enum values stay as strings. Types are exported fromlabelboxand documented inuser-group-audit.rst. Unit tests cover mutations, batch continuation, audit filtering/parsing, and validation.Reviewed by Cursor Bugbot for commit 2a47bfa. Bugbot is set up for automated code reviews on this repo. Configure here.