Repository navigation
Commit c88467d
feat(console): ask for the installer's OAuth client on Connect for a clientSource installer connector (#29496)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} -->
_Requested by **Steedos** · [project
thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbSYY7fbDBFK5hXog1WZFvie)_
Part of #28869
Clause-②: yes
Metadata-protocol: none
PR 1 of 2 on the card, per the seat's claim amendment (6581522588,
option B): items 1, 3, 4 and 5. Item 2, the redirect URI with a copy
button, is PR 2 on this card once the server half #29463 lands, because
no answer the Console reads carries the redirect URI today (stop report
6581473243).
## 维护者速读
- 改了什么:声明 `clientSource: 'installer'` 的 OAuth 连接器,在 设置 → 集成 → 连接器连接
页点「连接」或「重新连接」时,先弹出表单让管理员填写在供应商处登记的 Client ID 和 Client
secret,再打开供应商登录窗口;连接请求体带 `{ clientId, clientSecret }`。secret
输入框为密码框,每次打开都是空的,提交即清空,页面上永不显示。已连接的行显示「OAuth client 某 ID, secret
stored」。其他连接器照旧,无表单。
- 为什么改:#28702 裁决 B 的界面半边;服务端 #29097 已合并,此前控制台连接这类实例会得到 400。
- 风险与回滚:只改控制台一页和语言包。重新连接时按当前服务端行为必须再次发送客户端(预填 Client ID,有 secret
需重新输入);#29463 落地后 PR 2 改为「不替换则沿用」。回滚即撤掉本 PR。
-
先看:`ui/packages/app-shell/src/views/setup/ConnectorConnectionsPage.tsx`
的 `startConnect` / `submitClient`(提交前清空 secret
那一行);`connectorConnections.ts` 的 `beginConnection`
请求体;`readConnectableInstances` 的 `clientSource` 判定。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/app-shell/src/views/setup/ConnectorConnectionsPage.test.tsx`,应看到
17 条全过(新增 6 条在 an installer-supplied OAuth client 组)。
- 需要你做的:无,席位落地。
新增语言键(`connectorConnections` 下 12
个,十种语言全部补齐):`clientKeptWithSecret`、`clientKept`、`clientTitle`、`clientIntro`、`clientStored`、`clientStoredSecret`、`clientStoredNoSecret`、`clientResend`、`clientId`、`clientSecret`、`clientSecretHint`、`clientContinue`。
## What changes
- `connectorConnections.ts`: `readConnectableInstances` marks an
instance whose declaration (`GET /meta/connector`) says
`auth.clientSource: 'installer'`. `beginConnection(name, client?)` sends
`{ clientId, clientSecret? }` as a JSON body for such an instance and no
body otherwise, exactly as before.
- `ConnectorConnectionsPage.tsx`: Connect / Reconnect on an
installer-client instance opens a form (client ID; masked client secret
with `autocomplete=new-password`) before any window opens or anything is
sent. Continue opens the sign-in window on that click and begins with
the client. The secret is cleared from the form state before the begin
is awaited; a refused begin keeps the form open with the server's words
and an empty secret. A connected row shows the kept client from `client
{ clientId, hasSecret }` on the status. Reconnect shows the stored
client ID and whether a secret is kept, prefills the ID, leaves the
secret empty and sends the client again: today's server refuses a
client-less begin of such an instance on every begin, reconnect included
(`installerClientOfBegin`). The client-less reconnect that reuses the
stored client is ask 2 of #29463; PR 2 switches to it. Every other
instance (a declared client, an MCP dynamically registered client)
connects at once with no form and no body.
- No redirect URI is shown, guessed or parsed from prose. The form says
the Connectors documentation describes the redirect URI to register.
- `@object-ui/i18n`: the twelve keys above in all ten locales (the
all-locales parity suite requires every pack, so the card's four became
ten).
- Changeset `.changeset/28869-installer-oauth-client-form.md`
(`@object-ui/app-shell`, `@object-ui/i18n`: patch).
## Tests
New `describe('an installer-supplied OAuth client')` in
`ConnectorConnectionsPage.test.tsx`, six cases: the form appears before
any window or POST and the begin carries `{ clientId, clientSecret }`
(id trimmed); a public client sends only `{ clientId }`; a refused begin
keeps the form with the server's words and an empty secret; a reconnect
shows the stored client, prefills the id, starts with an empty secret
and sends the client again (today's server behaviour, pinned); Cancel
sends nothing and the next opening has an empty secret; no other
instance shows the form and its begin has no body. Every case that types
the secret asserts it is absent from `document.body.innerHTML`
afterwards.
## Acceptance notes
- Deviation from the card text, by the seat's ruling: reconnect sends
the client again (re-enter the secret) instead of keeping the stored
one, because the server requires a client on every begin today. Ask 2 of
#29463 adds the reuse; PR 2 follows it.
- Locale keys went to all ten packs, not four: `all-locales-key-parity`
holds every pack to the same key set.
- Live run used a fake vendor (a local authorize/token stub) on
`app-crm`; the token leg authenticated with HTTP Basic as the
installer's client, as the server half intends.
## Verification
<details><summary>Page suite, ablations (head bc8ea24, re-run on merge
4a4fe17)</summary>
- `pnpm exec vitest run
packages/app-shell/src/views/setup/ConnectorConnectionsPage.test.tsx`
(from `ui/`, under os-verify-lock): 17 passed (11 existing + 6 new). On
merge head 4a4fe17 with `packages/i18n/`: Test Files 96 passed, Tests
1460 passed, 13 skipped.
- Ablation A1 (via `scripts/ablation-replace.mjs`, restored blob ==
HEAD, `git diff HEAD` empty): the installer gate in `startConnect`
dropped, so every instance gets the form: 6 failed / 11 passed, the "no
other instance shows the form" pin among them.
- Ablation A2: `readConnectableInstances` never marks `clientSource:
'installer'`: 5 failed / 12 passed (every installer case).
- Ablation A3: the secret not cleared when the begin is sent: 1 failed /
16 passed ("a refused begin keeps the form open ..., and the secret is
gone from it").
- ui vitest aliases `@object-ui/*` to source, so no rebuild leg was
owed.
</details>
<details><summary>Packages and gates (head bc8ea24)</summary>
- `pnpm exec vitest run packages/i18n/` (under the lock): Test Files 95
passed, Tests 1443 passed, 13 skipped.
- `turbo run type-check --filter=@object-ui/app-shell
--filter=@object-ui/i18n`: 66 tasks successful, VERDICT command-exit 0.
- `pnpm --dir ui exec vitest run scripts/`: Test Files 169 passed, 2
skipped; Tests 4921 passed.
- `node scripts/check-sdui-manifest.mjs`: exit 0 (no registry change).
- `dispatch-gates --commands`: 34 families, every one exit 0; `--ran`:
34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN.
</details>
<details><summary>Live run (app-crm, Vite source Console)</summary>
`objectstack dev --seed-admin --fresh` on app-crm with `OS_BASE_URL` set
to the Console origin, the Vite Console proxying to it, a local stub for
the vendor's authorize/token endpoints, and an installer connector saved
through `PUT /meta/connector/vendor_docs` (`clientSource: 'installer'`,
the dogfood fixture's shape). In Playwright: Connect opened the client
form; Continue sent `POST .../vendor_docs/connection` with body keys
`clientId`, `clientSecret`; the stub saw the authorize request with that
client id and the token request authenticated as that client; the page
showed Connected and "OAuth client live-installer-client, secret
stored"; the status read answered `client: { source: 'installer',
clientId: 'live-installer-client', hasSecret: true }`. Reconnect opened
the form with the id prefilled and the secret empty. The typed secret
was absent from the page's HTML after the connect and in the reconnect
form. Screenshots of the Connect step, the connected row and the
Reconnect step were handed to the seat.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QsR2jQhfprmgNtfhzNURJ6)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent ec2f5d5 commit c88467d
14 files changed
Lines changed: 503 additions & 16 deletions
File tree
- .changeset
- ui/packages
- app-shell/src/views/setup
- i18n/src/locales
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
20 | 28 | | |
21 | 29 | | |
22 | 30 | | |
| |||
250 | 258 | | |
251 | 259 | | |
252 | 260 | | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 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 | + | |
0 commit comments