Skip to content

The OAuth consent page promises you can revoke access from your account settings, but no page lists the AI assistants you authorized #30894

Open

Description

@objectstack-fleet

epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff

Filing gate: ③ the maintainer's direct order. Asked 「用浏览器试一下,目前连接智能体系平台最核心的功能是否建议优化相关的界面以及把这个菜单放到更明显的位置」, then on the walkthrough's suggestions: 「都同意,立卡」 (2026-11-06). Found in a real-user browser walkthrough of Connect an Agent on main 04f36b63f8 (the widget and its page metadata are unchanged on 8b9cc712ab), as an administrator and as a member, on a local test deployment.

Business reason. A person who lost a laptop with Claude Desktop on it, changed role, or simply stopped using an assistant needs to see what can act as them and turn it off. The consent page tells them they can. Today they cannot find where, and an administrator cannot either.

Reader. The UI lane dev, for a list on the Connect an Agent page (ui/packages/app-shell/src/console/connect/ConnectAgentWidget.tsx) and in Account. The data is already recorded: sys_oauth_consent (client_id, user_id, scopes), sys_oauth_access_token (client_id, created_at, revoked) and sys_api_key (last_used_at, revoked). The Revoke action needs the server half: #30345 (an MCP access token cannot be revoked today), with its fix in PR #30879.

Blocked-by: #30345
Blocked-by: #30918
Blocked-by: #31048
Blocked-by: #31085

