chore: stop reading the retired OAuth proxy link on toolsets
AIM-671
Summary
- Removes every read of
toolsets.oauth_proxy_server_id: the MCP security check, install-page security mode, both visibility-flip guards, admin server health (drops theoauth_proxylegacy-auth value from the admin API, Admin MCP and admin UI), external MCP migration warnings, deploymentoauth_configured, and a dead well-known proxy branch and unused log attribute. - Adds
server/database/sqlc_retired_columns.sql(ALTER TABLE toolsets DROP COLUMN oauth_proxy_server_id;) as a second schema file for the four sqlc packages that querytoolsets. sqlc expandsSELECT */RETURNING *at generation time, so the regenerated code no longer names the column and keeps returningrepo.Toolset. The pattern is documented in thepostgresqlskill. - After this change,
grep -rn oauth_proxy_server_id server/internal --include='*.go'only hits the schema-deriveddatabase/models.goand a test helper.
Motivation
The OAuth proxy provider code was removed in #3465, and well-known and challenge responses already ignore the proxy. The link survives only as a column that some legacy toolsets still carry. This PR stops reading it so the stacked mig: PR can drop the column.
Why the overlay instead of explicit column lists: rewriting the ~23 star queries in toolsets/queries.sql makes sqlc emit a row type per query. That breaks repo.Toolset across about 20 packages, and the types flip back once the column is dropped, which would force code changes into the migration PR. The overlay leaves queries.sql almost untouched, so it also merges cleanly with the parallel toolsets work. New star queries added in these packages before the drop are covered automatically.
Effects on toolsets that still carry the link
- Every toolset with the link in a live project also has a user session issuer. The issuer gate still rejects unauthenticated requests with 401 and a challenge. On a public one, the old proxy check also rejected valid issuer sessions, because it looked for an OAuth token input that a session bearer does not provide. Those sessions are now served. Private ones are unchanged. New tests pin this for public and private endpoints and for the legacy toolset-slug route.
- Their visibility can now be changed through
toolsets.updateandmcpServers.update. Before, the guard rejected this with a misleading "external OAuth" error. The issuer stays attached. - A private toolset whose only OAuth reference is the link gets an API-key install page. It was always served with an API key.
- A public proxy-linked toolset with no issuer now serves anonymously. Before, it returned 401 with no challenge, so no client could sign in to it. No such toolset exists in a live project.
- Gateway (meta MCP) members that carry the link no longer need a member token. They now behave like other issuer-gated members.
- Until the drop ships, a proxy-linked toolset cannot attach an external OAuth server, because
toolsets_oauth_exclusivitystill forbids both links and nothing clears the proxy link any more. On main this already failed unless the user first removed OAuth. The stacked PR drops the check.
Gutternote review steps
The admin change is visible only on a server whose legacy authentication was the OAuth proxy. Seeded demo data has none, so there is nothing new to see in the preview.
Rollout
- Safe to roll back: the column still exists, and older code still reads it.
- Deploy the server before the admin dashboard. The admin SDK's legacy-auth enum no longer accepts
oauth_proxy. - The stacked
mig:PR must merge only after this PR is deployed to prod, and once no pre-PR image is a rollback target.
š¤ Generated with Claude Code
Summary by cubic
Stops reading the retired OAuth proxy link on toolsets, clearing the way for a stacked migration that drops the toolsets.oauth_proxy_server_id column. The link is now ignored in the MCP security check, install-page security mode, both visibility-flip guards, admin server health, external MCP migration warnings, deployment oauth_configured, and the dead well-known proxy branch. Instead of rewriting the ~23 star queries in toolsets/queries.sql ā which would change the repo.Toolset row type across ~20 packages, then change again once the column drops ā the four sqlc packages that query toolsets list sqlc_retired_columns.sql after schema.sql, so generated code never names the column.
Behavioral changes
- Public toolsets with a user session issuer now accept valid issuer sessions; the old proxy check also rejected them because it looked for an OAuth token input that a session bearer does not provide.
- Their visibility can now be changed through
toolsets.updateandmcpServers.update; previously the guard rejected it with a misleading "external OAuth" error. - A public proxy-linked toolset with no issuer now serves anonymously instead of a 401 that carried no challenge, which no client could sign in against. No such toolset exists in a live project.
- Until the drop ships, a proxy-linked toolset cannot attach an external OAuth server, because
toolsets_oauth_exclusivitystill allows only one link and nothing clears the proxy link anymore.
Rollout
- Deploy the server before the admin dashboard; the admin SDK's legacy-auth enum no longer accepts
oauth_proxy. - Rollback is safe ā the column still exists and older code still reads it.
- The stacked migration must merge only after this PR is deployed to prod, and once no image built before this PR is a rollback target.
š Preview Environment (PR #8019)
Preview URL: https://pr-8019.dev.getgram.ai
| Component | Status | Details | Updated (UTC) |
|---|---|---|---|
| ā Database | Ready | Existing database reused | 2026-10-24 01:18:58. |
| ā Images | Available | Container images ready | 2026-10-24 01:23:47. |
Gram Preview Bot