Repository navigation
Commit f6faf75
fix(ui): land on home when an impersonation starts, and keep MCP agent sets out of the person permission-set picker (#30482)
<!-- claude-projects-attribution: {"github_login":"os-sales"} -->
_Requested by **Sales** · [project
thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4UuVbp5Gt3wFjzgF6n64t9ySi)_
domain:ui#6 · os-sales · session_01L6bhgUiuTxKJNYhUNmgKS6 (card thread
for seat session_01L6bhgUR8Nu4M7tbtgES7q2)
Refs #30212 — rows 1 and 4 only. Rows 2 and 3 stay on the card (see
Acceptance notes).
Clause-②: no
Metadata-protocol: none
## 维护者速读
-
改了什么:在系统设置里开始模拟用户后,直接进入被模拟用户的首页,不再停在「你没有访问此应用的权限」;给人员授权时的权限集下拉不再列出三个「MCP
AI 助手」权限集。
- 为什么改:真实用户走查(#30212 第 1、4 行)发现模拟后落到无权限页,且给人授权时能选到只属于 AI 助手的权限集。
- 风险与回滚:只改控制台前端两处,无接口、无元数据变化;回滚即还原本 PR。已存的「人员持有 MCP 集」授权仍照常显示。
- 先看:`ui/packages/app-shell/src/layout/ImpersonationBanner.tsx` 的
`useLandOnImpersonationStart`;`ui/packages/fields/src/widgets/RegistryRefField.tsx`
的 `nonGrantableNames`。
- 两分钟验证:以管理员打开 系统设置 → 用户 → 任一非管理员用户 →
点「模拟用户」并确认,应落到该用户的首页且顶部有模拟横幅;在该用户的「权限集」页签点「新建」,下拉中不应出现「MCP AI 助手」。
- 需要你做的:无,席位落地。
## What changes
- **Row 1, impersonation landing.** `ImpersonationBanner` gains
`useLandOnImpersonationStart`: when a session the console already held
as an ordinary one becomes impersonated, it navigates to `/`, where
`RootLandingRedirect` resolves the landing for the identity now held. A
boot into an impersonated session (reload, new tab, deep link) stays on
its URL, and stopping an impersonation does not move the page. The
navigate is the host's (`useHostNavigation`, supplied by
`ConsoleShell`'s `HostNavigationBridge`), so the deployment basename
applies and a tree with no host navigate does not move.
- **Row 4, agent sets in the person picker.** The `permission-ref`
widget (the `permission_set` field of the `sys_user_permission_set`
grant form opened from a person's Permission Sets tab) leaves the spec's
`MCP_AGENT_PERMISSION_SETS` out of its options, through the same
`nonGrantableNames` mechanism `position-ref` uses for the audience
anchors. A stored agent set still shows as the row's own option,
unflagged. `position-ref` is unchanged. The constant is imported
statically from `@objectstack/spec/ai` (no root export); the console's
OAuth consent page already imports that module's scope constants
statically.
- One root changeset, `@object-ui/app-shell` + `@object-ui/fields`
patch. No new language-pack key.
## Tests
- `ImpersonationBanner.test.tsx` — new top-level describe mounted under
`MemoryRouter` + `HostNavigationBridge`: an ordinary session becoming
impersonated navigates to `/`; a boot already impersonated stays on its
URL; ending the impersonation does not move the page.
- `RegistryRefField.audienceAnchors-12200.test.tsx` — new describe:
`permission-ref` offers no agent set; a stored agent set still shows by
its label beside its name and writes nothing; `position-ref` does not
apply the agent list. The old "permission-ref filters nothing" describe
is renamed to what it still pins (it does not apply the anchor list).
<details><summary>Positive control: the new pins are red on
main</summary>
Source files restored to the base (`git restore --source=c5800818`),
tests kept, markers counted 0, then restored with `git checkout HEAD --`
and `git diff HEAD` empty:
```
× offers the sets a person can hold and no agent set
× a stored agent set still shows by its label beside its name, unflagged, and writes nothing
× navigates to / when an ordinary session becomes impersonated
Tests 3 failed | 21 passed (24)
```
The boot-impersonated and stop cases pass on both sides by design (they
pin what must not move).
</details>
<details><summary>Suites on 8b921e1</summary>
`pnpm --dir ui exec vitest run` over ImpersonationBanner,
RemediationOverlay.impersonation-13208,
RegistryRefField.audienceAnchors-12200,
RegistryRefField.registryName-7611, RegistryRefCell.readFace: Test Files
5 passed, Tests 49 passed.
`turbo run type-check --filter=@object-ui/fields
--filter=@object-ui/app-shell`: 69/69 tasks successful (both packages'
`tsc --noEmit` and `tsconfig.test.json`).
eslint on the four changed files: 0 errors (2 pre-existing
`no-explicit-any` warnings in the anchor test's harness).
</details>
## Acceptance notes
- **Rows not shipped.** Row 2 (bulk-import set-password link lives 60
minutes) is a server credential-lifetime change owned by the server
lane, and the card asks the dev to confirm the lifetime with the
security seat. Row 3 (mail sender name defaults to `ObjectStack`) lives
in `packages/plugins/plugin-email`, server lane. Both were outside this
claim (`packages/**` fenced) and stay on #30212.
- Row 4 needed no server filter: the agent sets are named by the spec
constant `MCP_AGENT_PERMISSION_SETS`. The picker lives in
`ui/packages/fields`, not `views/metadata-admin`; the claim was amended
to that surface before this PR.
- `pnpm check:eager-closure` was not run locally (needs a full console
build); CI's bundle job weighs the static `@objectstack/spec/ai` import.
## Verification
Live, on a fresh `objectstack dev --seed-admin` showcase stack with the
console on Vite, zh-CN, 1440 wide, admin impersonating a fresh member.
Before = base source served, after = this branch. Screenshots sit on the
never-merged branch `claude/project-thread-cro7hi-evidence`.
| | Before (main) | After |
|:--|:--|:--|
| Row 1, after confirming 「模拟用户」 on the member's Setup record | [lands
on
你没有访问此应用的权限](https://github.com/objectstack-ai/objectstack/blob/65737b6c99c82685b06aa84c9102573b43923723/evidence/30212/before-row1-2-landed-zh-1440.png?raw=true)
| [lands on the member's home (showcase landing page), banner
up](https://github.com/objectstack-ai/objectstack/blob/65737b6c99c82685b06aa84c9102573b43923723/evidence/30212/after-row1-2-landed-zh-1440.png?raw=true)
|
| Row 4, 权限集 tab → 新建 → 权限集 picker | [lists the three MCP AI 助手
sets](https://github.com/objectstack-ai/objectstack/blob/65737b6c99c82685b06aa84c9102573b43923723/evidence/30212/before-row4-permission-picker-zh-1440.png?raw=true)
| [15 sets, no MCP AI
助手](https://github.com/objectstack-ai/objectstack/blob/65737b6c99c82685b06aa84c9102573b43923723/evidence/30212/after-row4-permission-picker-zh-1440.png?raw=true)
|
Confirm dialog (same on both sides):
[before-row1-1-confirm](https://github.com/objectstack-ai/objectstack/blob/65737b6c99c82685b06aa84c9102573b43923723/evidence/30212/before-row1-1-confirm-zh-1440.png?raw=true).
Ending the impersonation kept the URL on both sides.
<details><summary>Local gates on 8b921e1</summary>
`node scripts/pm/dispatch-gates.mjs --commands`: 35 derived; all 35 run,
each exit 0 (`pnpm --dir ui exec vitest run scripts/` was killed once by
the container's memory limit and re-run alone under the lock: 170 files
/ 4985 tests passed). `--ran` reconciliation: 35 derived, 35 run, 0
NOT-MEASURED, 0 UNRUN.
ui checks: `check:new-line-citations` 0 new, `check:test-path-roots` OK.
`check:spec-symbols` NOT MEASURED locally: it exits 1 on 22 stale-ALLOW
entries in packages this diff does not touch (cause in this container
not established); this diff declares no new type or interface. CI's Type
Check UI judges it.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01L6bhgUiuTxKJNYhUNmgKS6)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent f4cd4ec commit f6faf75
5 files changed
Lines changed: 220 additions & 14 deletions
File tree
- .changeset
- ui/packages
- app-shell/src/layout
- __tests__
- fields/src/widgets
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
53 | 68 | | |
54 | 69 | | |
55 | | - | |
| 70 | + | |
56 | 71 | | |
57 | 72 | | |
58 | | - | |
| 73 | + | |
| 74 | + | |
59 | 75 | | |
60 | 76 | | |
61 | 77 | | |
| |||
108 | 124 | | |
109 | 125 | | |
110 | 126 | | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
111 | 151 | | |
112 | 152 | | |
113 | 153 | | |
| |||
116 | 156 | | |
117 | 157 | | |
118 | 158 | | |
| 159 | + | |
119 | 160 | | |
120 | 161 | | |
121 | 162 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
39 | 40 | | |
| 41 | + | |
40 | 42 | | |
41 | 43 | | |
42 | 44 | | |
| |||
306 | 308 | | |
307 | 309 | | |
308 | 310 | | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
56 | 57 | | |
57 | 58 | | |
58 | 59 | | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
63 | 67 | | |
64 | 68 | | |
65 | 69 | | |
| |||
83 | 87 | | |
84 | 88 | | |
85 | 89 | | |
| 90 | + | |
86 | 91 | | |
87 | 92 | | |
88 | 93 | | |
89 | 94 | | |
90 | 95 | | |
91 | 96 | | |
92 | | - | |
93 | | - | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
94 | 102 | | |
95 | | - | |
96 | | - | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
97 | 106 | | |
98 | 107 | | |
99 | 108 | | |
100 | 109 | | |
101 | 110 | | |
102 | 111 | | |
103 | 112 | | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
104 | 119 | | |
105 | 120 | | |
106 | | - | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
107 | 124 | | |
108 | 125 | | |
109 | 126 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
21 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
22 | 25 | | |
23 | 26 | | |
24 | 27 | | |
25 | 28 | | |
26 | 29 | | |
27 | 30 | | |
| 31 | + | |
28 | 32 | | |
29 | 33 | | |
30 | 34 | | |
| |||
118 | 122 | | |
119 | 123 | | |
120 | 124 | | |
121 | | - | |
| 125 | + | |
122 | 126 | | |
123 | 127 | | |
124 | 128 | | |
| |||
132 | 136 | | |
133 | 137 | | |
134 | 138 | | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
0 commit comments