# Proxy Bridge — Live-State Baseline Captured 2026-09-23 before restructuring work (canonical repo = ~/gists/scripts/proxy, deploy target = /opt/proxy-bridge). All values observed, none invented. ## Service - systemd user service: `proxy-bridge.service`, state **active** - Unit file: `~/.config/systemd/user/proxy-bridge.service` - ExecStart: `/home/tke/.nvm/versions/node/v20.20.2/bin/node /opt/proxy-bridge/bridge.js` - Restart=on-failure, RestartSec=5, WantedBy=default.target - Last service start: 2026-09-22 13:24 (PID 4638), prior start 2026-09-16 16:05 (after the HTTPS-fix commit d8b9db2) ## Port → profile map (from startup log lines, 2026-09-22 boot) | Port | Profile | Type | |-------|-------------|----------| | 8888 | dynamic | special | | 8889 | internet | builtin | | 8890 | direct | builtin | | 8891 | off | builtin | | 8892 | proxy-inet | PAC | | 8893 | proxy-tke | PAC | | 8894 | proxy-wan | PAC | ss confirms 8888-8894 all listening on 127.0.0.1. Map shifts if PAC files in `~/.mozilla/*.pac` are added/removed — re-derive from startup lines on every restart. ## Live config files in /opt/proxy-bridge (runtime, not committed there — profile.json is the only dirty file) - config.json: `{enabled: true, host: "proxy-inet.certbw.org", port: "8080"}` - profile.json: `{profile: "proxy-tke"}` (dirty in /opt git — runtime state, fs-watched) - user.json: `{username: ""}` — password is NOT here, it's in the keyring - overrides.json: 5 rules (turtle.ktf.ninja→internet, ai.int.auf.bundeswehr.de→proxy-wan, api.anthropic.com→off, vault.lockedshields.de→internet, irt-docker.csocbw.org→direct) - remotes.json: 1 entry (wanbw → proxy-wan PAC URL) ## Code divergence (the reason for Task 1) - /opt bridge.js (deployed, 19,018 B, HEAD d8b9db2): HAS PAC `HTTPS host:port` support — `const tls = require('tls')`, HTTPS branch in parseProxyConfig, TLS-wrap around CONNECT. Fixes 2026-09-16 502-on-PAC-routes (proxy-inet:8081). - gists bridge.js (dev, 17,999 B, uncommitted +59/-10): LACKS the HTTPS fix; HAS new socket-lifecycle hardening (fragmented CONNECT header buffering, head-forward on PROXY, close/error handling, keepalive/nodelay, truncated-response propagation, large-body streaming). - Live journal confirms active use of the HTTPS path: `connect port=8888 profile="dynamic" ... upstream="HTTPS proxy-inet.certbw.org:8081"`. Deploying the unmerged gists copy would regress this immediately. ## Known bug in the uncommitted gists copy DIRECT-mode CONNECT establishes the tunnel twice: shared `onUpstreamData` else-branch (~lines 415-422) AND a DIRECT-only `'connect'` listener (~lines 427-435) both write `200 Connection Established` and call `pipe()`. `connected` flag prevents double-execution, but the logic races and head-forwarding differs between paths. Task 1 fixes this with a single owner. ## Credential handling today (pre-Task-2) - Username: user.json; password: keyring via `secret-tool lookup service proxy-bridge account ` — never stored in JSON. - `refreshAuth()` runs once at startup; AUTH_HEADER cached for process life. - 407 responses pass through unexamined; no backoff, no invalidation, no re-verification, no missing-cred guard beyond `if (AUTH_HEADER)`. - Lockout risk: if the keyring password expires, every PROXY/HTTPS request retries the stale credential indefinitely until manual intervention. ## Environment - Node /opt runtime: v20.20.2 via nvm; `node --test` works against the gists copy (6/6 tests pass as of baseline). - No outbound internet from this sandbox; all tests must use local stub servers (net/http/tls on 127.0.0.1). - Legacy scripts present in gists scripts/proxy/: `install_proxy.sh`, `update_apt_proxy.sh`, `update_bashrc_proxy.sh`, `update_service_proxy.sh`, `get_proxy.sh` — all embed username+password into apt config, bashrc exports (~/.http_proxy), snap and systemd drop-ins. To be retired by Task 4/5.