Repository navigation
fix(app-shell): the Delegated Admin Scope block lists a delegate's companion grants and grants the missing ones (#26191) - #26340
Conversation
Claude-Session: https://claude.ai/code/session_01SMps7wq7rBTk53e8KTSEup Co-authored-by: Claude <noreply@anthropic.com>
…ings for the scope block's hint Claude-Session: https://claude.ai/code/session_01SMps7wq7rBTk53e8KTSEup Co-authored-by: Claude <noreply@anthropic.com>
…legate-companion-grants
…mpanion grants and grants the missing ones Claude-Session: https://claude.ai/code/session_01SMps7wq7rBTk53e8KTSEup Co-authored-by: Claude <noreply@anthropic.com>
…legate-companion-grants
维护者速读改了什么:设置里编辑权限集的「委派管理范围」块,选定业务单元后会列出委派管理员还需要的 5 项配套权限(进入 Setup、读用户/业务单元/成员、增删改查岗位分配),逐项标出已有/缺失,并给一个「补齐缺失项」按钮。 席位核对seat 2 · 2026-10-26T22:27Z · head
|
Fixes #26191
Clause-②: no
Metadata-protocol: none
Part of the #26059 ruling (6416233738, Q3 child 5, item 2). UI and docs only: no server change, no spec key.
What changes
The Delegated Admin Scope block lists the companion grants a delegate needs. A scope says what its holder may administer; it does not let the holder in. Once the scope names a business unit (the block's existing gate for its dependent controls), the block lists:
setup.access: enter Setupsys_user,sys_business_unit,sys_business_unit_member: read, so the lookups can pick people and unitssys_user_position: create, read, edit and delete, for the assignment rowsEach row is marked "On this set" or "Not on this set", read from the draft being edited (
systemPermissionsandobjects). A row counts as granted only when every flag it needs istrue; nothing is inferred."Grant the missing ones" adds only what is missing, as one draft edit. It is one
setDraftcall, and the set's normal Save persists it.setup.accessis appended tosystemPermissions. Each companion object row gains only the flags it lacks. An existing row keeps every key it already has (an extra Edit, a View All), and a row that already covers its grant is left as the same object. Nothing is removed or narrowed, and no new key is written: both keys already exist onPermissionSetSchema. The button shows only when the set is writable and something is missing.Under a package binding, the hint is shown without the action. The package door's draft holds, and its Save writes, only the package's own objects (
scopePermissionSet/mergePermissionSlice, ADR-0086 P0). There, thesys_*rows would not survive Save, and their absence from the draft says nothing about the stored set. So under a package the block lists the five grants without a granted/missing mark and without the button, plus a note: grant these in Setup, on an environment permission set the delegate holds.How the facet knows it is package-bound.
PermissionAdvancedFacetsgains an optionalpackageBoundprop. When the prop is omitted, it is read fromonly. The Studio Access pillar is the one host that setsonly, and it always edits under apackageId(AccessPillar'spackageIdis required). Setup's permission page sets neither.PermissionMatrixEditor.tsxis outside this card's claimed file surface, so this PR does not wirepackageBound={!!packageId}there. See Acceptance notes.Docs.
content/docs/permissions/delegated-administration.mdx: the authoring example now carriessystemPermissions: ['setup.access']. A new paragraph names the five companion grants and why each is needed, and says the Setup editor lists them and grants the missing ones.Strings. Nine new
perm.admin.companions.*keys inmetadata-admin/i18n.ts, in both locales the block's existing strings use (en, zh).Tests
PermissionAdvancedFacets.companionGrants-26191.test.tsxdrives the facet with the draft held as the host holds it. It has 10 cases:PermissionSetSchemaand carries no new keypackageBound: the hint shows unmarked, there is no action, and the note showsonly) is package-bound by defaultpackageBound={false}keeps the actionRed first, at
c3066c2b(the test committed, the component not yet changed): 9 failed, 1 passed. The one that passed is the "hidden until a business unit is named" case, which holds both before and after the change. The failures wereUnable to find [data-testid="admin-companions"]and the like, not errors.Green, all at head
8ecd7344(this branch withmainmerged after #26284 landed), from cwdui/underscripts/pm/os-verify-lock.sh:pnpm exec vitest run FILES --maxWorkers=2over 254 files: every app-shell test file that importsPermissionAdvancedFacetsorviews/metadata-admin/i18n, the new file included.Test Files 254 passed (254),Tests 2578 passed (2578). The lock's verdict wascommand-exit 0. The full app-shell suite was not run locally; CI runs it.eslinton the three changed source files: 0 errors and 5 warnings. Two warnings are new, bothno-explicit-anyin the test harness, where the updater'sprevis typedany, as the prop itself types it. The other three are on existing lines.pnpm --filter @object-ui/app-shell type-check: NOT MEASURED locally. It ran without the@object-ui/*dependency closure built, so it answered only unresolved-module cascades (TS2307 / TS7006). None of them is on a line this PR adds. CI'sType Check UIis the reading.node scripts/pm/dispatch-gates.mjs --commands: 68 derived commands, reconciled with--ranas 66 run (all exit 0) and 2 NOT MEASURED. Both of those are exit-3 prerequisite refusals:check:skill-examples(packages/client-reactwas not built; this page's example block carries no type-check marker) andcheck:type-check-debt(it needs the shared lock for its closure build and timed out in the queue). CI'sLint & Repo Gatesruns both.node scripts/check-sdui-manifest.mjs: exit 0. app-shell has no sdui record, so there was nothing to re-record.Acceptance notes
only, not frompackageId, becausePermissionMatrixEditor.tsxis outside this card's file surface (fix(app-shell): permission matrix sets and shows readScope / writeScope (#26187) #26284 held it). Once that file is open to a card, passingpackageBound={!!packageId}at both facet mounts makes the binding explicit, and theonlyfallback can go. Until then the two coincide by construction:packageIdis passed only byAccessPillar, always together withstudiochrome, and that chrome is what setsonly.setup.access. Clicking then adds the exact capability, which is an addition and narrows nothing.PermissionMatrixEditor.tsx,permission-slice.ts, the server,packages/specandui/packages/i18nare untouched. app-shell has no sdui record (node scripts/check-sdui-manifest.mjsexits 0).content/docs/**) is not a governed surface:node scripts/pm/check-governed-merges.mjs --testover the five files exits 0.Generated by Claude Code