Skip to content

[design] Stage 2: register the generic connector OAuth redirect for Drive/WorkDrive/Gmail and retire the dedicated flows (Stage 1 — the registry declaration — has shipped) #352

Description

@serge-ivo

The gap

lib/connectors/registry.ts is the platform's answer to "what can an agent reach, and who says so". A
connector is declared once and everything derives from that entry: the tool catalog,
connectorClient auth dispatch, capabilities.tools gating, the write-consent gate (#90), and all
three surfaces (agent runtime / /v1/instances/:id/tools / MCP).

Eleven connectors live there: github, meta, terminal, tmux, browser, repo-local,
supervision, http, mcp, google_sheets, web-search.

Google Drive, Zoho WorkDrive and Gmail are not among them. They are bespoke routes
(routes/drive.ts, routes/workdrive.ts, routes/email.ts), with hand-written console blocks in
SettingsTab.tsx:967-1075.

Because they are not declared, there is nothing for a capability to gate against. So they render on
every instance, for every agent, regardless of what that agent can do. On this account that is 26
instances — including Repo Chat, whose entire job is answering questions about code, and the four
terminal Operators, none of which has any file-connector tool.

Why this is a half-finished migration, not a refactor

Three pieces of the destination already exist and are already tested:

1. The grant model is built and unused. Connector.grantModel (lib/connectors/types.ts:129)
takes "user" | "instance-resource", the second documented as "each tool call must target a
resource granted to the instance"
— which is precisely Drive/WorkDrive's folder grant.
connectors/client.ts:90-102 mints a token for such a connector only after
requireConnectorGrant passes, fail-closed with a 403, and client.test.ts:143,152 covers both
directions.

No connector in CONNECTORS declares grantModel: "instance-resource". The feature was built for
these three and they never arrived.

2. They already share the storage. routes/drive.ts:27 and routes/workdrive.ts:16 both import
lib/connector-grants.js — the same connector_grants table the registry model reads. Its own
header comment names the intended consumers: "Known values: google_drive | zoho_workdrive | (any
connector id with grantModel:"instance-resource")"
.

3. The OAuth path is proven on the same credential. google_sheets (#89/#143/#147) is a
declarative manifest driven by the generic OAuth2 handler, connecting at
/v1/connectors/google_sheets/oauth/startusing the same GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET
as Drive
, with its refresh token in its own vault slot. Its source comment says so explicitly:
"separate from Drive". Sheets took the new road; Drive stayed on the old one.

So the destination is not hypothetical. It is a manifest per connector plus handlers for the parts
that are genuinely custom (Drive's file listing, WorkDrive's DC-specific bases, Gmail's
find_confirmation_link permission gate).

What it buys

Sequencing

This supersedes the symptom fixes rather than competing with them — but those are small and land
today, so do them first and let this delete the code they touch.

Gmail is the delicate one: find_confirmation_link is permission-gated on
AgentState.permissions.email and reads the owner's inbox. Its gate must survive the move as a
declared scope, not be softened into a plain write-consent checkbox.

Related: #146 (connector manifests), #147 (generic connector OAuth), #86 (registry), #90
(write-consent).

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3: laterDesign, strategy, or deferred pending a decision or demandbackendBackend / Worker / API workconnectorsConnector + tool frameworkenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions