You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Setup › Permission set › Add user: the user picker lists names only, so two people of one name cannot be told apart #27433
Follow-up from #27410 (PR #27427, seat ACCEPT 6489766088). The os-dev reported it in that PR's acceptance notes.
What happens
On a Setup permission-set page, Assigned users › Add opens RecordPickerDialog on sys_user with no columns (ui/packages/app-shell/src/views/metadata-admin/AssignedUsersSection.tsx, the picker near L612). The picker draws only its default display column, the name. An administrator cannot tell two people of the same name apart, or confirm the account before granting the set. Yet the assigned-user rows on the same section already show each person's email under the name (≈L579).
This is the same gap #27410 closed for Setup › Position › Add holder.
Pass columns for name and email, with en/zh headers from the section's own copy, and objectSchema set to sys_user from the useMetadata() objects the section already holds. Add no new fetch.
Add no permission check of its own: the picker's readableColumns rule decides what is drawn.
Acceptance
The picker draws a Name column and an Email column.
CONTROL: choosing people still writes the sys_user_permission_set grant by name ({ user_id, permission_set }). It still offers the active organization's members only, and the AI-seat cap refusal still shows inline.
CONTROL: under a real PermissionProvider that denies sys_user.email, only the name column is drawn and no email text appears.
Test against the real RecordPickerDialog, with a columns ablation that goes red.
Claim: PM loop round 1
Session: session_01Utp6CbDAucNyQ4UtzCJKyh
Account: os-bill
Branch: claude/project-thread-8i0z2y (the card thread's designated push branch, the recorded platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-27433
Domain: domain:ui
Seat: domain:ui#4
File surface: ui/packages/app-shell/src/views/metadata-admin/AssignedUsersSection.tsx, one new test beside it, root .changeset/; @object-ui/i18n packs only if a new header key is needed (then Clause-②: yes (widening)) (stop on breach; explain in the report)
Container & model: S, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier on 968cacfd: no path-derived mandate), effort: medium
Clause-②: no
Metadata-protocol: none
Responsibility: the Add user picker on a Setup permission set draws a Name and an Email column (reusing the #27427 shape), with the card's CONTROL lines pinned against the real RecordPickerDialog
Thread-read: none
Premise: holds
Serial constraints cleared: none — no open PR touches AssignedUsersSection.tsx
Dispatched 2026-10-29T23:19Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.
Activity
objectstack-fleet commentedon Oct 29, 2026
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh
Claim: PM loop round 1
Session:
session_01Utp6CbDAucNyQ4UtzCJKyhAccount:
os-billBranch:
claude/project-thread-8i0z2y(the card thread's designated push branch, the recorded platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-27433Domain:
domain:uiSeat:
domain:ui#4File surface:
ui/packages/app-shell/src/views/metadata-admin/AssignedUsersSection.tsx, one new test beside it, root.changeset/;@object-ui/i18npacks only if a new header key is needed (thenClause-②: yes (widening)) (stop on breach; explain in the report)Container & model:
S,mode:thread,model: TIER_DEFAULT(dispatch-gates --tieron968cacfd: no path-derived mandate),effort: mediumClause-②: no
Metadata-protocol: none
Responsibility: the Add user picker on a Setup permission set draws a Name and an Email column (reusing the #27427 shape), with the card's CONTROL lines pinned against the real
RecordPickerDialogThread-read: none
Premise: holds
Serial constraints cleared: none — no open PR touches
AssignedUsersSection.tsxDispatched 2026-10-29T23:19Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.
Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:ui#4 · os-bill · session_01Utp6CazvDXxebLfghuZZ7t
os-dev-report
{ "issue": 27433, "status": "done", "branch": "claude/project-thread-8i0z2y", "pr": "https://github.com/objectstack-ai/objectstack/pull/27808", "session": "session_01Utp6CazvDXxebLfghuZZ7t", "premise_still_valid": true, "summary": "Setup permission set > Assigned users > Add user now opens RecordPickerDialog with columns name + email (headers from the section's own en/zh copy, no new i18n key) and objectSchema = sys_user from the useMetadata() objects the section already holds; no new fetch and no permission check of its own. Same shape as PR #27427. Premise measured on 968cacfd: the picker had no columns and the assigned rows already drew email.", "tests": "head 3b0005b0: new file AssignedUsersSection.pickerColumns-27433.test.tsx against the real RecordPickerDialog + real PermissionProvider: Test Files 1 passed, Tests 5 passed (lock VERDICT command-exit 0). All 44 test files naming AssignedUsersSection (the new file included), re-run on 3b0005b0: Test Files 44 passed, Tests 332 passed (VERDICT command-exit 0). pnpm --filter @object-ui/app-shell run type-check: VERDICT command-exit 0 (first run exit 2 on TS2322 SchemaLike vs a Record of string to unknown; fixed in 3b0005b0 by the precedent's cast). Ablation via scripts/ablation-replace.mjs on c0a3253b (before 3b0005b0, a type-only cast change): delete the columns prop, anchor 1 -> 0, blob 6e003bf1 -> 495a0d0e, the column test red (1 failed / 4 passed, CONTROLs green), restored blob == HEAD, git diff HEAD empty. app-shell tests import src, so no dist rebuild leg.", "gates": "local derived set on 3b0005b0, exit codes recorded before any pipe: node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 ; node scripts/check-adr-0087-registration.mjs --self-test :: exit 0 ; node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 ; node scripts/check-closing-keyword-parity.mjs :: exit 0 ; node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 ; node scripts/check-comment-mask-corpus.mjs :: exit 0 ; node scripts/check-empty-changeset.mjs --base origin/main :: exit 0 ; node scripts/check-empty-changeset.mjs --self-test :: exit 0 ; node scripts/check-sdui-manifest.mjs :: exit 0 ; node scripts/check-sdui-manifest.mjs --self-test :: exit 0 ; node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0 ; node scripts/release-pending-publish.mjs --self-test :: exit 0 ; pnpm --dir ui exec vitest run scripts/ :: exit 0 ; pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0 ; pnpm check:changeset-gate-self-tests :: exit 0 ; pnpm check:closed-ceremony-text :: exit 0 ; pnpm check:cross-package-test-inputs :: exit 0 ; pnpm check:dispatcher-error-vocabulary :: exit 0 ; pnpm check:driver-memory-census :: exit 0 ; pnpm check:engine-double-contract :: exit 0 ; pnpm check:gitlink-declared :: exit 0 ; pnpm check:nul-bytes :: exit 0 ; pnpm check:pm-changeset-deadline-census :: exit 0 ; pnpm check:published-files :: exit 0 ; pnpm check:query-options-erasure :: exit 0 ; pnpm check:refd-timer-probe :: exit 0 ; pnpm check:skill-identifier-liveness :: exit 0 ; pnpm check:test-source-alias :: exit 0 ; pnpm check:tier-file-adoption :: exit 0 ; pnpm check:type-check-coverage :: exit 0 ; pnpm check:type-check-debt :: exit 0 ; pnpm check:undeclared-dep-imports :: exit 0 ; pnpm check:watch-hint-literal :: exit 0 ; pnpm check:where-matcher :: exit 0. dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. CI families: the PR's check-runs, in_progress at report time.", "line_budget": "206 changed lines (+206/-0 at 3b0005b0 vs merge base 968cacfd; 3 files), under the 3000 human-merge threshold", "files_changed": [ "ui/packages/app-shell/src/views/metadata-admin/AssignedUsersSection.tsx", "ui/packages/app-shell/src/views/metadata-admin/AssignedUsersSection.pickerColumns-27433.test.tsx", ".changeset/27433-permission-set-user-picker-email.md" ], "deviations": [ "origin/main moved 13 commits past the base before the PR; none touches the three changed files or RecordPickerDialog, so the branch was not merged with it (AGENTS.md multi-agent §10 pre-PR pull skipped on zero overlap)", "the session-context's after-PR assign + review request step was skipped per the dispatch order (no assignees, no review request)", "the harness PR-subscription posture is not taken; CI convergence is the seat's per os-dev.md" ], "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "1 — mcp__claude-code-remote__get_session (read of this session's id); 0 GitHub MCP calls", "api_writes": "2 — relay pr_create (POST pulls, PR #27808); post-stamped issue comment on #27433 (this report). Plus git push (not REST).", "open_questions": [], "out_of_scope_findings": [] }Report taken 2026-10-30T00:04Z.
objectstack-fleet commentedon Oct 30, 2026
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh
ACCEPT → PR #27808 comment 6511624958 · 2026-10-30T00:13Z
Generated by Claude Code