chore: stop reading the retired OAuth proxy link on toolsets

Merged
DA
5d ago
+265-158

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 the oauth_proxy legacy-auth value from the admin API, Admin MCP and admin UI), external MCP migration warnings, deployment oauth_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 query toolsets. sqlc expands SELECT * / RETURNING * at generation time, so the regenerated code no longer names the column and keeps returning repo.Toolset. The pattern is documented in the postgresql skill.
  • After this change, grep -rn oauth_proxy_server_id server/internal --include='*.go' only hits the schema-derived database/models.go and 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.update and mcpServers.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_exclusivity still 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.update and mcpServers.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_exclusivity still 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

ComponentStatusDetailsUpdated (UTC)
āœ… DatabaseReadyExisting database reused2026-10-24 01:18:58.
āœ… ImagesAvailableContainer images ready2026-10-24 01:23:47.

Gram Preview Bot