From da239cb9b2443c1d977b881cf600c8ebf4b2a368 Mon Sep 17 00:00:00 2001 From: luvs01 <27862058+luvs01@users.noreply.github.com> Date: Sun, 13 Sep 2026 13:00:06 +0900 Subject: [PATCH] fix(cli): open hub management on its bound IPv4 address --- docs-site/src/content/docs/fr/guides/web-dashboard.md | 3 ++- docs-site/src/content/docs/fr/reference/cli/lifecycle.md | 2 +- docs-site/src/content/docs/guides/remote-hub.md | 2 ++ docs-site/src/content/docs/guides/web-dashboard.md | 3 ++- docs-site/src/content/docs/ja/guides/web-dashboard.md | 2 +- docs-site/src/content/docs/ja/reference/cli/lifecycle.md | 2 +- docs-site/src/content/docs/ko/guides/remote-hub.md | 2 ++ docs-site/src/content/docs/ko/guides/web-dashboard.md | 2 +- docs-site/src/content/docs/ko/reference/cli/lifecycle.md | 2 +- docs-site/src/content/docs/reference/cli/lifecycle.md | 9 +++++---- docs-site/src/content/docs/ru/guides/web-dashboard.md | 2 +- docs-site/src/content/docs/ru/reference/cli/lifecycle.md | 2 +- docs-site/src/content/docs/tr/guides/web-dashboard.md | 2 +- docs-site/src/content/docs/tr/reference/cli/lifecycle.md | 2 +- docs-site/src/content/docs/zh-cn/guides/web-dashboard.md | 2 +- .../src/content/docs/zh-cn/reference/cli/lifecycle.md | 2 +- docs-site/src/content/docs/zh-tw/guides/web-dashboard.md | 2 +- .../src/content/docs/zh-tw/reference/cli/lifecycle.md | 2 +- src/cli/dispatch.ts | 2 +- structure/clients/claude-desktop.md | 2 ++ structure/config.md | 2 ++ structure/gui-and-management-api.md | 4 ++-- structure/ops/docs-and-release.md | 2 ++ structure/runtime.md | 4 ++++ tests/cli/cli-dispatch.test.ts | 4 ++-- 25 files changed, 41 insertions(+), 24 deletions(-) diff --git a/docs-site/src/content/docs/fr/guides/web-dashboard.md b/docs-site/src/content/docs/fr/guides/web-dashboard.md index 2d4d753bb5..3b545cee09 100644 --- a/docs-site/src/content/docs/fr/guides/web-dashboard.md +++ b/docs-site/src/content/docs/fr/guides/web-dashboard.md @@ -13,7 +13,8 @@ catalogue, les services auxiliaires, les réglages des sous-agents et le trafic ocx gui ``` -Cette commande ouvre `http://localhost:` dans votre navigateur et démarre d'abord automatiquement le +Cette commande ouvre `http://localhost:` dans votre navigateur — ou +`http://127.0.0.1:` lorsque l’ingress de gestion du hub est activé — et démarre d'abord automatiquement le proxy si nécessaire. En développement, vous pouvez lancer séparément le serveur de développement de l'interface contre un proxy déjà actif : diff --git a/docs-site/src/content/docs/fr/reference/cli/lifecycle.md b/docs-site/src/content/docs/fr/reference/cli/lifecycle.md index b7959f558f..73b3c6d065 100644 --- a/docs-site/src/content/docs/fr/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/fr/reference/cli/lifecycle.md @@ -298,7 +298,7 @@ Installe et contrôle l’icône OpenCodex dans la zone de notification Windows. ### `ocx gui` -Ouvre le [tableau de bord Web](/fr/guides/web-dashboard/) à l’adresse `http://localhost:` et démarre automatiquement le proxy s’il n’est pas actif. +Ouvre le [tableau de bord Web](/fr/guides/web-dashboard/) à l’adresse `http://localhost:` — ou `http://127.0.0.1:` lorsque l’ingress de gestion du hub est activé — et démarre automatiquement le proxy s’il n’est pas actif. ## Mise à jour diff --git a/docs-site/src/content/docs/guides/remote-hub.md b/docs-site/src/content/docs/guides/remote-hub.md index e582b03428..816ec09c15 100644 --- a/docs-site/src/content/docs/guides/remote-hub.md +++ b/docs-site/src/content/docs/guides/remote-hub.md @@ -19,6 +19,8 @@ exchange; see [Remote Workspace](/guides/remote-workspace/). Do not publish its port directly, do not add a cloud-firewall rule for it, and do not use Tailscale Funnel. Funnel is a public-internet surface and is outside this deployment model. +With management ingress enabled, the local dashboard command opens `http://127.0.0.1:` so the address matches the IPv4-only listener without resolving `localhost`. + ## Trust and consent boundaries - Provider and OAuth credentials stay on the hub. Never copy them into a client, image layer, diff --git a/docs-site/src/content/docs/guides/web-dashboard.md b/docs-site/src/content/docs/guides/web-dashboard.md index 18954df175..2a9f03f0f7 100644 --- a/docs-site/src/content/docs/guides/web-dashboard.md +++ b/docs-site/src/content/docs/guides/web-dashboard.md @@ -13,7 +13,8 @@ settings, and request traffic. ocx gui ``` -This opens `http://localhost:` in your browser, auto-starting the proxy first if needed. In +This opens `http://localhost:` in your browser — or `http://127.0.0.1:` when hub +management ingress is enabled — auto-starting the proxy first if needed. In development you can run the GUI dev server separately against a running proxy: ```bash diff --git a/docs-site/src/content/docs/ja/guides/web-dashboard.md b/docs-site/src/content/docs/ja/guides/web-dashboard.md index 304c9646b8..dc1186b2c4 100644 --- a/docs-site/src/content/docs/ja/guides/web-dashboard.md +++ b/docs-site/src/content/docs/ja/guides/web-dashboard.md @@ -13,7 +13,7 @@ opencodex はプロキシが提供するローカルウェブダッシュボー ocx gui ``` -ブラウザで `http://localhost:` を開きます。プロキシがオフなら先に自動で起動します。 +ブラウザで `http://localhost:` を開きます。ハブで管理イングレスが有効な場合は `http://127.0.0.1:<管理ポート>` を開きます。プロキシがオフなら先に自動で起動します。 開発中は実行中のプロキシと GUI 開発サーバーを別々に起動できます。 ```bash diff --git a/docs-site/src/content/docs/ja/reference/cli/lifecycle.md b/docs-site/src/content/docs/ja/reference/cli/lifecycle.md index c7a3379fca..74f3b3151b 100644 --- a/docs-site/src/content/docs/ja/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/ja/reference/cli/lifecycle.md @@ -271,7 +271,7 @@ Windows ステータス トレイ アイコンをインストールして制御 ### `ocx gui` -`http://localhost:` で [ウェブダッシュボード](/guides/web-dashboard/) を開き、プロキシが実行されていない場合は自動起動します。 +`http://localhost:` で [ウェブダッシュボード](/guides/web-dashboard/) を開き、プロキシが実行されていない場合は自動起動します。ハブで管理イングレスが有効な場合は `http://127.0.0.1:<管理ポート>` を開きます。 ## 更新 diff --git a/docs-site/src/content/docs/ko/guides/remote-hub.md b/docs-site/src/content/docs/ko/guides/remote-hub.md index bf8b7178ce..f9ac2e2599 100644 --- a/docs-site/src/content/docs/ko/guides/remote-hub.md +++ b/docs-site/src/content/docs/ko/guides/remote-hub.md @@ -9,6 +9,8 @@ Remote Hub를 쓰면 프로바이더 인증 정보와 사용량 기록은 허브 관리 포트에서는 `/v1/*`, `/healthz`, `/readyz`, WebSocket을 제공하지 않습니다. 이 포트를 직접 공개하거나 방화벽에 열지 말고 Tailscale Funnel도 사용하지 마세요. +관리 리스너를 사용하면 로컬 대시보드 명령은 `http://127.0.0.1:<관리 포트>`를 엽니다. `localhost` 이름 해석 없이 IPv4 전용 리스너 주소와 일치합니다. + ## 보안과 동의 경계 - 프로바이더/OAuth 인증 정보는 허브 밖으로 복사하지 마세요. diff --git a/docs-site/src/content/docs/ko/guides/web-dashboard.md b/docs-site/src/content/docs/ko/guides/web-dashboard.md index fc3fa67f80..178620abe9 100644 --- a/docs-site/src/content/docs/ko/guides/web-dashboard.md +++ b/docs-site/src/content/docs/ko/guides/web-dashboard.md @@ -13,7 +13,7 @@ opencodex는 프록시가 제공하는 로컬 웹 대시보드(`gui/` 아래의 ocx gui ``` -브라우저에서 `http://localhost:`를 엽니다. 프록시가 꺼져 있으면 먼저 자동으로 시작합니다. +브라우저에서 `http://localhost:`를 엽니다. 허브에서 관리 리스너를 켜 두면 `http://127.0.0.1:<관리 포트>`를 엽니다. 프록시가 꺼져 있으면 먼저 자동으로 시작합니다. 개발 중에는 실행 중인 프록시와 GUI 개발 서버를 따로 띄울 수 있습니다. ```bash diff --git a/docs-site/src/content/docs/ko/reference/cli/lifecycle.md b/docs-site/src/content/docs/ko/reference/cli/lifecycle.md index 96ed5be6ff..66ab5f9829 100644 --- a/docs-site/src/content/docs/ko/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/ko/reference/cli/lifecycle.md @@ -382,7 +382,7 @@ Windows 상태 트레이 아이콘을 설치하고 제어합니다. Windows 로 ### `ocx gui` 프록시가 실행 중이 아니면 자동으로 시작하면서 [웹 대시보드](/guides/web-dashboard/)를 -`http://localhost:`에서 엽니다. +`http://localhost:`에서 엽니다. 허브에서 관리 리스너를 켜 두면 `http://127.0.0.1:<관리 포트>`에서 엽니다. ## 업데이트 diff --git a/docs-site/src/content/docs/reference/cli/lifecycle.md b/docs-site/src/content/docs/reference/cli/lifecycle.md index 39be1d5326..dd1f07c711 100644 --- a/docs-site/src/content/docs/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/reference/cli/lifecycle.md @@ -325,9 +325,9 @@ The URL must name `/v1/catalog` at the host root. A reverse proxy that serves th path prefix is not supported by this command. The command downloads the full catalog and compares bytes locally instead of issuing an `ETag` / -`If-None-Match` conditional request. Identical bytes are treated as a complete no-op, so a home -whose catalog is correct but whose `models_cache.json` is missing or stale is not repaired by this -command; use `ocx sync-cache` for that. +`If-None-Match` conditional request. Identical bytes are treated as a complete no-op, so a +Codex home whose catalog is correct but whose `models_cache.json` is missing or stale is not +repaired by this command; use `ocx sync-cache` for that. `--json` emits one stable envelope on stdout. `schemaVersion`, `ok`, `status`, `catalogWritten`, `cacheSynced`, and `codexRestarted` are always present. `codexRestarted` still means app-servers @@ -598,7 +598,8 @@ proxy controls. `start` and `stop` control the icon only; use its menu to contro ### `ocx gui` -Open the [web dashboard](/guides/web-dashboard/) at `http://localhost:`, auto-starting the proxy +Open the [web dashboard](/guides/web-dashboard/) at `http://localhost:` — or at +`http://127.0.0.1:` when hub management ingress is enabled — auto-starting the proxy if it is not running. ## Updating diff --git a/docs-site/src/content/docs/ru/guides/web-dashboard.md b/docs-site/src/content/docs/ru/guides/web-dashboard.md index 2ea633b175..0410d733ef 100644 --- a/docs-site/src/content/docs/ru/guides/web-dashboard.md +++ b/docs-site/src/content/docs/ru/guides/web-dashboard.md @@ -13,7 +13,7 @@ opencodex включает локальный веб-дашборд (Vite/React- ocx gui ``` -Команда открывает `http://localhost:` в браузере, при необходимости сначала автоматически +Команда открывает `http://localhost:` в браузере (или `http://127.0.0.1:<порт управления>`, если на хабе включён management ingress), при необходимости сначала автоматически запуская прокси. При разработке dev-сервер GUI можно запускать отдельно поверх работающего прокси: ```bash diff --git a/docs-site/src/content/docs/ru/reference/cli/lifecycle.md b/docs-site/src/content/docs/ru/reference/cli/lifecycle.md index eabdcbdec0..04315f0e2a 100644 --- a/docs-site/src/content/docs/ru/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/ru/reference/cli/lifecycle.md @@ -384,7 +384,7 @@ one-click управление прокси. `start` и `stop` управляю ### `ocx gui` -Открыть [веб-дашборд](/guides/web-dashboard/) по адресу `http://localhost:`, автоматически +Открыть [веб-дашборд](/guides/web-dashboard/) по адресу `http://localhost:` (или `http://127.0.0.1:<порт управления>`, если на хабе включён management ingress), автоматически запустив прокси, если он ещё не работает. ## Обновление diff --git a/docs-site/src/content/docs/tr/guides/web-dashboard.md b/docs-site/src/content/docs/tr/guides/web-dashboard.md index cfc04ca1df..36d4c66f21 100644 --- a/docs-site/src/content/docs/tr/guides/web-dashboard.md +++ b/docs-site/src/content/docs/tr/guides/web-dashboard.md @@ -15,7 +15,7 @@ ocx gui ``` Bu, gerekirse önce proxy'yi otomatik olarak başlatarak tarayıcınızda -`http://localhost:` adresini açar. Geliştirme sırasında GUI geliştirme +`http://localhost:` adresini açar; hub'da yönetim ingress'i etkinse `http://127.0.0.1:` adresini açar. Geliştirme sırasında GUI geliştirme sunucusunu çalışan bir proxy'ye karşı ayrı olarak çalıştırabilirsiniz: ```bash diff --git a/docs-site/src/content/docs/tr/reference/cli/lifecycle.md b/docs-site/src/content/docs/tr/reference/cli/lifecycle.md index a0d8f6a6c0..4e2175bb38 100644 --- a/docs-site/src/content/docs/tr/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/tr/reference/cli/lifecycle.md @@ -461,7 +461,7 @@ simgeyi kontrol eder; proxy'yi kontrol etmek için menüsünü kullanın. ### `ocx gui` Çalışmıyorsa proxy'yi otomatik olarak başlatarak `http://localhost:` -adresindeki [web kontrol panelini](/tr/guides/web-dashboard/) açın. +adresindeki [web kontrol panelini](/tr/guides/web-dashboard/) açın; hub'da yönetim ingress'i etkinse `http://127.0.0.1:` adresini açar. ## Güncelleme diff --git a/docs-site/src/content/docs/zh-cn/guides/web-dashboard.md b/docs-site/src/content/docs/zh-cn/guides/web-dashboard.md index fe3c9f1f22..5482c0a89c 100644 --- a/docs-site/src/content/docs/zh-cn/guides/web-dashboard.md +++ b/docs-site/src/content/docs/zh-cn/guides/web-dashboard.md @@ -12,7 +12,7 @@ opencodex 内置了一个由代理提供服务的本地 web 仪表盘(`gui/` ocx gui ``` -该命令会在浏览器中打开 `http://localhost:`;如果代理尚未运行,会先自动启动。开发时也可 +该命令会在浏览器中打开 `http://localhost:`;在启用了管理 ingress 的 hub 上则打开 `http://127.0.0.1:<管理端口>`;如果代理尚未运行,会先自动启动。开发时也可 让 GUI dev server 单独连接到正在运行的代理: ```bash diff --git a/docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md b/docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md index ff209deb28..39787e18f0 100644 --- a/docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md @@ -258,7 +258,7 @@ ocx codex-shim uninstall ### `ocx gui` -在 `http://localhost:` 打开 [web dashboard](/guides/web-dashboard/),如果代理未运行则会自动启动。 +在 `http://localhost:` 打开 [web dashboard](/guides/web-dashboard/),如果代理未运行则会自动启动。在启用了管理 ingress 的 hub 上,打开的是 `http://127.0.0.1:<管理端口>`。 ## 更新 diff --git a/docs-site/src/content/docs/zh-tw/guides/web-dashboard.md b/docs-site/src/content/docs/zh-tw/guides/web-dashboard.md index 76e7fcecb9..037d092c9b 100644 --- a/docs-site/src/content/docs/zh-tw/guides/web-dashboard.md +++ b/docs-site/src/content/docs/zh-tw/guides/web-dashboard.md @@ -12,7 +12,7 @@ opencodex 內建了一個由代理提供服務的本機 web 儀表板(`gui/` ocx gui ``` -該命令會在瀏覽器中開啟 `http://localhost:`;如果代理尚未執行,會先自動啟動。開發時也可 +該命令會在瀏覽器中開啟 `http://localhost:`;在啟用管理 ingress 的 hub 上則開啟 `http://127.0.0.1:<管理埠>`;如果代理尚未執行,會先自動啟動。開發時也可 讓 GUI dev server 單獨連線到正在執行的代理: ```bash diff --git a/docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md b/docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md index 1771936b0b..02421b11bd 100644 --- a/docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md @@ -243,7 +243,7 @@ ocx codex-shim uninstall ### `ocx gui` -在 `http://localhost:` 開啟[網頁儀表板](/zh-tw/guides/web-dashboard/),若代理未執行則自動啟動它。 +在 `http://localhost:` 開啟[網頁儀表板](/zh-tw/guides/web-dashboard/),若代理未執行則自動啟動它。在啟用管理 ingress 的 hub 上,開啟的是 `http://127.0.0.1:<管理埠>`。 ## 更新 diff --git a/src/cli/dispatch.ts b/src/cli/dispatch.ts index 576bf96bb0..1f74ded2b7 100644 --- a/src/cli/dispatch.ts +++ b/src/cli/dispatch.ts @@ -70,7 +70,7 @@ export function selectDefaultGuiUrl( probeHostname: (hostname: string | undefined) => string, ): string { const ingress = config.runtimeRole === "hub" ? config.hub?.managementIngress : undefined; - if (ingress?.enabled) return `http://localhost:${ingress.port}`; + if (ingress?.enabled) return `http://127.0.0.1:${ingress.port}`; const guiHost = probeHostname(live?.hostname ?? config.hostname); const hostname = guiHost === "127.0.0.1" ? "localhost" : guiHost; diff --git a/structure/clients/claude-desktop.md b/structure/clients/claude-desktop.md index 00a0b78dbe..c686e260a0 100644 --- a/structure/clients/claude-desktop.md +++ b/structure/clients/claude-desktop.md @@ -10,6 +10,8 @@ Shared parsing and streaming follow the [request-copy](../transports/byte-accoun Claude-only connections keep their existing non-failing readiness policy; displayed catalog reasons follow the [terminal rendering contract](../runtime.md#cli-readiness-diagnostics) whether they surface at connect time or on a later refresh. +The hub-side CLI dashboard uses the [management ingress address](../runtime.md#hub-management-dashboard-address); this does not change connected Desktop profile endpoints. + ## Connected Claude Desktop profiles Connected `ocx claude desktop apply` reads the hub's Desktop snapshot and writes the hub origin diff --git a/structure/config.md b/structure/config.md index ac643d3c7f..60501fe138 100644 --- a/structure/config.md +++ b/structure/config.md @@ -5,6 +5,8 @@ is scoped to canonical ChatGPT Responses forwarding; other source-area behavior Connected-client catalog diagnostics use the [terminal rendering contract](runtime.md#cli-readiness-diagnostics) on the first connection and on every `ocx sync` refresh; stored catalog values are unchanged. +Hub management ingress also selects the [local dashboard address](runtime.md#hub-management-dashboard-address) using its configured port. + ## Config surface ### OpenCodex home and live process state diff --git a/structure/gui-and-management-api.md b/structure/gui-and-management-api.md index c445858e6b..0496735405 100644 --- a/structure/gui-and-management-api.md +++ b/structure/gui-and-management-api.md @@ -5,8 +5,8 @@ is scoped to canonical ChatGPT Responses forwarding; other source-area behavior ## Dashboard serving -The bundled React dashboard is built into `gui/dist` and served by the same Bun proxy. `ocx gui` -starts the proxy when needed and opens `http://localhost:`. +The bundled React dashboard is built into `gui/dist` and served by the same Bun proxy. `ocx gui` starts +the proxy when needed and opens `http://localhost:`, or `http://127.0.0.1:` when `hub.managementIngress.enabled` is true — see [the hub management dashboard address](runtime.md#hub-management-dashboard-address). All ordinary HTTP responses (excluding successful WebSocket upgrades) include `X-Frame-Options: DENY` and `Content-Security-Policy: frame-ancestors 'none'`. This prevents another page from framing the local diff --git a/structure/ops/docs-and-release.md b/structure/ops/docs-and-release.md index 2789f3bd11..0fc71bd084 100644 --- a/structure/ops/docs-and-release.md +++ b/structure/ops/docs-and-release.md @@ -7,6 +7,8 @@ Shared parsing and streaming follow the [request-copy](../transports/byte-accoun Human-readable connect and sync-refresh diagnostics follow the [terminal rendering contract](../runtime.md#cli-readiness-diagnostics), with regression coverage for both paths in `tests/cli/cli-connect-readiness.test.ts`. +The CLI default dashboard address follows the [management ingress bind](../runtime.md#hub-management-dashboard-address), covered by `tests/cli/cli-dispatch.test.ts`. + ## Public docs The public documentation site lives in `docs-site/` and is built with Astro + Starlight. English is diff --git a/structure/runtime.md b/structure/runtime.md index 3287baba40..0e319fdc3c 100644 --- a/structure/runtime.md +++ b/structure/runtime.md @@ -13,6 +13,10 @@ Shared parsing and streaming follow the [request-copy](transports/byte-accountin Catalog-derived reasoning-level diagnostics are escaped only at the human-output boundary, which `src/cli/runtime-api.ts` owns alongside the human/JSON print split. Every CLI path that prints a hub-supplied catalog value renders it there: the first-time refusal in `src/cli/connect.ts` and the connected `ocx sync` refusal in `src/cli/dispatch.ts`. C0/C1 controls, DEL, and Unicode line/paragraph separators print as visible hexadecimal escapes; structured status retains the exact reason, and a rendered failure keeps the domain error as its `cause`. The ready/unverified/incompatible classification and exit policy are unchanged. +## Hub management dashboard address + +When hub management ingress is enabled, `src/cli/dispatch.ts` opens the dashboard on the literal IPv4 loopback address and configured ingress port, matching the listener in `src/server/index.ts`. Other dashboard address selection is unchanged. + ## Entrypoints | Path | Responsibility | diff --git a/tests/cli/cli-dispatch.test.ts b/tests/cli/cli-dispatch.test.ts index 970f8f5bd6..7ffec5adc6 100644 --- a/tests/cli/cli-dispatch.test.ts +++ b/tests/cli/cli-dispatch.test.ts @@ -657,7 +657,7 @@ describe("GUI command delegation", () => { defaultProvider: "openai", }; - test("opens the loopback management ingress from the hub", () => { + test("opens the hub management ingress on its literal IPv4 loopback bind", () => { const hubConfig = { port: 10100, hostname: "100.76.170.81", @@ -670,7 +670,7 @@ describe("GUI command delegation", () => { const live = { hostname: "100.76.170.81", port: 10100 }; expect(selectDefaultGuiUrl(hubConfig, live, hostname => hostname ?? "127.0.0.1")) - .toBe("http://localhost:10102"); + .toBe("http://127.0.0.1:10102"); const withoutIngress = { ...hubConfig, hub: { managementPublicOrigin: "https://hub.example.test" } }; expect(selectDefaultGuiUrl(withoutIngress, live, hostname => hostname ?? "127.0.0.1"))