AGENTS.md@packages/client/src/components/Gateway · git:20260808.f219f4e · 2026-08-08 · sha256 fd9d846fe3cd70c2
AGENTS.md@packages/client/src/components/Gateway git:20260808.f219f4eA
Immutable. This exact content is served forever at /api/v1/blob/fd9d846fe3cd70c2.
# DOX — packages/client/src/components/Gateway
Reusable Gateway (tunnel-providers) UI sections + two hosts. User-facing label
"Gateway"; the wire keeps `tunnel`. Composed by the Gateway settings page and
the tabbed Gateway dialog. See change: add-tunnel-providers.
| File | Purpose |
|------|---------|
| `GatewayDialog.tsx` | Tabbed **Gateway** dialog (task 9.3): Setup / Access & QR (default) / Security. Reads `tunnel.provider`/`mode` via `GET /api/config`, persists via `PUT /api/config` (`tunnel` deep-merged). Composes the four sections; Security tab cross-refs the Security page. Exports `GatewayDialog`. `gateway-forget-reserved` button calls `disconnectTunnel({forget:true})` (releases v2 reserved name). See change: support-zrok-v2. |
| `GatewayEndpoints.tsx` | "Accessible at" tagged endpoint list (kind pill + TLS/no-TLS badge + copy) + **Add HTTPS URL** control (task 6.4). Add path: re-read config → `appendPublicBaseUrl` → PUT the TOP-LEVEL `publicBaseUrls` (seeded from legacy `pairing.publicBaseUrls` on first write) → refetch. See change: config-override-oauth-redirect-base. Client https/wss gate is UX-only. Exports `GatewayEndpoints`. |
| `GatewayPage.tsx` | **Gateway** settings page (task 9.2) under Network nav. Full-width host: provider/mode, connect-a-device (QR first), gateway URLs (`GatewayUrlManager`), accessible-at, setup guide, Security cross-ref. Self-manages provider/mode via GET/PUT config. Exports `GatewayPage`. |
| `GatewayPairQR.tsx` | Connect-a-device — **one QR at a time via a network selector** (radio group over `pairingEps ++ linkEps`). Default = public TLS pairing endpoint (`pairingEps[0]`), else first link (`linkEps[0]`). Selected drives one `QrCanvas`: pairing → camera-scannable `https://<selected-tls>/pair#pi:pair:v1.<b64>` deep link (`encodePairingQrUrl` from `lib/pairing-qr.ts`, landing base = the SELECTED endpoint's url; payload in FRAGMENT, one-time code out of logs); link → bare `selected.url`. Copy-string stays bare `pi:pair:v1.…` (`encodePayloadString`) for Electron paste. Payload TLS-only `{v,id,code,urls[]}` re-guarded by `guardPairingUrls`. Context panel swaps by `isPairingEligible(selected)`: pairing controls (copy-string, expiry, fp, confirm input, Approve D12) vs. link note. Selector is `role=radiogroup` + per-row `role=radio`/`aria-checked`, roving tabIndex, arrow-key nav, Space/Enter commit; ●/○ non-colour cue. `QrCanvas` exposes `data-qr-text` for tests. Exports `GatewayPairQR`. See change: add-gateway-qr-network-selector. See change: make-pairing-qr-camera-scannable. |
| `GatewayProviderSection.tsx` | Provider + mode segmented controls. Mode gated by the provider matrix (`supportsMode`); switching provider auto-selects a valid mode. Exports `GatewayProviderSection`. |
| `GatewaySetupGuide.tsx` | Per-provider setup steps (D3): install=copy-paste; auth-token/activate=field+button → `runEnrollStep` (`POST /api/tunnel/enroll`, validated param); browser-auth/external=link. Also renders `GatewayUrlManager` so the first run gets the add-gateway action (same component as the Gateway page). Exports `GatewaySetupGuide`. |
| `GatewayUrlManager.tsx` | "Add a gateway URL" action (D12/D13) + per-gateway status row. One shared component rendered by BOTH `GatewayPage` and `GatewaySetupGuide`, so first-run and steady state cannot drift. Add = ONE `PUT /api/config` from `buildGatewayAddPatch`; states the scheme rules inline (`http://` → OAuth + QR checkboxes disabled with a reason, trusted network required, CIDR prefilled `/32` via `suggestTrustEntries`). Row shows the computed status (`data-status` ok/incomplete/conflicting/ineligible) with `Fix` (delta-only reconcile) and `Remove` (confirmation lists every reverted field). Exports `GatewayUrlManager`. See change: config-override-oauth-redirect-base. |