fix(amr): follow vela's test Cloud domain cutover (#7880)

vela moved the test Cloud entry off `vela.powerformer.net` onto
`open-design.powerformer.net/cloud` (vela #1922 prepare, #1929 finalize).
The new host serves the test Landing page at `/` and hands `/cloud*` and
`/amr*` to a test-only path proxy; per vela's `specs/current/envs.md` the
legacy hostname is no longer a mapped test route and is scheduled for
decommissioning, so it must not be relied on for a compatibility redirect.

Both surfaces that name the test console were still on the old host, so a
`OPEN_DESIGN_AMR_PROFILE=test` build sent every console link (dashboard,
plans, workspace settings, top-up) at a host on its way out.

Every consumer of the daemon's console origin concatenates a path onto it
(`${origin}/dashboard`, `${origin}/settings`) rather than resolving against
it as a URL base, so carrying the `/cloud` segment in the origin is safe and
mirrors the existing prod entry `https://open-design.ai/cloud`.

Left unchanged, deliberately:
- prod stays on `/amr/dashboard`. It is already the dashboard, not a wallet
  page, and prod `/amr*` still answers with a 302 to `/cloud/dashboard` that
  preserves path and query. Moving prod off the compat prefix touches a much
  wider surface and is not part of this cutover.
- feature-test still has no row in either table. Its hostname is internal and
  this repository ships publicly, so it arrives through OD_VELA_WEB_URLS /
  OD_VELA_WEB_URL at packaging time and otherwise falls back to the public
  console instead of guessing.

The daemon's public origin table had no test coverage at all; the added cases
pin the shipped test/prod/local values and the feature-test absence.
This commit is contained in:
lefarcen
2026-09-08 05:35:20 +00:00
committed by GitHub
parent 677457dfbc
commit 11943a400f
8 changed files with 62 additions and 12 deletions
@@ -2,12 +2,25 @@ import { resolveAmrProfile } from './vela-profile.js';
type EnvMap = NodeJS.ProcessEnv | Record<string, string | undefined>;
// Publicly named console origins already used by the web client. feature-test
// remains build-injected because its deployment hostname is intentionally not
// part of the public repository.
// Publicly named console origins already used by the web client. Each value is
// a Cloud *base* that callers append a console path to (`/dashboard`,
// `/settings`), so the `/cloud` segment belongs here rather than at each call
// site — every consumer concatenates, none resolves against it as a URL base.
//
// The test entry moved off `vela.powerformer.net` onto
// `open-design.powerformer.net/cloud` when vela cut the test Cloud domain over
// (vela #1922 prepare, #1929 finalize). The new host serves the test Landing
// page at `/` and hands `/cloud*` and `/amr*` to a test-only path proxy; the
// legacy hostname is no longer a mapped test route and is scheduled for
// decommissioning, so it must not be relied on for a compatibility redirect.
//
// feature-test is deliberately absent: this repository ships publicly and that
// deployment's hostname is internal. It is supplied at packaging time through
// OD_VELA_WEB_URLS / OD_VELA_WEB_URL, so an un-injected build resolves nothing
// for it and the client falls back to the public console instead of guessing.
const PUBLIC_ORIGINS: Partial<Record<string, string>> = {
prod: 'https://open-design.ai/cloud',
test: 'https://vela.powerformer.net',
test: 'https://open-design.powerformer.net/cloud',
local: 'http://localhost:5173',
};
@@ -40,6 +40,34 @@ describe('resolveVelaConsoleOrigin', () => {
})).toBe('https://feature.example.invalid');
});
// The publicly named profiles resolve without any build injection, so their
// literals in PUBLIC_ORIGINS are the shipped value. vela moved the test Cloud
// entry off `vela.powerformer.net` onto `open-design.powerformer.net/cloud`
// (vela #1922 prepare / #1929 finalize); that host maps `/cloud*` and `/amr*`
// to the Web origin, and the legacy hostname is explicitly no longer a mapped
// test route, so a stale value here sends every console link off-environment.
it('resolves the public console origin for a runtime profile selection', () => {
expect(resolveVelaConsoleOrigin({}, { OPEN_DESIGN_AMR_PROFILE: 'test' })).toBe(
'https://open-design.powerformer.net/cloud',
);
expect(resolveVelaConsoleOrigin({}, { OPEN_DESIGN_AMR_PROFILE: 'prod' })).toBe(
'https://open-design.ai/cloud',
);
expect(resolveVelaConsoleOrigin({}, { OPEN_DESIGN_AMR_PROFILE: 'local' })).toBe(
'http://localhost:5173',
);
});
// feature-test is deliberately NOT in the public table: its deployment
// hostname is internal, and this repository ships publicly. It arrives only
// through OD_VELA_WEB_URLS / OD_VELA_WEB_URL at packaging time, so with no
// injection the runtime reports nothing rather than guessing a hostname.
it('has no public origin for the internal feature-test profile', () => {
expect(
resolveVelaConsoleOrigin({}, { OPEN_DESIGN_AMR_PROFILE: 'feature-test' }),
).toBeUndefined();
});
it('never reuses the packaged origin after switching to an unmapped profile', () => {
expect(resolveVelaConsoleOrigin({
OPEN_DESIGN_AMR_PROFILE: 'test',
+10 -1
View File
@@ -78,9 +78,18 @@ export const AMR_CONSOLE_UPGRADE_INTENT = 'plan';
*/
export const AMR_CONSOLE_AUTO_RECHARGE_INTENT = 'auto-recharge';
// The test entry moved off `vela.powerformer.net` onto
// `open-design.powerformer.net/cloud` when vela cut the test Cloud domain over
// (vela #1922 prepare, #1929 finalize). That host serves the test Landing page
// at `/` and routes `/cloud*` to the AMR web origin; the legacy hostname is no
// longer a mapped test route and must not be relied on for a redirect.
//
// feature-test has no row on purpose — see the note at the bottom of this file:
// an internal hostname must not be a literal in a publicly shipped bundle, so
// it arrives through the daemon's runtime console origin instead.
const AMR_CONSOLE_URL_BY_PROFILE: Record<string, string> = {
prod: DEFAULT_AMR_RECHARGE_URL,
test: 'https://vela.powerformer.net/dashboard?source=open_design',
test: 'https://open-design.powerformer.net/cloud/dashboard?source=open_design',
local: 'http://localhost:5173/dashboard?source=open_design',
};
@@ -279,7 +279,7 @@ describe('AmrLoginPill', () => {
expect(screen.getByText('leaf@example.com')).toBeTruthy();
expect(screen.getByText('TEST')).toBeTruthy();
expect(screen.getByRole('link', { name: 'Manage' }).getAttribute('href')).toBe(
'https://vela.powerformer.net/dashboard?source=open_design',
'https://open-design.powerformer.net/cloud/dashboard?source=open_design',
);
});
@@ -266,7 +266,7 @@ describe('ChatPane session switcher', () => {
const parsedConsoleUrl = new URL(String(consoleUrl));
// Top-up reports on the console dashboard now, not a wallet page.
expect(`${parsedConsoleUrl.origin}${parsedConsoleUrl.pathname}`).toBe(
'https://vela.powerformer.net/dashboard',
'https://open-design.powerformer.net/cloud/dashboard',
);
// The plain top-up entry must NOT carry the upgrade intent — it opens the
// console to add credit, not the plan catalog.
@@ -312,7 +312,7 @@ describe('ChatPane session switcher', () => {
// non-prod build sent people to production checkout.
const parsedPlansUrl = new URL(String(plansUrl));
expect(`${parsedPlansUrl.origin}${parsedPlansUrl.pathname}`).toBe(
'https://vela.powerformer.net/dashboard',
'https://open-design.powerformer.net/cloud/dashboard',
);
expect(parsedPlansUrl.searchParams.get('billing')).toBe('plan');
expect(parsedPlansUrl.searchParams.get('od_entry_source')).toBe('chat_error_upgrade');
@@ -664,8 +664,8 @@ describe('InlineModelSwitcher AMR row', () => {
// The point of this case is the PROFILE: a signed-in test-profile account
// must not be handed a production upgrade link. While the plans URL ignored
// its profile argument this assertion read the prod host (T54).
expect(parsed.origin).toBe('https://vela.powerformer.net');
expect(parsed.pathname).toBe('/dashboard');
expect(parsed.origin).toBe('https://open-design.powerformer.net');
expect(parsed.pathname).toBe('/cloud/dashboard');
expect(parsed.searchParams.get('billing')).toBe('plan');
expect(parsed.searchParams.get('od_entry_source')).toBe('inline_amr_upgrade');
expect(parsed.searchParams.get('od_device_id')).toBe('od-install-abc');
+1 -1
View File
@@ -33,7 +33,7 @@ describe('amrRechargeUrlForProfile', () => {
);
expect(amrRechargeUrlForProfile('prod')).toBe(DEFAULT_AMR_RECHARGE_URL);
expect(amrRechargeUrlForProfile('test')).toBe(
'https://vela.powerformer.net/dashboard?source=open_design',
'https://open-design.powerformer.net/cloud/dashboard?source=open_design',
);
expect(amrRechargeUrlForProfile('local')).toBe(
'http://localhost:5173/dashboard?source=open_design',
@@ -35,7 +35,7 @@ describe('升级按钮的落点:console 的套餐页', () => {
it('test profile 落在 test console,不再落在生产 Pricing', () => {
expect(amrPlansUrlForProfile('test')).toBe(
'https://vela.powerformer.net/dashboard?source=open_design&billing=plan',
'https://open-design.powerformer.net/cloud/dashboard?source=open_design&billing=plan',
);
});