Skip to content

Generated by AI agent: route portal extension-pages.json at console, not localhost - #4803

Open
Brandoffsky wants to merge 1 commit into
mainfrom
fix/portal-config-console-url
Open

Generated by AI agent: route portal extension-pages.json at console, not localhost#4803
Brandoffsky wants to merge 1 commit into
mainfrom
fix/portal-config-console-url

Conversation

@Brandoffsky

@Brandoffsky Brandoffsky commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Ticket

https://disruptorbeam.atlassian.net/browse/BEAM-XXXX

Brief Description

RemotePortalConfigService.FetchRemotePortalConfig hardcodes the mount-site catalog URL:

-        var url = "http://localhost:4950/" + "/extension-pages.json";
+        var url = PortalCommand.GetPortalBaseUrl(args, PortalType.Console) + "/extension-pages.json";

This is an unreleased regression, not a live outage. The released CLI (7.2.2) derives the URL from the target host, so portal extension * works today against a dev realm. The hardcode is on main only — shipping it would fetch the catalog from localhost:4950 for every realm, for every developer, regardless of what they're pointed at.

Three reasons that's worse than it looks:

  1. It fails silently. FetchRemotePortalConfig catches, warns, and returns an empty RemotePortalConfiguration(). So portal extension list-extension-options would report no mount options with nothing user-visible explaining why — only a log line. project new portal-extension, portal extension add-microservice and portal open-extension degrade the same way. A hard failure would at least be noticed.

  2. It makes --portal-url inert. GetPortalBaseUrl consults the PortalUrlOption override first; a literal string never does. So while the URL is hardcoded, the documented escape hatch for pointing the CLI at a locally-running portal does nothing — the code is local-only, not local-first.

  3. Consistency. BeamoLocalSystem_PortalExtension.cs already calls GetPortalBaseUrl(..., PortalType.Console) for the sibling path. Two call sites for the same catalog currently disagree.

Notes

On the PortalType choice. Both derivations serve the catalog for a dev realm, so Console is a direction/consistency call rather than a correctness one. Measured against /extension-pages.json:

target host derives result
dev.api.beamable.comConsole dev.console.beamable.com 200
dev.api.beamable.comLegacyPortal dev-portal.beamable.com 200
api.beamable.comConsole console.beamable.com 404
api.beamable.comLegacyPortal portal.beamable.com 404

Worth correcting an earlier version of this description: it claimed the LegacyPortal default "resolves to portal.beamable.com and 404s". That is true for prod only. The substitution is Replace("dev.", "dev-").Replace("api", "portal"), so a dev host yields dev-portal.beamable.com, which serves. Console is preferred here for consistency with the sibling call site and because the console host is where this is heading — not because Legacy is broken.

Prod does not publish the catalog under either name. That is a hosting-side gap rather than a CLI one, and worth routing to whoever owns console deploys; it is unchanged by this PR.

Also corrects the stale docstring on RemotePortalConfiguration, which still pointed at portal.beamable.com.

Checklist

  • Have you added appropriate text to the CHANGELOG.md files?

Testing

No new tests. FetchRemotePortalConfig is a private static whose behaviour is a live HTTP fetch, with no existing coverage.

Verified by dotnet build cli/cli.csproj (0 errors), the endpoint checks in the table above, and end-to-end through beam mcp serve from an external consumer (Wingman coding mode, beamable/BeamableAPI#701) — which is where the silent-empty-config failure mode was observed, and which passes --portal-url through for local-portal development once this lands.

RemotePortalConfigService.FetchRemotePortalConfig hardcoded
`http://localhost:4950/` + `/extension-pages.json`, so every consumer of the
remote mount-site catalog 404'd against a service that is not running. This
blocks `portal extension list-extension-options`, `project new
portal-extension`, `portal extension add-microservice`, and `portal
open-extension` -- including when driven over MCP (`beam mcp serve`).

Route through PortalCommand.GetPortalBaseUrl(args, PortalType.Console), which
maps {env}.api.beamable.com -> {env}.console.beamable.com. This matches the
sibling call already using PortalType.Console at
BeamoLocalSystem_PortalExtension.cs:234.

Note the plan doc (cli/projects/portal-extension-tests-plan.md:38) shows the
bare GetPortalBaseUrl(args) -- that is the LegacyPortal default and resolves
to portal.beamable.com, which 404s (NoSuchKey). The plan predates the console
split; Console is the correct variant.

Verified 2026-08-13:
  dev.console.beamable.com/extension-pages.json      200, valid mountSites
  staging.console.beamable.com/extension-pages.json  NXDOMAIN
  console.beamable.com/extension-pages.json          404

Only dev publishes the catalog today. That is non-fatal -- the fetch already
catches, warns, and returns an empty config so locally-discovered mount sites
still surface -- but the remote catalog stays unavailable on staging/prod
until console publishes the file there. That is a hosting-side gap, not a CLI
one.

Also corrects the stale docstring on RemotePortalConfiguration, which still
pointed at portal.beamable.com.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Brandoffsky
Brandoffsky requested review from jstnlef and removed request for jstnlef August 13, 2026 17:35
@github-actions

Copy link
Copy Markdown
Contributor

Lightbeam link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant