Repository navigation
feat(plugin-security): Setup People & Organization entries for position holders and permission-set assignment - #28332
Conversation
…on holders and permission-set assignment Two type: 'component' entries under group_people_org, contributed by plugin-security beside its catalog entries and gated the same way (no item gate; Setup's setup.access and the ungated group anchor decide). Labels in the four platform-objects Setup bundles, with recorded source digests. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4czVnUdQQCVKSW5J2uk
…es and their labels Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4czVnUdQQCVKSW5J2uk
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4czVnUdQQCVKSW5J2uk
📓 Docs Drift CheckThis PR changes 2 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 18 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 28b3ad8816eb318c8e8bad6c18e4ad541e02f755 && git checkout 28b3ad8816eb318c8e8bad6c18e4ad541e02f755
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 501c864dd5918a7bab1f3a59e1246b8a0ddff48c d1bf48213a5bb8a2f9a2f08977ec9ba64ee6ec6c && git checkout -B drift-repro 501c864dd5918a7bab1f3a59e1246b8a0ddff48c && git merge --no-ff d1bf48213a5bb8a2f9a2f08977ec9ba64ee6ec6c
node scripts/docs-audit/affected-docs.mjs --json 501c864dd5918a7bab1f3a59e1246b8a0ddff48c
|
|
domain:server#1 · os-elon-musk · session_016WV4czVnUdQQCVKSW5J2uk Seat ACCEPT · PR #28332 · head
|
Fixes #28316
Clause-②: no
Metadata-protocol: none
Skills-docs: none changed.
skills/**has zero hits for People & Organization Setup navigation text.content/docs/permissions/administrator-guide.mdx(lines 51, 75, 209-211) andcontent/docs/ui/apps.mdx(line 813, thegroup_people_orgrow) list the group's entries and do not yet name the two new pages; they are outside this claim's file surface and are worth a docs pass once the pages ship.Lands after PR #28310 (the two app-shell pages). Before it merges, the entries are harmless: a component ref with no registration opens the console's not-found page.
维护者速读
pnpm --filter @objectstack/plugin-security exec vitest run src/people-org-assignment-nav-contribution.test.ts,预期 5 个测试全部通过。What changes
@objectstack/plugin-securitycontributes a second Setup navigation block,group: 'group_people_org', priority 200 (after platform-objects' base entries at 100), with two items:nav_position_holders·type: 'component'· label "Position Holders" ·componentRef: 'security:position-holders'· iconuser-checknav_permission_set_assignment·type: 'component'· label "Permission Set Assignment" ·componentRef: 'security:permission-set-assignment'· iconkey-roundrequiredPermissions,requiresService,requiresObjectorvisible): the Setup app'srequiredPermissions: ['setup.access']and the ungated group anchor decide who sees them (ADR-0146 D7 names the pages as the scope ofsetup.accessand the delegated-administrator gate). The writes the pages make keep their own server-side gates. Riding plugin-security's manifest, the entries disappear wherever the plugin is not composed, exactly like the catalog entries.appssection; every Setup nav label, plugin-security's catalog entries included, lives in@objectstack/platform-objects' hand-authored Setup bundles (apps.setup.navigation.ID.label). Both ids are added to all four locales that carry the group (en,zh-CN,ja-JP,es-ES), and each translated leaf's source digest is recorded inLOCALE.source-hashes.tsviacollectSourceHashes(en)(control: the computed digest fornav_positionsequals its recorded517a2743f949b5f0). No*.generated.tsfile is involved;pnpm check:i18nconfirms all generated bundles stay in sync.@objectstack/plugin-securitypatch,@objectstack/platform-objectspatch.Before (measured on
origin/mainb339465):git grep "group: 'group_people_org'"outside tests and translations names one contributor,packages/platform-objects/src/apps/setup-nav.contributions.ts, whose block has 0componentRefitems;git grepfor either ref outsideui/returns 0 files (control:componentRef: 'automation:packaged'returns 1 source hit).Tests
New
packages/plugins/plugin-security/src/people-org-assignment-nav-contribution.test.ts(5 cases), modelled on plugin-audit'saudit-nav-contribution.test.ts: it runs the plugin's realinit()and folds the Setup app through the realSchemaRegistry.group_people_orgcontribution, with the exactcomponentRefs, as registry keys, and every contribution parses withNavigationContributionSchema.nav_positionsandnav_permission_sets: the four gate keys compare equal (control: both catalog entries exist).nav_users, the group anchor's gate equals Access Control's, and each ref opens in exactly one place.nav_positions/nav_permission_setsare also absent (control:nav_usersstill served).SetupAppTranslationsthat carriesgroup_people_org(measured: the four) labels both,enequals the declared label, and no translated locale serves the English string.No existing test enumerates plugin-security's Setup entries;
setup-nav-dead-key-tombstone.test.tsandapp-nav-translation-parity.test.tsdeliberately do not list Setup's contributed leaves (that ispnpm check:app-nav-i18n, which boots plugin-security and now judges 60 merged Setup ids, OK in 4 locales), so neither was extended.Ablations (each reverted, red shown, restored;
scripts/ablation-replace.mjs, restore proven by blob equal to HEAD and an emptygit diff HEAD)security:position-holderstosecurity:positionsrequiredPermissions: ['manage_platform_settings']tonav_permission_set_assignmentgroup_access_controlnav_position_holderslabel (platform-objects rebuilt)zh-CN nav_position_holders: expected undefined to be truthy)nav_position_holders(rebuilt; dist preflight: marker present in 4 built files)nav_permission_set_assignmentlabel set to the English string (rebuilt)After the platform-objects legs, the package was rebuilt from HEAD;
dist/carries the restored labels and the file reruns 5/5 green.Acceptance notes
scripts/ablation-dist-preflight.mjs --absentread the A5 / A7 markers as absent vacuously: esbuild escapes non-ASCII, sodist/never carries the raw spelling. The red runs themselves prove those mutations reacheddist/(an undefined label; the English string served), and the restored escaped spellings were read back fromdist/apps/index.mjsdirectly.Verification
Head
d1bf4821, tree clean:pnpm --filter @objectstack/plugin-securityvitest: Test Files 238 passed (238), Tests 5124 passed, 45 skipped. Exit 0.@objectstack/platform-objectsvitest: Test Files 104 passed (104), Tests 1474 passed. Exit 0.pnpm --filter @objectstack/plugin-security typecheckexit 0;pnpm --filter @objectstack/platform-objects typecheckexit 0.pnpm lintexit 0.pnpm build(full, under the verify lock) exit 0.node scripts/pm/dispatch-gates.mjs --commands: 62 families, each run with its exit code recorded before any pipe. Three first exited 3 (PREREQUISITE NOT MET: no built tree, or the lock queue) and were rerun after the full build:check:i18nexit 0 (10 packages, all bundles in sync),check:dual-build-cjs-loadsexit 0,check:type-check-debtexit 0.--ran: "62 derived famil(ies) accounted for — 62 run, 0 NOT-MEASURED (a DERIVED zero — all 62 recorded an exit code and none of them is 3)".pnpm check:app-nav-i18nexit 0, "13 contributor(s), 4 locale(s), 2 app(s) — setup: 60 merged nav id(s) … every id labelled in every locale".🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4czVnUdQQCVKSW5J2uk