chore: isolate the remaining toolset MCP hosting columns ahead of their drop

Merged
DA
3d ago
+2251-1583

Closes AIM-731 (3 of 3). Stacked on #8127.

Summary

  • New hostedmcp/legacyalias package. This is the one seam that reads and writes the legacy /mcp/<slug> alias (toolsets.mcp_slug / custom_domain_id). It has its own sqlc package and these Go functions:
    • Find and FindInProject: the slug-fallback lookups.
    • Get and List: alias reads.
    • Taken: the toolset branch of the unified slug check.
    • FollowAlias / AliasAddress: moved here from hostingstate.
    • SetFixture: for tests.
      AIM-670 deletes this package along with every call to it.
  • Alias reads moved behind the seam. Every former alias read now goes through it. Queries that joined t.mcp_slug no longer name it; Go fills the alias in through legacyalias. Covered:
    • the MCP slug fallback, install page, export and well-known pages
    • the unified slug availability check (endpoint creation, custom-domain root, approvals server)
    • gateway telemetry matchers
    • assistants attachments and enable checks
    • Platform MCP plugin views
    • plugin generation
    • the external MCP migration
    • toolset views
    • the OpenAPI impact report
    • admin health
    • attach-impact
    • mint
  • sqlc retired-columns overlay. server/database/sqlc_retired_columns.sql now drops all five hosting columns. Every sqlc package except legacyalias lists it, so toolsetsrepo.Toolset and every other generated toolset row no longer has McpSlug, McpIsPublic, McpEnabled, CustomDomainID or UserSessionIssuerID. Expanded SELECT * / RETURNING * no longer name them.
  • The demo seed postflight no longer checks the columns. It still checks that each canonical server mirrors its toolset and has an endpoint.

Motivation

AIM-671 drops the five columns. Before it does, nothing may read or write them except the alias code AIM-670 owns. This PR makes that boundary checkable.

How it is proven:

  1. Go: the overlay removes the fields from every generated struct outside legacyalias, so any Go read or write of them fails to compile. go build ./... and go vet ./... pass.
  2. SQL: sqlc's analyzer does not check column references inside subqueries, so the overlay alone cannot prove the SQL. Instead, every query of every sqlc package except legacyalias was prepared against a database with the five columns dropped. This used sqlc vet with the sqlc/db-prepare rule, on a copy of sqlc.yaml whose entries point at a schema-only database where ALTER TABLE toolsets DROP COLUMN ... CASCADE had removed the five columns.
    • Every query prepared, apart from the unrelated localaccounts schema, which is not in that database.
    • Control: the same check on the base PR fails with 36 "column does not exist" errors, in admin, assistants, demoseed, deployments, externalmcp, mcpendpoints, metamcp, platformmcp, plugins, testenv and toolsets.
  3. Text: a scan of all queries.sql files for the five column names next to toolsets finds them only in legacyalias. The other hits are other tables' columns with the same names.

Rollout

  • For the AIM-671 drop: legacyalias still reads and writes mcp_slug and custom_domain_id, so those two can only be dropped after AIM-670 deletes the package. mcp_is_public, mcp_enabled and user_session_issuer_id can be dropped once this PR is on every pod. The drop migration must also remove its lines from sqlc_retired_columns.sql.

  • Merging main into the stack: main already deleted sqlc_retired_columns.sql along with the oauth_proxy_server_id drop (#8020). When the stack merges main, keep the file and drop its oauth_proxy_server_id line.

  • No schema or API change.

  • Toolset response hosting fields are unchanged: the hosted server's endpoint, else the legacy alias, else none.

šŸ¤– Generated with Claude Code