# DC AMD Proxy Полный воспроизводимый install/recovery/migration-контракт находится в [`OPERATIONS.md`](./OPERATIONS.md). Этот README фиксирует краткую runtime-модель; операционные изменения должны одновременно обновлять runbook. `dc-amd-proxy` is the dedicated, controllable boundary between NODE.DC Map Gateway and the adjacent AMD VPN machine. It is deliberately independent from the historic `proxy-contur` service. After pairing it has no direct Cesium egress: every approved Cesium/Bing request is tunnelled through the authenticated AMD connector (`172.22.0.183:8791`). The NAS always addresses this stable LAN endpoint; the AMD host alone owns its changing VPN exit. This is a single restricted transport path, not a per-tile relay chain. The NAS keeps a small, bounded pool of HTTP/1.1 TLS tunnels per approved upstream host, so adjacent tile requests reuse the existing `NAS → AMD → VPN` channel. The pool is limited to eight active and four idle sockets per host by default; it cannot become a general-purpose proxy or consume an unbounded amount of the workstation's network resources. `/status` exposes only safe operational counters: active/idle/queued sockets per approved origin, the retained peak queue, logical/in-flight/terminal requests, tunnels opened, reused sockets, bounded retries, complete and partial response bytes, separate queue/CONNECT+TLS/TTFB/retry/total timing, body-stream failures, client aborts, and the last short error code. Every accepted egress request is accounted exactly once even when the browser disconnects while it is queued, connecting, following a redirect, waiting for headers, or retrying. The status never contains an Ion token, connector token, full URL, or query parameters. An upstream `Authorization` header is retained only across same-origin redirects. A redirect from the Cesium API origin to an assets or Bing origin is followed only after that header is removed, so an API/master bearer cannot cross provider credential boundaries. Only an idempotent `GET`/`HEAD` that loses an already reused keep-alive socket is retried, once. The failed reused-socket attempt and the terminal retry attempt are logged separately with numeric transport timings and no URL or credential fields. A response body that makes no progress for 30 seconds is terminated and counted as a stream failure, so a stalled VPN connection cannot occupy one of the eight per-origin sockets forever. These limits are local to Cesium egress and do not modify routing or connectivity of the AMD workstation. ## Pairing and operational state The active service has an explicitly narrow first-pair contract: - `POST /api/pair` accepts exactly one connector access token and only from the configured AMD LAN source address; - the AMD operator invokes a supplied local script; it reads the token inside the AMD installation and sends it without printing it or putting it in chat; - the NAS writes the paired value only to its private runtime directory, never to `.env`, SMB inbox, a deploy artifact, browser code, or logs; - the Map Gateway fetch contract (`/proxy/cesium/fetch`) remains private to the NAS LAN address and still requires the runner-synchronised map egress token; - the service follows only the fixed Cesium Ion/Bing host allowlist and cannot fall back to direct NAS Internet egress. ## Deployment order 1. Deploy this service and confirm `/healthz` reports `awaiting_pair`. Map Gateway remains on its existing egress during this step. 2. On AMD, run the supplied one-time pairing script. It sends the locally-held connector secret directly to the NAS and reports no secret value. 3. Verify the private Map Gateway request through this service. 4. Apply the separate, minimal Map Gateway switch patch. It changes only its private egress hostname from the historical service to `dc-amd-proxy`. The initial 001 deployment was intentionally inert. It is superseded by this active configuration; it did not alter NAS routing, the NAS VPN/Tailscale configuration, or the Windows workstation's VPN configuration. ## Why host networking is narrow here Synology's Docker published-port proxy replaces the caller address before it reaches a bridged container. That makes a strict one-time AMD source-address check impossible. This service therefore uses the host network namespace but binds its own HTTP listener only to `172.22.0.222:8790`; it is not bound to all NAS interfaces. No host route, VPN, DNS, Tailscale setting or firewall rule is changed. The forwarding code still has one hard-coded outbound path only: the authenticated AMD connector.