Repository navigation
feat(console): Connector connections page — connection status and Connect / Reconnect / Disconnect for OAuth connector instances - #28651
Conversation
… Reconnect / Disconnect over the connection door Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…s rules Co-Authored-By: Claude <noreply@anthropic.com>
…gated on manage_connector_connections (red) Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 7 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 11 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 20fa0b10d5463f6d5282d4fb5dfd1a9eaca18d64 && git checkout 20fa0b10d5463f6d5282d4fb5dfd1a9eaca18d64
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 5114b0e1d56f8a21edcbf8623a92f8c3dbda8de6 0537d24f8a110e6e66c056dcdb2530c442ce1107 && git checkout -B drift-repro 5114b0e1d56f8a21edcbf8623a92f8c3dbda8de6 && git merge --no-ff 0537d24f8a110e6e66c056dcdb2530c442ce1107
node scripts/docs-audit/affected-docs.mjs --json 5114b0e1d56f8a21edcbf8623a92f8c3dbda8de6
|
… on manage_connector_connections Co-Authored-By: Claude <noreply@anthropic.com>
…ns in the service-automation tier Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH 席位核对 · ACCEPT · PR #28651 · 2026-11-01T13:05ZHead-sha: 维护者速读(席位终稿)
核对六项
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Requested by Leehom · project thread
Fixes #26702 (item 7, the Console half and its Setup navigation entry; item 7 was the card's last open item). What stays open: nothing.
Clause-②: yes (widening: new Setup entry nav_connector_connections resolving automation:connector-connections; no existing key, route or shape changes)
Metadata-protocol: none
维护者速读
automation:connector-connections):列出每个oauth2+authorization_code连接器实例在本组织的连接状态(未连接 / 已连接 / 需要重新连接,附服务端记录的原因),降级实例的原因与它的连接同行显示;提供连接、重新连接、断开连接三个操作。「连接器凭据」页加了一条指向它的链接。ui/packages/app-shell/src/views/setup/ConnectorConnectionsPage.tsx(连接按钮:同步打开登录窗口、清空opener、再导航到服务端返回的授权地址);ui/packages/app-shell/src/views/setup/connectorConnections.ts(只接受 http(s) 授权地址)。cd ui && pnpm exec vitest run packages/app-shell/src/views/setup/ConnectorConnectionsPage.test.tsx,预期 11/11 通过。What changes
ui/packages/app-shell/src/views/setup/connectorConnections.ts(new): the Console's client for the connection door. It finds the instances an administrator connects from their declaration (GET /api/v1/meta/connector, entries with aproviderandauth.type: 'oauth2'+grant: 'authorization_code'), joins each instance's registry state fromGET /api/v1/automation/connectors, and readsGET …/connectors/:name/connectionfor each.beginConnectionposts with no body;revokeConnectiondeletes. Every answer is read into aConnectorConnectionStateor the server's own refusal sentence (actionErrorDetail), rendered, never parsed. The begin leg'sauthorizationUrlis accepted only when it parses ashttps:orhttp:.ui/packages/app-shell/src/views/setup/ConnectorConnectionsPage.tsx(new): the page. One row per instance: label and name; aDegradedbadge with the descriptor'sdegradedReasonwhen the instance is degraded, in the same row as its connection; the connection's status badge andstatusReason; who connected it and when, the scopes, when the access token renews; and the actions (Connect fornot_connected, Reconnect and Disconnect otherwise).window.open('about:blank', …), since a window opened after an await is blocked), itsopeneris cleared before it leaves this origin, and only then is the POST sent; the window is then sent to the answered URL. The page re-reads the status every 2 s until the connection isconnectedwith a newconnectedAt(then it closes the window and shows the new status), the window is closed (it shows the status read then), or the begun connect'sexpiresAtpasses. A blocked window sends nothing; a refused begin closes the window and shows the server's sentence.ui/packages/app-shell/src/services/builtinComponents.tsx: registers the page underautomation:connector-connections.ui/packages/app-shell/src/views/setup/ConnectorCredentialsPage.tsx: one line under the list linking to the new page.ui/packages/i18n/src/locales/*.ts(all ten packs): aconnectorConnectionsnamespace (32 keys) and twoconnectorCredentialskeys for the link.content/docs/automation/connectors.mdx: one paragraph under theauthorization_codeconnect calls, describing the Console page..changeset/26702-console-connector-connections.md:@object-ui/app-shelland@object-ui/i18n, patch.⛔ No
packages/specedit and no server change: the page reads and drives only what the server already serves.Server surface inventory (read on
origin/maina798ae8f)GET /automation/connectors/:name/connectionpackages/runtime/src/domains/automation.ts(respondToConnectorConnectionDoor), ledger row inroute-ledger.tsConnectorConnectionState:status(not_connected/connected/reconnect_required),statusReason,scopes,expiresAt,connectedAt,connectedBy. Never a token.POST …/:name/connection{ authorizationUrl, expiresAt }; the pending connect lives ten minutesDELETE …/:name/connectionnot_connected); 404 when nothing was connectedGET /automation/connectors/oauth/callbackmanage_connector_connections(org-scoped), held by the shipped organization-admin set (plugin-securitydefault-permission-sets.ts)holdConnectorUntilConnectedregisters the instance degraded "not connected" / "reconnect required" with{ kind: 'connection' }as its hold;getConnectorDescriptorsservesstate+degradedReasonbut not the holdreconnect_requiredwritersmarkReconnectRequiredinconnector-connections.ts:invalid_granton refresh, and the discovery refusal from PR #28598Reconnect requiredwithstatusReasonTests
New: ConnectorConnectionsPage.test.tsx, 11 tests (red on main: the module does not exist there)
cd ui && pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/views/setup/ConnectorConnectionsPage.test.tsxat head5986e268:Over stubbed
/meta/connector,/automation/connectorsand connection doors:authorization_codeinstances (abearerand aclient_credentialsinstance are absent), with status badges,statusReason,connectedBy;degradedReasonbeside the connection;about:blankon the click, clearsopener, sends one POST with no body, navigates the window to the answered URL, closes it once a re-read answersconnectedwith a newconnectedAt, and the URL'sstatevalue never appears in the page text;javascript:URL is never navigated to;Not connected; a 404 keeps the dialog open with the sentence.Ablations of the two security guards (each red, then restored by blob hash)
node scripts/ablation-replace.mjson the final head, the source imported relatively (nodist/hop):signIn.opener = null;replaced by a comment:× opens a detached window on the click, …·Tests 1 failed | 10 passed (11)· restored,git diff HEADempty.if (protocol !== 'https:' && protocol !== 'http:')replaced by a never-true test:× an authorization URL that is not http(s) is never navigated to·Tests 1 failed | 10 passed (11)· restored,git diff HEADempty.Neighbouring suites, typecheck, lint
cd ui && pnpm exec vitest run packages/app-shell/src/views/setup/ packages/app-shell/src/__tests__/ packages/app-shell/src/services/:Test Files 48 passed (48) · Tests 719 passed (719)(includes the unchanged Connector credentials page suite and the product-neutral ratchet).cd ui && pnpm exec vitest run packages/i18n/:Test Files 94 passed (94) · Tests 1438 passed | 13 skipped(includes all-locales key parity).ui/packages/app-shell:pnpm run type-checkexit 0, 0 errors (after building the@object-ui/app-shell^...closure).ui/packages/i18n:pnpm run type-checkexit 0.pnpm exec eslint --no-inline-configon the four touched app-shell files: exit 0, no problems.Acceptance notes
manage_metadata, which the organization-admin set does not hold, so this PR addsnav_connector_connectionsto the same contribution inpackages/services/service-automation/src/connector-credentials-ui.ts(componentRef: automation:connector-connections,requiredPermissions: ['manage_connector_connections'],group_integrations, priority 120), its label inpackages/platform-objects(en, es-ES, ja-JP, zh-CN;check:app-nav-i18n), and the Setup → Integrations order pin inpackages/cli. The bundle test was red first (2 of 6) and is 6/6.reconnect_requiredwith the server'sstatusReason; a revoke (here or by another administrator) arrives asnot_connected. The page renders exactly what the server answers.authorization_codeinstance, and a connect needs a vendor authorization server. The server's door is pinned indomains/automation-connector-connection-door.test.ts; the Console's behaviour is pinned over the same shapes above.Verification
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 66 families) run locally on the final head5986e268, exit codes captured before any pipe: all 66 exit 0.--ranreconciliation:66 run, 0 NOT-MEASURED (a DERIVED zero). On the first pass, at8538b112,check:skill-examplesexited 3 (its own refusal on a stale@objectstack/client-reactdist, before measuring); afterpnpm --filter @objectstack/client-react buildit exited 0, and on the final-head pass it exited 0 directly. Run record:pm-orders/server/26702-item7-gates-ran.txtin the project folder.Generated by Claude Code