From 1ea83bc56de61c2b4dd7553c791920549f3f4cd7 Mon Sep 17 00:00:00 2001 From: Sawyer Date: Wed, 2 Sep 2026 00:45:51 -0700 Subject: [PATCH] roles: scope person picker to user-kind principals only (CL-6664) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Assign a role" person picker showed all principals — people, agents, and workflows — in one flat list. This surfaced 49+ duplicate placeholder- named service accounts (e.g. "Dana Reyes Gaj0a5c7 Localhost") in the picker, none scoped to the workbench's actual member roster. Fix by filtering principals to kind === "user" in both the picker select and the assignments table, matching the People section's member list. Remove the now-unused optgroup structure and PRINCIPAL_KIND imports. All 4 tests rewritten to verify user-only filtering. --- packages/settings-ui/src/identity.ts | 10 ++- packages/settings-ui/src/roles-section.tsx | 34 ++++------ .../settings-ui/test/roles-section.test.tsx | 65 +++++++++++++------ 3 files changed, 63 insertions(+), 46 deletions(-) diff --git a/packages/settings-ui/src/identity.ts b/packages/settings-ui/src/identity.ts index 209422c9e..3acff7402 100644 --- a/packages/settings-ui/src/identity.ts +++ b/packages/settings-ui/src/identity.ts @@ -7,12 +7,10 @@ // only, never as visible text. // // `PRINCIPAL_KIND_LABEL` and `PRINCIPAL_KIND_ORDER` live here too, shared by -// every picker that lists principals (Grants' target select and filter, -// Roles' assignment select): Grants/Roles assign to people, agents, *and* -// workflows (see `people-section.tsx`'s own header comment), and a picker -// that shows only names with no kind is kind-blind — a workflow's machine -// principal can look identical to a person's account. Every such picker -// must show which kind an option is, not just its name. +// every picker that lists principals (Grants' target select and filter). +// Grants assign to people, agents, *and* workflows. Roles' assignment picker +// is scoped to user-kind principals only (CL-6664): agents/workflows are +// machine identities that belong on separate surfaces. import { SETTINGS_STRINGS } from "./strings"; diff --git a/packages/settings-ui/src/roles-section.tsx b/packages/settings-ui/src/roles-section.tsx index 42814bc5d..6df074a51 100644 --- a/packages/settings-ui/src/roles-section.tsx +++ b/packages/settings-ui/src/roles-section.tsx @@ -32,11 +32,7 @@ import { UnauthenticatedError, describeQueryError, } from "@corbits/api-query"; -import { - PRINCIPAL_KIND_LABEL, - PRINCIPAL_KIND_ORDER, - principalLabel, -} from "./identity"; +import { principalLabel } from "./identity"; import { SETTINGS_STRINGS } from "./strings"; import { assignRole, @@ -317,7 +313,13 @@ export function RoleAssignments({ const [principalId, setPrincipalId] = useState(""); const [roleId, setRoleId] = useState(""); - const assignments = principals.flatMap((principal) => + // CL-6664: Scope both picker and assignments to user-kind principals only. + // Agents and workflows are machine identities — the "Person" picker and + // its assignment table should match the People section's member roster, + // not the full tenant-wide principal list. + const people = principals.filter((p) => p.kind === "user"); + + const assignments = people.flatMap((principal) => principal.roles.map((role) => ({ principal, role })), ); @@ -333,21 +335,11 @@ export function RoleAssignments({ onChange={(event) => setPrincipalId(event.target.value)} > - {PRINCIPAL_KIND_ORDER.map((kind) => { - const kindPrincipals = principals.filter( - (principal) => principal.kind === kind, - ); - if (kindPrincipals.length === 0) return null; - return ( - - {kindPrincipals.map((principal) => ( - - ))} - - ); - })} + {people.map((principal) => ( + + ))}