You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
POST …/connections/{provider}/start still completes a real OAuth handshake and stores a credential no agent can reach. #828 removed the console's offer of it; it did not remove the path.
The routes are registered unconditionally in a shipped build — oauth is in default (Cargo.toml), so this is not a feature-gated corner:
src/server/ops/connections.rs:69 POST …/connections/{provider}/start
:71 POST …/connections/{provider}/disconnect
:75 GET /api/v1/oauth/callback (unscoped; the signed `state` carries the company)
The callback stores oauth/{provider} (ops::oauth_key, src/server/ops/mod.rs:193). Every reader of that key computes a display boolean or builds a revoke request — src/server/ops/connections_read.rs:374 and the connections routes themselves. Nothing under src/harness/ resolves a credential from it.
The codebase already states the consequence, deliberately, in the one place that has to reason about it — verify_connection's planning arm (src/harness/planning.rs:1189-1194):
A provider connected natively — stored under the host's own oauth/{provider} namespace by the Connections tab — is reported missing with a note that says so, rather than satisfied: the credential is real, but no agent can reach it.
So the product's own planner treats a completed native handshake as not a connection, while the route that creates one is live.
Why now. Until #828 the console was the only thing that made this discoverable. With the offer gone, the path is reachable only by a script, an older console bundle, a bookmarked URL, or someone reading the route table in docs/modules/server/README.md — and none of those has anything telling them the credential is inert. Removing the surface removed the warning along with the trap, which is the half worth recording. Raised by @oxoxDev in review of #828:
the console was the only thing that made this discoverable, and removing it means the route is now a live path with no surface warning about it. Worth either a deprecation note at the route itself, or an issue to retire it alongside whatever resolves #396, so the decision is recorded where the next person will be standing.
One correction to that framing, since it changes what this issue can wait for:#396 is already closed as completed (2026-08-08), and #828 is the change that made its offer honest. There is no open issue left for this to be retired "alongside" — which is precisely why it needs its own, or the write path quietly outlives the issue it was closed under.
Proposal
Smallest useful change, and deliberately not a deletion:
Say so at the route. A doc comment on connections::router() and on start/callback recording that the stored oauth/{provider} credential is consumed by no agent path, that the console stopped offering it in fix(console): stop offering the inert native OAuth catalog (#822) #828, and that a caller reaching it directly gets a stored secret and no capability. Mirror it in docs/modules/server/README.md's route table, which is the other place someone finds this.
Decide the route's fate, once, in writing. Either
retire it — remove start + callback, keep disconnect for as long as any tenant can still hold an oauth/{provider} secret (see below); or
Not urgent and nothing is newly broken: the path predates #828 and behaves exactly as it did. What changed is that it is now unsurfaced, which makes it likelier to be rediscovered by someone who assumes an offered route confers something.
The residual set is bounded and shrinking, which is why disconnect should outlive start. A company can still hold an oauth/{provider} secret written before #828, and DELETE-ing the tile is how it goes; after #828 no console can create a new one. Retiring start first shrinks the set to zero over time without stranding anyone who already has one.
Problem
POST …/connections/{provider}/startstill completes a real OAuth handshake and stores a credential no agent can reach. #828 removed the console's offer of it; it did not remove the path.The routes are registered unconditionally in a shipped build —
oauthis indefault(Cargo.toml), so this is not a feature-gated corner:The callback stores
oauth/{provider}(ops::oauth_key,src/server/ops/mod.rs:193). Every reader of that key computes a display boolean or builds a revoke request —src/server/ops/connections_read.rs:374and the connections routes themselves. Nothing undersrc/harness/resolves a credential from it.The codebase already states the consequence, deliberately, in the one place that has to reason about it —
verify_connection's planning arm (src/harness/planning.rs:1189-1194):So the product's own planner treats a completed native handshake as not a connection, while the route that creates one is live.
Why now. Until #828 the console was the only thing that made this discoverable. With the offer gone, the path is reachable only by a script, an older console bundle, a bookmarked URL, or someone reading the route table in
docs/modules/server/README.md— and none of those has anything telling them the credential is inert. Removing the surface removed the warning along with the trap, which is the half worth recording. Raised by @oxoxDev in review of #828:One correction to that framing, since it changes what this issue can wait for: #396 is already closed as completed (2026-08-08), and #828 is the change that made its offer honest. There is no open issue left for this to be retired "alongside" — which is precisely why it needs its own, or the write path quietly outlives the issue it was closed under.
Proposal
Smallest useful change, and deliberately not a deletion:
connections::router()and onstart/callbackrecording that the storedoauth/{provider}credential is consumed by no agent path, that the console stopped offering it in fix(console): stop offering the inert native OAuth catalog (#822) #828, and that a caller reaching it directly gets a stored secret and no capability. Mirror it indocs/modules/server/README.md's route table, which is the other place someone finds this.start+callback, keepdisconnectfor as long as any tenant can still hold anoauth/{provider}secret (see below); orNot urgent and nothing is newly broken: the path predates #828 and behaves exactly as it did. What changed is that it is now unsurfaced, which makes it likelier to be rediscovered by someone who assumes an offered route confers something.
The residual set is bounded and shrinking, which is why
disconnectshould outlivestart. A company can still hold anoauth/{provider}secret written before #828, andDELETE-ing the tile is how it goes; after #828 no console can create a new one. Retiringstartfirst shrinks the set to zero over time without stranding anyone who already has one.Alternatives
OPENCOMPANY_OAUTH_*is injected, per connections: the Connect button stores a credential that no agent can ever use #396). The cost is that the only thing that ever explained it was the button fix(console): stop offering the inert native OAuth catalog (#822) #828 removed.oauth/{provider}secret with no way to release it, andconnections_readwould keep reporting it connected.Related