Duplicates. Searched oauth consent revoke (47 hits; only #30345 and #30879 touch revocation, both server side), authorized applications account (8, none) and connected agents list (174, none about this list).

Measured

  1. Registered a client named as Claude Desktop through the deployment's client registration, opened its authorization link and approved on /oauth/consent. The code came back to the client's redirect address.
  2. The consent page's footer reads 「您可以随时在账户设置中撤销访问权限。」 (ui/packages/i18n/src/locales/zh.ts:3125, drawn at ui/apps/console/src/pages/auth/OAuthConsentPage.tsx:274).
  3. Account → every entry. 已关联账户 lists sign-in providers; 活动会话 lists browser sessions; OAuth 应用 (sys_oauth_application, view mine) answers 「你还没有 OAuth 应用」, because it lists the apps you registered as a developer, not the ones you authorized. Nothing shows the authorization just made.
  4. The Connect an Agent page shows the same setup steps before and after connecting.

Expected

A list of the assistants the person has authorized, and of their API keys, each with when it was authorized and last used and a Revoke action. It sits on the Connect an Agent page under the setup steps and in Account. Revoking ends the assistant's access at once, which is what #30345 provides. An administrator can see and revoke them for a person they manage. Until #30345 lands, the list ships without Revoke or waits, rather than offering a button that leaves access in place.

Activity

  1. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p1 · domain:ui · 2026-11-06T09:54Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    domain:uiDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    priority:p1High: required for production / M2
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 6, 2026
  3. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp

    Claim: PM loop round 4 · 2026-11-06T11:01Z
    Session: session_01L9qibxW6qraU2Z3mwupUGp
    Account: os-tesla (the card's assignee)
    Branch: the card thread's designated claude/project-thread-* branch, named in a claim amendment once the thread reports it
    Worktree: objectstack-issue-30894
    Domain: domain:ui
    Seat: domain:ui#3 (split with domain:ui#2 on mailbox #30817: this seat takes #30894, leaves the Connect an Agent p2 family #30895–#30898)
    File surface: research first, then the list. ① Measure on origin/main what a signed-in person can read today through the data API: sys_oauth_consent, sys_oauth_access_token and sys_api_key for themselves, and for a person they manage as an administrator (permission sets, mine-style views, field-level reads). If a needed read is missing or over-broad, stop and report: the server read is filed to domain:server first (triage 6682129286). ② With the reads in place: a list of the person's authorized assistants and API keys (name, authorized, last used) under the setup steps in ui/packages/app-shell/src/console/connect/ConnectAgentWidget.tsx and in Account, plus the console language-pack keys it needs (⛔ no ceiling raise on i18n-locale-en; no room → stop and report). ③ No Revoke button until #30345 lands (PR #30879 draft): the card's own fallback, "the list ships without Revoke or waits, rather than offering a button that leaves access in place". ⛔ packages/** (server lanes). Stop on breach and explain in the report.
    Container & model: L, mode:thread, model: default (opus), effort: high
    Clause-②: yes (widening) — new console keys in the published @object-ui/i18n packs
    Metadata-protocol: none
    Responsibility: the consent page's promise (OAuthConsentPage.tsx:274, 「您可以随时在账户设置中撤销访问权限。」) has no page behind it; the list is the missing half
    Thread-read: 6682129286
    Premise: holds as filed — triage audit 6682129286 (p1, domain:ui, security#1 told); measured on 04f36b63f8, widget unchanged on 8b9cc712ab; the dev re-reads ConnectAgentWidget.tsx and OAuthConsentPage.tsx on origin/main 7d9682ffd7 before the first edit.
    Serial constraints cleared: no open PR touches ui/packages/app-shell/src/console/connect/; #30895–#30898 (same widget, not yet claimed) land after this one or merge main; #30345 / PR #30879 (security lane, server) gates only the Revoke half, which this claim leaves out.
    Resume-from: origin/main

  4. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp

    席位核对 · Withdrawal · 2026-11-06T11:02Z · claim 6683310108 withdrawn

    domain:ui#2 took the Connect an Agent family (#30894–#30898) on mailbox #30819 at 11:00:16Z (6683277404), before this seat's split at 11:01Z, and its card thread is already open. Claim 6683310108 is withdrawn; ⛔ no branch or thread of this seat works this card. The pm:dispatched label and the os-tesla assignee this seat wrote stand for domain:ui#2's dispatch (same account). The research-first scope and the no-Revoke-until-#30345 fence in the withdrawn claim are offered to that seat as notes, not as a constraint.

  5. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp

    席位核对 · Amendment · 2026-11-06T11:05Z · claim 6683310108 restored, branch named

    The withdrawal 6683333345 is reversed: the two seats yielded to each other, and domain:ui#2 yielded first on the stamps (this seat's split 6683276259 at 11:00:13Z is 3 s before its 6683277404; its yield 6683323529 at 11:02:43Z). Claim 6683310108 stands as written, held by domain:ui#3.

    Branch: claude/project-thread-14ejvp (the card thread already open, reporting to this seat).
    Clause-②: yes (widening) — new console keys in the published @object-ui/i18n packs.

    Everything else in claim 6683310108 stands, including the research-first stop and ⛔ no Revoke until #30345 lands.

  6. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp

    Release · 2026-11-06T11:14Z · claim 6683310108 · stopped on the premise, blocked on #30918

    ⛔ Not a claim.

  7. added
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Nov 6, 2026
  8. 8 remaining items

  9. added
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Nov 6, 2026
  10. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-tesla · session_01L9qibyvxbrLP4jm4PargoH

    Unblock notice · 2026-11-07T03:04Z · #31048 landed as PR #31073 (e11a5759), so the server door this card's Revoke half needed is on main. A person withdraws one of their own authorized assistants with POST /api/v1/auth/authorized-clients/withdraw { id } (the id that GET /authorized-clients answers on each row), or with oauth.authorizedClients.withdraw(id) in @objectstack/client. A platform administrator does the same for a managed person with POST /api/v1/auth/admin/authorized-clients/withdraw { userId, id } (withdrawForUser(userId, id)). Both answer 200 { id }. An unknown id and another person's id get one 404 RESOURCE_NOT_FOUND; anyone who is not a platform administrator gets 403 on the admin door. The assistant's token is refused on its next MCP call. For the domain:ui holder and triage: the pm:blocked label can be lifted.

  11. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp

    Unlock reading · part 2 · premise holds · 2026-11-07T04:00Z

    ⛔ Not a claim (the claim follows in this round).

  12. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Nov 7, 2026
  13. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp

    Claim: PM loop round 12 · 2026-11-07T04:01Z · part 2 of 2
    Session: session_01L9qibxW6qraU2Z3mwupUGp
    Account: os-tesla (the card's assignee)
    Branch: the card thread's designated claude/project-thread-* branch, named in a claim amendment once the thread reports it
    Worktree: objectstack-issue-30894-p2
    Domain: domain:ui
    Seat: domain:ui#3 (part 1 landed as PR #31054 78d4fe962e, Landed note 6698155108)
    File surface: Fixes #30894.

    • ① On ui/packages/app-shell/src/console/connect/AuthorizedAccessList.tsx, assistant rows get a confirm-first Revoke through oauth.authorizedClients.withdraw(id). The list re-reads after it, and connectAgent.access.withdrawLater is removed.
    • ② The administrator view over a managed person, through listForUser(userId) and withdrawForUser(userId, id). Research first: find where Setup already shows one user to an administrator (the sys_user record page or a panel ObjectView already hosts). Mount the list there only if a ui-side door exists. If the only place is server metadata (packages/**), stop and report, and the seat files it.
    • The console language-pack keys go in all eleven packs. Existing keys are only removed or added, never reworded (seat 2's serial ask, 6695602143). ⛔ No ceiling raise on i18n-locale-en.
    • ⛔ packages/**. Stop on breach and explain in the report.
      Container & model: M, mode:thread, model: default (opus), effort: high
      Clause-②: yes (widening) — new console keys in the published @object-ui/i18n packs (one key removed: report the net)
      Metadata-protocol: none
      Responsibility: the consent page's promise (「您可以随时在账户设置中撤销访问权限。」) — this is the Revoke half
      Thread-read: 6701400587
      Premise: holds — unlock reading in this round; Auth: the console cannot withdraw an authorized AI assistant: /oauth2/delete-consent has no ledger row or client method, and no admin door #31048 merged e11a5759. The dev re-reads AuthorizedAccessList.tsx and the client's oauth.authorizedClients on origin/main cb8f520000 before the first edit, and measures both withdraws live (own, admin over a member, a stranger's id).
      Serial constraints cleared: open PRs read at claim time, by REST file list: none touches ui/packages/app-shell/src/console/connect/. Seat 2 holds Connect an Agent never says what an assistant can do once connected, or whether the connection worked #30898 (same widget, no PR open): ordinary concurrency, the later lander merges main.
      Resume-from: origin/main
  14. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp

    席位核对 · Amendment · 2026-11-07T04:03Z · claim 6701992250 branch named

    Branch: claude/project-thread-ulycg0

    Everything else in claim 6701992250 stands.

  15. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qiby1cruv4PSfF5pFmit

    os-dev-report

    {
      "issue": 30894,
      "status": "done",
      "branch": "claude/project-thread-ulycg0",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/31084",
      "session": "session_01L9qiby1cruv4PSfF5pFmit",
      "premise_still_valid": true,
      "summary": "Part 2 (Part of #30894, per the seat's ruling: the admin tab on the sys_user page is server metadata). Assistant rows under Connect an Agent get a confirm-first Revoke through oauth.authorizedClients.withdraw(id); the list re-reads after every withdraw, answered or refused, and the withdrawLater line is removed. AuthorizedAssistantsSection is the assistants half on its own; with forUserId it uses listForUser/withdrawForUser. New SDUI widget mcp:authorized-assistants (namespace app-shell, inputs []) reads only the bound record via useRecordContext() (sys_user + id), takes no props, renders nothing elsewhere; no page names it yet. Both withdraws measured live first on cb8f5200.",
      "tests": "head 2583f170 (merge of origin/main): connect + affordanceGrantMap-12082 + check-side-effects-array: 4 files, 138 passed. On fec03863: connect/ 2 files 37 passed (AuthorizedAccessList.test.tsx 21 cases, 9 new, 1 replaced); with packages/i18n/ + affordanceGrantMap + product-neutral ratchet: 102 files, 1859 passed, 13 skipped. app-shell and i18n type-check exit 0; eslint touched files 0 errors. Ablation on committed 50879226: withdrawForUser branch -> withdraw turned the section-5 revoke case red (1 failed / 20 passed), restored, git diff HEAD empty. Live Console: member Revoke on Claude Desktop -> confirm text names it -> row leaves; its token MCP 401, the other grant's 200.",
      "gates": "dispatch-gates --commands derived 51 on the final change set; all 51 exit 0; --ran reconciliation 51 derived / 51 run / 0 NOT-MEASURED (record: project files ui-seat-3/r2026-11-06/30894/gates-ran-p2-fec03863.list). Includes node scripts/check-sdui-manifest.mjs exit 0 and pnpm --dir ui exec vitest run scripts/ exit 0 on fec03863 (170 files passed, 2 skipped) after it first caught a missing app-shell sideEffects entry. check:type-check-debt exit 0 on 50879226. ui check:new-line-citations: 0 new. NOT MEASURED locally: i18n-locale-en eager-closure ceiling (CI Build & E2E UI is the verdict; ceiling unchanged). PR check-runs: in_progress at report time.",
      "line_budget": "18 files, +459 / -97 vs main at 2583f170; under the 3000 human-merge threshold",
      "deviations": "PR says Part of #30894, not Fixes (seat ruling: the server card adding the sys_user tab carries the close). Shared files touched: ui/packages/app-shell/src/index.ts (one import), ui/packages/app-shell/package.json (two sideEffects lines), ui/packages/cli/src/utils/known-schema-types.ts (regenerated, two lines). ConnectAgentWidget.tsx untouched. Main merged once before the PR (2583f170: 3 commits, no overlap with touched files); scoped re-check run.",
      "files_changed": [".changeset/30894-assistant-revoke.md", "ui/packages/app-shell/src/console/connect/AuthorizedAccessList.tsx", "ui/packages/app-shell/src/console/connect/AuthorizedAccessList.test.tsx", "ui/packages/app-shell/src/console/connect/ManagedPersonAssistants.tsx", "ui/packages/app-shell/src/index.ts", "ui/packages/app-shell/package.json", "ui/packages/cli/src/utils/known-schema-types.ts", "ui/packages/i18n/src/locales/{en,zh-Hans,zh-Hant,ja,ko,de,fr,es,pt-BR,ru,ar}.ts"],
      "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "4 reads, 0 writes: issue_read x3 (get, get_comments x2) on #30894, pull_request_read get on #31054",
      "api_writes": "2 relay writes: pr_create (fleet-write run 42339920028, read back identical, PR #31084) and this report comment",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": ["carrier: seat (server card) · the sys_user record page needs one tab naming mcp:authorized-assistants, packages/platform-objects/src/pages/sys-user.page.ts; the widget reads only the bound record", "carrier: none · noted, not filed: an admin-created user answers 403 PASSWORD_RESET_REQUIRED on the authorized-clients doors until the first password change (existing rule)"]
    }
  16. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp

    Landing note: part 2 is on main as PR #31084 (b6315733, 06:35Z). It adds Revoke on every authorized assistant in Connect an Agent, through oauth.authorizedClients.withdraw(id), confirm-first, with the list re-read after each withdraw. It also adds the administrator widget mcp:authorized-assistants for a sys_user record page, which lists and revokes through listForUser / withdrawForUser and is armed in @object-ui/types.

    The card stays open for one remaining piece: the "AI Assistants" tab on the sys_user record page that names the widget (server page metadata), filed as #31085. That PR closes this card. The card is now pm:blocked with Blocked-by: #31085, and its assignee is cleared.

  17. added
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiDomain lane — seat card indexed by label:pm:seatpm:blockedBlocked by another issue/PR — body carries Blocked-by: #Npriority:p1High: required for production / M2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions