#22347: Feature request: gateway.clientUrl config to decouple client URL
gateway
size: S
Cluster:
Gateway Resilience and Configuration
## What changed
- Add optional `gateway.clientUrl` to config schema (`types`/`zod`) and UI metadata (`help`/`labels`/`placeholders`).
- Use `gateway.clientUrl` for pairing setup URL generation when present.
- Use `gateway.clientUrl` in local CLI/gateway connection resolution before loopback fallback.
- Keep existing remote-mode precedence and fallback order for other URL sources unchanged.
- Add/extend tests to assert configured `gateway.clientUrl` is used and surfaced via source metadata.
## Why this fixes the issue
It decouples listener binding from client connect endpoint selection. This lets local setups use a stable client-facing URL (including loopback or explicit overrides) without altering bind behaviour, avoiding brittle assumptions when the listener is non-loopback.
## Tests run
- `pnpm vitest run --config vitest.config.ts src/pairing/setup-code.test.ts src/gateway/call.test.ts src/config/schema.hints.test.ts`
- `pnpm test src/pairing/setup-code.test.ts src/gateway/call.test.ts src/config/schema.hints.test.ts`
## Edge cases and notes
- `gateway.clientUrl` is validated through existing URL normalization/validation.
- Blank/invalid values are rejected with clear error in pairing flow; otherwise local-resolution behavior follows the existing fallback order.
- Existing loopback exposure/bind reporting is preserved for source/bind detail metadata.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR adds `gateway.clientUrl` config to decouple the client connection URL from the gateway listener bind address. When configured, `gateway.clientUrl` overrides the default loopback URL for local gateway connections in both CLI/gateway calls and pairing URL generation.
**Key Changes:**
- Added `gateway.clientUrl` field to config schema, types, help text, labels, and hints
- Modified `buildGatewayConnectionDetails` in `src/gateway/call.ts` to prefer `clientUrl` over loopback when connecting locally
- Modified `resolveGatewayUrl` in `src/pairing/setup-code.ts` to use `clientUrl` before falling back to bind-based resolution
- Added comprehensive test coverage for the new configuration option
- Security validation via `isSecureWebSocketUrl` ensures `gateway.clientUrl` is checked for plaintext ws:// to non-loopback addresses
**Implementation Quality:**
- Clean implementation that fits well with existing precedence logic
- Proper fallback behavior maintained (empty/invalid values fallback to default resolution)
- Security controls remain in place - the configured URL is validated by existing security checks
- Test coverage is thorough with tests for both gateway calls and pairing flows
<h3>Confidence Score: 5/5</h3>
- Safe to merge - well-tested configuration feature with proper security validation
- Clean implementation with comprehensive test coverage, proper error handling, and security validation. The change follows existing patterns, includes appropriate fallback behavior, and doesn't introduce any security risks.
- No files require special attention
<sub>Last reviewed commit: 3c43ef8</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#19026: fix(gateway): use loopback for local CLI-to-gateway connections
by Phineas1500 · 2026-02-17
78.6%
#19088: fix(gateway): allow startup with unset mode and fix pairing for local…
by mdanassaif · 2026-02-17
78.5%
#22056: fix(gateway): use loopback for self-connections regardless of bind ...
by usedhonda · 2026-02-20
78.0%
#22381: Security/Gateway: block cross-origin silent auto-pairing in auth mo...
by bmendonca3 · 2026-02-21
77.5%
#21697: fix(gateway): unblock local spawn pairing and gated private-LAN ws
by rjuanluis · 2026-02-20
77.5%
#21326: Security/UI: harden Control UI gatewayUrl URL overrides
by bmendonca3 · 2026-02-19
77.5%
#21265: Security/Pairing: reject insecure non-loopback ws setup URLs
by bmendonca3 · 2026-02-19
77.3%
#22365: fix(gateway): auto-approve loopback scope upgrades
by AIflow-Labs · 2026-02-21
77.1%
#22712: fix(gateway): auto-approve all device pairing for localhost connect...
by NewdlDewdl · 2026-02-21
77.1%
#19437: Gateway: respect custom bind host for local health/RPC target resol...
by frudas24 · 2026-02-17
77.1%