Closes #261 ## Summary - improve startup remote URL selection when the server binds to `0.0.0.0` - print additional reachable remote URLs instead of advertising only the first external address - add targeted tests for address ordering and advertisability behavior ## Problem When CodeNomad was started with `--host 0.0.0.0`, the CLI chose the first external IPv4 address it discovered and displayed only that one as the remote URL. On Windows machines with WSL, Hyper-V, Docker, or other virtual adapters, that often surfaced a virtual `172.x.x.x` address even though a more useful LAN address such as `192.168.x.x` was also reachable and usable from other devices. That made remote access look broken or confusing even though the server itself was accessible. ## What changed - reuse the resolved network-address list for both: - primary remote URL selection - startup logging of additional reachable URLs - choose the primary remote URL from the **advertisable** external addresses instead of any external address - print `Other Accessible URLs` when multiple useful remote URLs are available - avoid hard-coding a preference like `192.168 > 10 > 172` - suppress link-local `169.254.*` addresses from user-facing advertised URLs - add tests covering: - stable ordering across RFC1918 address ranges - link-local addresses being non-advertisable - link-local-first discovery not stealing the primary LAN URL ## Why this approach This keeps address derivation in the network-address resolver layer and limits `index.ts` to startup wiring and presentation. It also fixes the misleading terminal output without redesigning binding behavior, TLS behavior, or the server API contract. ## Validation - `npm run typecheck --workspace @neuralnomads/codenomad` - `npx tsx --test '.\\src\\server\\__tests__\\network-addresses.test.ts'` ## Notes - this change is intentionally focused on selection and presentation of reachable addresses - it does not attempt a broader virtual-adapter classification policy beyond suppressing clearly low-value link-local addresses in user-facing output --------- Co-authored-by: Shantur Rathore <i@shantur.com>
54 lines
4.1 KiB
TypeScript
54 lines
4.1 KiB
TypeScript
export const remoteAccessMessages = {
|
|
"remoteAccess.eyebrow": "リモート引き継ぎ",
|
|
"remoteAccess.title": "CodeNomad にリモート接続",
|
|
"remoteAccess.subtitle": "別のデバイスから CodeNomad を開くには、以下のアドレスを使用してください。",
|
|
"remoteAccess.close": "リモートアクセスを閉じる",
|
|
"remoteAccess.refresh": "更新",
|
|
|
|
"remoteAccess.sections.listeningMode.label": "リッスンモード",
|
|
"remoteAccess.sections.listeningMode.help": "全インターフェースにバインドするか localhost のみにするかで、リモート引き継ぎを許可/制限します。",
|
|
"remoteAccess.toggle.on": "オン",
|
|
"remoteAccess.toggle.off": "オフ",
|
|
"remoteAccess.toggle.title": "他の IP からの接続を許可",
|
|
"remoteAccess.toggle.caption.all": "0.0.0.0 にバインド",
|
|
"remoteAccess.toggle.caption.local": "127.0.0.1 にバインド",
|
|
"remoteAccess.toggle.note": "変更には再起動が必要で、すべての稼働中インスタンスが一時的に停止します。サーバー再起動後に以下のアドレスを共有してください。",
|
|
"remoteAccess.listeningMode.restartConfirm.message": "リッスンモードを適用するため再起動しますか?実行中のインスタンスはすべて停止します。",
|
|
"remoteAccess.listeningMode.restartConfirm.title.all": "他のデバイスに公開",
|
|
"remoteAccess.listeningMode.restartConfirm.title.local": "このデバイスに限定",
|
|
"remoteAccess.listeningMode.restartConfirm.confirmLabel": "今すぐ再起動",
|
|
"remoteAccess.listeningMode.restartConfirm.cancelLabel": "キャンセル",
|
|
"remoteAccess.restart.errorManual": "自動で再起動できませんでした。変更を適用するにはアプリを再起動してください。",
|
|
|
|
"remoteAccess.sections.serverPassword.label": "サーバーパスワード",
|
|
"remoteAccess.sections.serverPassword.help": "リモート引き継ぎにはパスワードが必要です。覚えやすいものを設定して他のデバイスからのログインを有効にします。",
|
|
"remoteAccess.authStatus.unavailable": "認証状態を取得できません。",
|
|
"remoteAccess.username": "ユーザー名: {username}",
|
|
"remoteAccess.password.status.set": "リモートアクセス用のパスワードが設定されています。",
|
|
"remoteAccess.password.status.unset": "まだ覚えやすいパスワードが設定されていません。設定してリモート引き継ぎログインを有効にしてください。",
|
|
"remoteAccess.password.actions.cancel": "キャンセル",
|
|
"remoteAccess.password.actions.change": "パスワードを変更",
|
|
"remoteAccess.password.actions.set": "パスワードを設定",
|
|
"remoteAccess.password.form.newPassword": "新しいパスワード",
|
|
"remoteAccess.password.form.confirmPassword": "パスワードの確認",
|
|
"remoteAccess.password.form.placeholder": "8 文字以上",
|
|
"remoteAccess.password.error.tooShort": "パスワードは 8 文字以上である必要があります。",
|
|
"remoteAccess.password.error.mismatch": "パスワードが一致しません。",
|
|
"remoteAccess.password.save.saving": "保存中…",
|
|
"remoteAccess.password.save.label": "パスワードを保存",
|
|
|
|
"remoteAccess.sections.addresses.label": "到達可能なアドレス",
|
|
"remoteAccess.sections.addresses.help": "別の端末から起動またはスキャンして操作を引き継ぎます。",
|
|
"remoteAccess.addresses.loading": "アドレスを読み込み中…",
|
|
"remoteAccess.addresses.none": "まだ利用可能なアドレスがありません。",
|
|
"remoteAccess.addresses.actions.showOther": "他の {count} 件のアドレスを表示",
|
|
"remoteAccess.addresses.actions.hideOther": "他のアドレスを隠す",
|
|
"remoteAccess.address.scope.network": "ネットワーク",
|
|
"remoteAccess.address.scope.loopback": "ループバック",
|
|
"remoteAccess.address.scope.internal": "内部",
|
|
"remoteAccess.address.open": "開く",
|
|
"remoteAccess.address.showQr": "QR を表示",
|
|
"remoteAccess.address.hideQr": "QR を非表示",
|
|
"remoteAccess.address.qrAlt": "{url} の QR",
|
|
} as const
|