claude-use 4.5.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1733,15 +1733,213 @@ function recoveryDiagnostics(recovery, identity) {
1733
1733
  ];
1734
1734
  }
1735
1735
 
1736
- // src/headroom/mitm.ts
1736
+ // src/frontdoor/connect.ts
1737
1737
  import * as fs from "node:fs";
1738
1738
  import * as http from "node:http";
1739
1739
  import * as https from "node:https";
1740
1740
  import * as net from "node:net";
1741
1741
  import * as tls from "node:tls";
1742
1742
  import forge from "node-forge";
1743
- var MITM_INTERCEPT_HOST = "api.anthropic.com";
1744
- var HEADROOM_SERVED_PATH_PREFIX = "/v1/";
1743
+
1744
+ // src/frontdoor/capability.ts
1745
+ var CONNECT_PROXY_REALM = "claude-use front door";
1746
+ var BASIC_SCHEME = "basic";
1747
+ function capabilityFromProxyAuthorization(value) {
1748
+ const trimmed = value.trim();
1749
+ const space = trimmed.indexOf(" ");
1750
+ if (space === -1 || trimmed.slice(0, space).toLowerCase() !== BASIC_SCHEME) {
1751
+ return void 0;
1752
+ }
1753
+ const userPass = Buffer.from(trimmed.slice(space + 1).trim(), "base64").toString("utf8");
1754
+ const colon = userPass.indexOf(":");
1755
+ if (colon === -1) {
1756
+ return void 0;
1757
+ }
1758
+ const password = userPass.slice(colon + 1);
1759
+ return password === "" ? void 0 : password;
1760
+ }
1761
+
1762
+ // src/frontdoor/state.ts
1763
+ import path5 from "node:path";
1764
+ import { z as z3 } from "zod";
1765
+ var FrontDoorSessionSchema = z3.strictObject({ pid: z3.number().int().positive(), startedAt: z3.number(), token: z3.string().min(1) });
1766
+ var FrontDoorStateSchema = z3.strictObject({
1767
+ /** The supervisor process serving the front door. Alive means both listeners are up in that process. */
1768
+ supervisorPid: z3.number().int().positive().optional(),
1769
+ /** The loopback port the HTTPS provider listener serves on. Absent until the listener has bound and answered its health probe, so "port is set" is itself the ready signal a launcher polls for. */
1770
+ port: z3.number().int().positive().optional(),
1771
+ /**
1772
+ * The sticky port preference for the provider listener: kept across crashes, restarts and idle shutdowns so every provider session, whose base URL was frozen at launch, keeps finding the front door at the same address.
1773
+ */
1774
+ lastPort: z3.number().int().positive().optional(),
1775
+ /**
1776
+ * The loopback port the CONNECT surface listens on. Absent whenever no supervisor is serving it, so "connectPort is set" is the ready signal an OAuth launch polls for alongside `port`.
1777
+ */
1778
+ connectPort: z3.number().int().positive().optional(),
1779
+ /**
1780
+ * The sticky port preference for the CONNECT surface, the exact analogue of `lastPort` for the second listener: it survives every shutdown, because every OAuth session's environment was frozen at launch with HTTPS_PROXY pointing at this address and a restart that moves strands them.
1781
+ */
1782
+ lastConnectPort: z3.number().int().positive().optional(),
1783
+ /**
1784
+ * The loopback port the direct listener serves on: the listener a headroom hop tells the daemon to forward routed traffic back to. Sticky like the others, because headroom's allowlist admits its exact origin and an ephemeral port would invalidate the allowlist on every restart.
1785
+ */
1786
+ directPort: z3.number().int().positive().optional(),
1787
+ /** The sticky port preference for the direct listener, for the reason `directPort` gives. */
1788
+ lastDirectPort: z3.number().int().positive().optional(),
1789
+ /** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
1790
+ lastError: z3.string().optional()
1791
+ });
1792
+ function readFrontDoorState(fs2, stateFile) {
1793
+ let raw;
1794
+ try {
1795
+ raw = fs2.readFileUtf8(stateFile);
1796
+ } catch {
1797
+ return void 0;
1798
+ }
1799
+ if (raw === void 0 || raw.trim() === "") {
1800
+ return void 0;
1801
+ }
1802
+ try {
1803
+ const parsed = FrontDoorStateSchema.safeParse(JSON.parse(raw));
1804
+ return parsed.success ? parsed.data : void 0;
1805
+ } catch {
1806
+ return void 0;
1807
+ }
1808
+ }
1809
+ function writeFrontDoorState(fs2, stateFile, state) {
1810
+ fs2.mkdirp(path5.dirname(stateFile));
1811
+ fs2.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
1812
+ `);
1813
+ }
1814
+ function frontDoorOrigin(state) {
1815
+ const port = state?.directPort ?? state?.lastDirectPort;
1816
+ return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
1817
+ }
1818
+ function writeFrontDoorSession(fs2, sessionsDir, session) {
1819
+ fs2.mkdirPrivate(sessionsDir);
1820
+ fs2.writeFilePrivate(path5.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
1821
+ `);
1822
+ }
1823
+ function listFrontDoorSessions(fs2, sessionsDir) {
1824
+ const sessions = [];
1825
+ for (const name of fs2.readdir(sessionsDir)) {
1826
+ if (!name.endsWith(".json")) {
1827
+ continue;
1828
+ }
1829
+ try {
1830
+ const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs2.readFileUtf8(path5.join(sessionsDir, name)) ?? ""));
1831
+ if (parsed.success) {
1832
+ sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
1833
+ }
1834
+ } catch {
1835
+ continue;
1836
+ }
1837
+ }
1838
+ return sessions.sort((a, b) => a.pid - b.pid);
1839
+ }
1840
+ function removeFrontDoorSession(fs2, sessionsDir, pid) {
1841
+ fs2.removeRecursive(path5.join(sessionsDir, `${String(pid)}.json`));
1842
+ }
1843
+ function pruneDeadFrontDoorSessions(fs2, sessionsDir, isRunning) {
1844
+ const removed = [];
1845
+ for (const session of listFrontDoorSessions(fs2, sessionsDir)) {
1846
+ if (!isRunning(session.pid)) {
1847
+ removeFrontDoorSession(fs2, sessionsDir, session.pid);
1848
+ removed.push(session.pid);
1849
+ }
1850
+ }
1851
+ return removed;
1852
+ }
1853
+
1854
+ // src/frontdoor/supervisor.ts
1855
+ var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
1856
+ var FRONTDOOR_POLL_MS = 1e3;
1857
+ var MS_PER_MINUTE = 6e4;
1858
+ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
1859
+ const { fs: fs2, paths } = ports;
1860
+ const previous = readFrontDoorState(fs2, paths.frontdoorStateFile);
1861
+ let lastPort = previous?.lastPort;
1862
+ let lastConnectPort = previous?.lastConnectPort;
1863
+ let lastDirectPort = previous?.lastDirectPort;
1864
+ const sticky = () => ({
1865
+ ...lastPort === void 0 ? {} : { lastPort },
1866
+ ...lastConnectPort === void 0 ? {} : { lastConnectPort },
1867
+ ...lastDirectPort === void 0 ? {} : { lastDirectPort }
1868
+ });
1869
+ const fail = (message) => {
1870
+ writeFrontDoorState(fs2, paths.frontdoorStateFile, { lastError: message, ...sticky() });
1871
+ fs2.removeRecursive(paths.frontdoorLockFile);
1872
+ ports.log(`claude-use frontdoor supervisor: ${message}`);
1873
+ return 1;
1874
+ };
1875
+ writeFrontDoorState(fs2, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
1876
+ const previousSticky = lastPort;
1877
+ let http2;
1878
+ try {
1879
+ http2 = await ports.startProviderListener(lastPort);
1880
+ } catch (error) {
1881
+ return fail(`could not start the provider listener: ${error instanceof Error ? error.message : String(error)}`);
1882
+ }
1883
+ if (previousSticky !== void 0 && http2.port !== previousSticky) {
1884
+ ports.log(`claude-use frontdoor supervisor: sticky port ${String(previousSticky)} was occupied; moving to ${String(http2.port)} (sessions launched against the old port are stale until they relaunch)`);
1885
+ }
1886
+ lastPort = http2.port;
1887
+ const previousStickyConnect = lastConnectPort;
1888
+ let connect2;
1889
+ try {
1890
+ connect2 = await ports.startConnectListener(lastConnectPort);
1891
+ } catch (error) {
1892
+ await http2.close();
1893
+ return fail(`could not start the CONNECT surface: ${error instanceof Error ? error.message : String(error)}`);
1894
+ }
1895
+ if (previousStickyConnect !== void 0 && connect2.port !== previousStickyConnect) {
1896
+ ports.log(`claude-use frontdoor supervisor: sticky CONNECT port ${String(previousStickyConnect)} was occupied; moving to ${String(connect2.port)} (OAuth sessions launched against the old port are stale until they relaunch)`);
1897
+ }
1898
+ lastConnectPort = connect2.port;
1899
+ const previousStickyDirect = lastDirectPort;
1900
+ let direct;
1901
+ try {
1902
+ direct = await ports.startDirectListener(lastDirectPort);
1903
+ } catch (error) {
1904
+ await connect2.close();
1905
+ await http2.close();
1906
+ return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
1907
+ }
1908
+ if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
1909
+ ports.log(`claude-use frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom must be restarted to admit the new address)`);
1910
+ }
1911
+ lastDirectPort = direct.port;
1912
+ writeFrontDoorState(fs2, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, port: http2.port, connectPort: connect2.port, directPort: direct.port, ...sticky() });
1913
+ fs2.removeRecursive(paths.frontdoorLockFile);
1914
+ ports.log(`claude-use frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http2.port)}, CONNECT surface on 127.0.0.1:${String(connect2.port)}`);
1915
+ let idleSince;
1916
+ let ticks = 0;
1917
+ for (; ; ) {
1918
+ if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
1919
+ return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
1920
+ }
1921
+ ticks += 1;
1922
+ pruneDeadFrontDoorSessions(fs2, paths.frontdoorSessionsDir, ports.isRunning);
1923
+ if (listFrontDoorSessions(fs2, paths.frontdoorSessionsDir).length === 0) {
1924
+ idleSince ??= ports.now();
1925
+ if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
1926
+ ports.log(`claude-use frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
1927
+ await direct.close();
1928
+ await connect2.close();
1929
+ await http2.close();
1930
+ writeFrontDoorState(fs2, paths.frontdoorStateFile, sticky());
1931
+ return 0;
1932
+ }
1933
+ } else {
1934
+ idleSince = void 0;
1935
+ }
1936
+ await ports.sleep(FRONTDOOR_POLL_MS);
1937
+ }
1938
+ }
1939
+
1940
+ // src/frontdoor/connect.ts
1941
+ var CONNECT_INTERCEPT_HOST = "api.anthropic.com";
1942
+ var ROUTED_PATH_PREFIX = "/v1/";
1745
1943
  var HTTPS_PORT = 443;
1746
1944
  var MAX_PORT = 65535;
1747
1945
  var SERIAL_NUMBER_BYTES = 16;
@@ -1751,9 +1949,22 @@ var CONNECT_LINE_TOKENS = 3;
1751
1949
  var HEAD_TERMINATOR = "\r\n\r\n";
1752
1950
  var MAX_CONNECT_HEAD_BYTES = 8192;
1753
1951
  var CONNECT_ESTABLISHED = "HTTP/1.1 200 Connection Established\r\n\r\n";
1952
+ var REFUSAL = {
1953
+ badRequest: "400 Bad Request",
1954
+ proxyAuthenticationRequired: "407 Proxy Authentication Required",
1955
+ requestTimeout: "408 Request Timeout",
1956
+ headTooLarge: "431 Request Header Fields Too Large",
1957
+ serviceUnavailable: "503 Service Unavailable"
1958
+ };
1959
+ var CONNECT_LIMITS = {
1960
+ headDeadlineMs: 1e4,
1961
+ maxPendingHeads: 64,
1962
+ maxTunnels: 1024,
1963
+ revalidateMs: FRONTDOOR_POLL_MS
1964
+ };
1754
1965
  var CA_VALIDITY_DAYS = 3650;
1755
1966
  var LEAF_VALIDITY_DAYS = 397;
1756
- var CA_SUBJECT_COMMON_NAME = "claude-use headroom CA";
1967
+ var CA_SUBJECT_COMMON_NAME = "claude-use front door CA";
1757
1968
  var MS_PER_DAY = 864e5;
1758
1969
  function parseConnectTarget(authority) {
1759
1970
  const colon = authority.lastIndexOf(":");
@@ -1771,8 +1982,8 @@ function parseConnectTarget(authority) {
1771
1982
  function isInterceptedHost(host, interceptHost) {
1772
1983
  return host === interceptHost;
1773
1984
  }
1774
- function servedByHeadroom(path6) {
1775
- return path6?.startsWith(HEADROOM_SERVED_PATH_PREFIX) === true;
1985
+ function servedByPipeline(path7) {
1986
+ return path7?.startsWith(ROUTED_PATH_PREFIX) === true;
1776
1987
  }
1777
1988
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
1778
1989
  "connection",
@@ -1820,7 +2031,13 @@ function generateCa(now) {
1820
2031
  cert.sign(keys.privateKey, forge.md.sha256.create());
1821
2032
  return { certPem: forge.pki.certificateToPem(cert), keyPem: forge.pki.privateKeyToPem(keys.privateKey) };
1822
2033
  }
1823
- function mintLeaf(ca, host, now) {
2034
+ var SAN_TYPE_DNS = 2;
2035
+ var SAN_TYPE_IP = 7;
2036
+ function mintLeaf(ca, names, now) {
2037
+ const [commonName] = names;
2038
+ if (commonName === void 0) {
2039
+ throw new Error("a leaf certificate needs at least one name");
2040
+ }
1824
2041
  const caCert = forge.pki.certificateFromPem(ca.certPem);
1825
2042
  const caKey = forge.pki.privateKeyFromPem(ca.keyPem);
1826
2043
  const keys = forge.pki.rsa.generateKeyPair({ bits: 2048 });
@@ -1829,13 +2046,13 @@ function mintLeaf(ca, host, now) {
1829
2046
  cert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(SERIAL_NUMBER_BYTES));
1830
2047
  cert.validity.notBefore = new Date(now.getTime() - MS_PER_DAY);
1831
2048
  cert.validity.notAfter = new Date(now.getTime() + LEAF_VALIDITY_DAYS * MS_PER_DAY);
1832
- cert.setSubject([{ name: "commonName", value: host }]);
2049
+ cert.setSubject([{ name: "commonName", value: commonName }]);
1833
2050
  cert.setIssuer(caCert.subject.attributes);
1834
2051
  cert.setExtensions([
1835
2052
  { name: "basicConstraints", cA: false, critical: true },
1836
2053
  { name: "keyUsage", digitalSignature: true, keyEncipherment: true, critical: true },
1837
2054
  { name: "extKeyUsage", serverAuth: true },
1838
- { name: "subjectAltName", altNames: [{ type: 2, value: host }] },
2055
+ { name: "subjectAltName", altNames: names.map((name) => net.isIP(name) === 0 ? { type: SAN_TYPE_DNS, value: name } : { type: SAN_TYPE_IP, ip: name }) },
1839
2056
  { name: "subjectKeyIdentifier" },
1840
2057
  { name: "authorityKeyIdentifier", keyLocatorFields: [] }
1841
2058
  ]);
@@ -1849,7 +2066,7 @@ function createLeafCache(ca, now) {
1849
2066
  if (existing !== void 0) {
1850
2067
  return existing;
1851
2068
  }
1852
- const minted = mintLeaf(ca, host, now());
2069
+ const minted = mintLeaf(ca, [host], now());
1853
2070
  cache.set(host, minted);
1854
2071
  return minted;
1855
2072
  };
@@ -1872,17 +2089,10 @@ function caParses(ca) {
1872
2089
  return false;
1873
2090
  }
1874
2091
  }
1875
- async function startMitmServer(config, effects, preferredPort) {
2092
+ async function startConnectServer(config, effects, preferredPort) {
1876
2093
  const handler = (request3, response) => {
1877
- if (servedByHeadroom(request3.url)) {
1878
- const daemonPort = config.headroomPort();
1879
- if (daemonPort === void 0) {
1880
- const body = "claude-use headroom: the daemon is restarting";
1881
- response.writeHead(HTTP_BAD_GATEWAY, { "content-type": "text/plain", "content-length": String(body.length) });
1882
- response.end(body);
1883
- return;
1884
- }
1885
- effects.forwardHttp({ host: "127.0.0.1", port: daemonPort, tls: false }, request3, response);
2094
+ if (servedByPipeline(request3.url)) {
2095
+ config.serveRouted(request3, response);
1886
2096
  return;
1887
2097
  }
1888
2098
  effects.forwardHttp(config.upstream, request3, response);
@@ -1891,50 +2101,153 @@ async function startMitmServer(config, effects, preferredPort) {
1891
2101
  const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(config.interceptHost), (secure) => {
1892
2102
  httpSession.serve(secure);
1893
2103
  });
2104
+ const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
1894
2105
  const listener = await effects.listenLoopback(preferredPort, (socket) => {
1895
- handleConnect(socket, config, effects, tlsAcceptor);
2106
+ handleConnect(socket, { config, effects, tlsAcceptor, ledger });
1896
2107
  });
1897
2108
  return {
1898
2109
  port: listener.port,
1899
2110
  close: async () => {
2111
+ ledger.close();
1900
2112
  await listener.close();
1901
2113
  tlsAcceptor.close();
1902
2114
  httpSession.close();
1903
2115
  }
1904
2116
  };
1905
2117
  }
1906
- function handleConnect(socket, config, effects, tlsAcceptor) {
2118
+ function createConnectionLedger(limits, isLiveCapability) {
2119
+ const pending = /* @__PURE__ */ new Map();
2120
+ const authenticated = /* @__PURE__ */ new Map();
2121
+ let tunnels = 0;
2122
+ const leavePending = (socket) => {
2123
+ const deadline = pending.get(socket);
2124
+ if (deadline !== void 0) {
2125
+ clearTimeout(deadline);
2126
+ pending.delete(socket);
2127
+ }
2128
+ };
2129
+ const revalidation = setInterval(() => {
2130
+ for (const [capability, sockets] of authenticated) {
2131
+ if (!isLiveCapability(capability)) {
2132
+ for (const socket of sockets) {
2133
+ socket.destroy();
2134
+ }
2135
+ }
2136
+ }
2137
+ }, limits.revalidateMs);
2138
+ revalidation.unref();
2139
+ return {
2140
+ accept: (socket) => {
2141
+ const [oldest] = pending.keys();
2142
+ if (pending.size >= limits.maxPendingHeads && oldest !== void 0) {
2143
+ leavePending(oldest);
2144
+ refuse(oldest, REFUSAL.requestTimeout);
2145
+ }
2146
+ pending.set(
2147
+ socket,
2148
+ setTimeout(() => {
2149
+ leavePending(socket);
2150
+ refuse(socket, REFUSAL.requestTimeout);
2151
+ }, limits.headDeadlineMs)
2152
+ );
2153
+ socket.once("close", () => {
2154
+ leavePending(socket);
2155
+ });
2156
+ },
2157
+ headReceived: leavePending,
2158
+ establish: (socket, capability) => {
2159
+ if (tunnels >= limits.maxTunnels) {
2160
+ return false;
2161
+ }
2162
+ tunnels += 1;
2163
+ const sockets = authenticated.get(capability) ?? /* @__PURE__ */ new Set();
2164
+ sockets.add(socket);
2165
+ authenticated.set(capability, sockets);
2166
+ socket.once("close", () => {
2167
+ tunnels -= 1;
2168
+ sockets.delete(socket);
2169
+ if (sockets.size === 0 && authenticated.get(capability) === sockets) {
2170
+ authenticated.delete(capability);
2171
+ }
2172
+ });
2173
+ return true;
2174
+ },
2175
+ close: () => {
2176
+ clearInterval(revalidation);
2177
+ for (const deadline of pending.values()) {
2178
+ clearTimeout(deadline);
2179
+ }
2180
+ pending.clear();
2181
+ }
2182
+ };
2183
+ }
2184
+ function refuse(socket, status, headers = []) {
2185
+ socket.removeAllListeners("data");
2186
+ socket.pause();
2187
+ if (socket.destroyed || socket.writableEnded) {
2188
+ return;
2189
+ }
2190
+ socket.end(`HTTP/1.1 ${status}\r
2191
+ ${headers.map((header) => `${header}\r
2192
+ `).join("")}content-length: 0\r
2193
+ connection: close\r
2194
+ \r
2195
+ `, () => {
2196
+ socket.destroy();
2197
+ });
2198
+ }
2199
+ function handleConnect(socket, context) {
2200
+ socket.on("error", () => {
2201
+ socket.destroy();
2202
+ });
2203
+ context.ledger.accept(socket);
1907
2204
  let buffer = Buffer.alloc(0);
1908
2205
  const onData = (chunk) => {
1909
2206
  buffer = Buffer.concat([buffer, chunk]);
1910
2207
  const headEnd = buffer.indexOf(HEAD_TERMINATOR);
2208
+ if (headEnd === -1 ? buffer.length > MAX_CONNECT_HEAD_BYTES : headEnd > MAX_CONNECT_HEAD_BYTES) {
2209
+ context.ledger.headReceived(socket);
2210
+ refuse(socket, REFUSAL.headTooLarge);
2211
+ return;
2212
+ }
1911
2213
  if (headEnd === -1) {
1912
- if (buffer.length > MAX_CONNECT_HEAD_BYTES) {
1913
- socket.removeListener("data", onData);
1914
- socket.pause();
1915
- socket.destroy();
1916
- }
1917
2214
  return;
1918
2215
  }
1919
2216
  socket.removeListener("data", onData);
1920
2217
  socket.pause();
2218
+ context.ledger.headReceived(socket);
1921
2219
  const head = buffer.subarray(0, headEnd).toString("utf8");
1922
2220
  socket.unshift(buffer.subarray(headEnd + HEAD_TERMINATOR.length));
1923
- routeConnect(socket, head, config, effects, tlsAcceptor);
2221
+ routeConnect(socket, head, context);
1924
2222
  };
1925
2223
  socket.on("data", onData);
1926
- socket.on("error", () => {
1927
- socket.destroy();
1928
- });
1929
2224
  }
1930
- function routeConnect(socket, head, config, effects, tlsAcceptor) {
2225
+ function proxyAuthorizationOf(head) {
2226
+ const values = head.split("\r\n").slice(1).flatMap((line) => {
2227
+ const colon = line.indexOf(":");
2228
+ return colon > 0 && line.slice(0, colon).trim().toLowerCase() === "proxy-authorization" ? [line.slice(colon + 1)] : [];
2229
+ });
2230
+ const [value] = values;
2231
+ return values.length === 1 ? value : void 0;
2232
+ }
2233
+ function routeConnect(socket, head, context) {
2234
+ const { config, effects, tlsAcceptor, ledger } = context;
2235
+ const credential = proxyAuthorizationOf(head);
2236
+ const capability = credential === void 0 ? void 0 : capabilityFromProxyAuthorization(credential);
2237
+ if (capability === void 0 || !config.isLiveCapability(capability)) {
2238
+ refuse(socket, REFUSAL.proxyAuthenticationRequired, [`Proxy-Authenticate: Basic realm="${CONNECT_PROXY_REALM}"`]);
2239
+ return;
2240
+ }
1931
2241
  const requestLine = head.split("\r\n", 1)[0] ?? "";
1932
2242
  const parts = requestLine.split(" ");
1933
2243
  const authority = parts.length === CONNECT_LINE_TOKENS && parts[0]?.toUpperCase() === "CONNECT" ? parts[1] ?? "" : void 0;
1934
2244
  const target = authority === void 0 ? void 0 : parseConnectTarget(authority);
1935
2245
  if (target === void 0) {
1936
- socket.write("HTTP/1.1 400 Bad Request\r\ncontent-length: 0\r\n\r\n");
1937
- socket.destroy();
2246
+ refuse(socket, REFUSAL.badRequest);
2247
+ return;
2248
+ }
2249
+ if (!ledger.establish(socket, capability)) {
2250
+ refuse(socket, REFUSAL.serviceUnavailable);
1938
2251
  return;
1939
2252
  }
1940
2253
  socket.write(CONNECT_ESTABLISHED);
@@ -1952,6 +2265,10 @@ async function blindTunnel(socket, target, effects) {
1952
2265
  socket.destroy();
1953
2266
  return;
1954
2267
  }
2268
+ if (socket.destroyed) {
2269
+ upstream.destroy();
2270
+ return;
2271
+ }
1955
2272
  socket.pipe(upstream);
1956
2273
  upstream.pipe(socket);
1957
2274
  const drop = () => {
@@ -1967,7 +2284,7 @@ async function blindTunnel(socket, target, effects) {
1967
2284
  socket.destroy();
1968
2285
  });
1969
2286
  }
1970
- function realMitmEffects() {
2287
+ function realConnectEffects() {
1971
2288
  const plainAgent = new http.Agent({ keepAlive: true });
1972
2289
  const tlsAgent = new https.Agent({ keepAlive: true });
1973
2290
  const listenOnce = async (port, onSocket) => await new Promise((resolve, reject) => {
@@ -2096,7 +2413,7 @@ function realMitmEffects() {
2096
2413
  function isEnoent(error) {
2097
2414
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
2098
2415
  }
2099
- function realMitmCertStore(paths) {
2416
+ function realConnectCertStore(paths) {
2100
2417
  const read = (file) => {
2101
2418
  try {
2102
2419
  return fs.readFileSync(file, "utf8");
@@ -2109,54 +2426,49 @@ function realMitmCertStore(paths) {
2109
2426
  };
2110
2427
  return {
2111
2428
  loadCa: () => {
2112
- const certPem = read(paths.headroomCaCertFile);
2113
- const keyPem = read(paths.headroomCaKeyFile);
2429
+ const certPem = read(paths.frontdoorCaCertFile);
2430
+ const keyPem = read(paths.frontdoorCaKeyFile);
2114
2431
  return certPem === void 0 || keyPem === void 0 ? void 0 : { certPem, keyPem };
2115
2432
  },
2116
2433
  writeCa: (ca) => {
2117
- fs.mkdirSync(paths.headroomCaDir, { recursive: true });
2118
- fs.writeFileSync(paths.headroomCaCertFile, ca.certPem, "utf8");
2119
- fs.writeFileSync(paths.headroomCaKeyFile, ca.keyPem, { encoding: "utf8", mode: CA_KEY_FILE_MODE });
2120
- fs.chmodSync(paths.headroomCaKeyFile, CA_KEY_FILE_MODE);
2434
+ fs.mkdirSync(paths.frontdoorCaDir, { recursive: true });
2435
+ fs.writeFileSync(paths.frontdoorCaCertFile, ca.certPem, "utf8");
2436
+ fs.writeFileSync(paths.frontdoorCaKeyFile, ca.keyPem, { encoding: "utf8", mode: CA_KEY_FILE_MODE });
2437
+ fs.chmodSync(paths.frontdoorCaKeyFile, CA_KEY_FILE_MODE);
2121
2438
  }
2122
2439
  };
2123
2440
  }
2124
2441
 
2442
+ // src/frontdoor/ensure.ts
2443
+ import { randomUUID as randomUUID2 } from "node:crypto";
2444
+
2125
2445
  // src/headroom/state.ts
2126
2446
  import { createHash } from "node:crypto";
2127
- import path5 from "node:path";
2128
- import { z as z3 } from "zod";
2447
+ import path6 from "node:path";
2448
+ import { z as z4 } from "zod";
2129
2449
  var HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
2130
- var HeadroomStateSchema = z3.strictObject({
2450
+ var HeadroomStateSchema = z4.strictObject({
2131
2451
  /** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
2132
- supervisorPid: z3.number().int().positive().optional(),
2452
+ supervisorPid: z4.number().int().positive().optional(),
2133
2453
  /** The headroom proxy process itself. Absent while the supervisor is between restarts. */
2134
- headroomPid: z3.number().int().positive().optional(),
2454
+ headroomPid: z4.number().int().positive().optional(),
2135
2455
  /** The loopback port the proxy listens on. Absent until the proxy has passed its readiness check, so "port is set" is itself the ready signal a launcher polls for. */
2136
- port: z3.number().int().positive().optional(),
2137
- /**
2138
- * The loopback port the supervisor's in-process MITM CONNECT proxy listens on. Absent whenever no supervisor is serving it, so "mitmPort is set" is the ready signal an OAuth launch polls for alongside `port`.
2139
- */
2140
- mitmPort: z3.number().int().positive().optional(),
2141
- /**
2142
- * The sticky MITM port preference, the exact analogue of `lastPort` for the second server: it survives every shutdown, because every OAuth session's environment was frozen at launch with HTTPS_PROXY pointing at this address and a restart that moves strands them.
2143
- */
2144
- lastMitmPort: z3.number().int().positive().optional(),
2456
+ port: z4.number().int().positive().optional(),
2145
2457
  /**
2146
- * The sticky port preference: the address the daemon last served on, kept across crashes, restarts, and idle shutdowns so the next start reuses it. Distinct from `port` on purpose: `port` is the ready signal (absent whenever nothing is serving), while `lastPort` survives every shutdown, because every live session's environment was frozen at launch pointing at this address and a restart that moves strands them.
2458
+ * The sticky port preference: the address the daemon last served on, kept across crashes, restarts, and idle shutdowns so the next start reuses it. Distinct from `port` on purpose: `port` is the ready signal (absent whenever nothing is serving), while `lastPort` survives every shutdown, because the front door (which routes sessions through this daemon) reads it live and follows a restart to whichever address it lands on.
2147
2459
  */
2148
- lastPort: z3.number().int().positive().optional(),
2460
+ lastPort: z4.number().int().positive().optional(),
2149
2461
  /** The `headroom --version` output of the running install. */
2150
- version: z3.string().optional(),
2462
+ version: z4.string().optional(),
2151
2463
  /** Hash of the allowlist the running proxy was started with, so a provider-file change is detected as drift. */
2152
- allowlistHash: z3.string().optional(),
2464
+ allowlistHash: z4.string().optional(),
2153
2465
  /** The install spec the running install was last installed from, so a `source` config change is detected as drift. */
2154
- installedSource: z3.string().optional(),
2466
+ installedSource: z4.string().optional(),
2155
2467
  /** The last fatal error, kept across shutdowns so `headroom status` can explain a daemon that is not running. */
2156
- lastError: z3.string().optional()
2468
+ lastError: z4.string().optional()
2157
2469
  });
2158
- var HeadroomSessionSchema = z3.strictObject({ pid: z3.number().int().positive(), startedAt: z3.number() });
2159
- var HeadroomLockSchema = z3.strictObject({ pid: z3.number().int().positive(), at: z3.number() });
2470
+ var HeadroomSessionSchema = z4.strictObject({ pid: z4.number().int().positive(), startedAt: z4.number() });
2471
+ var HeadroomLockSchema = z4.strictObject({ pid: z4.number().int().positive(), at: z4.number() });
2160
2472
  function parseJson(raw, schema) {
2161
2473
  if (raw === void 0 || raw.trim() === "") {
2162
2474
  return void 0;
@@ -2172,7 +2484,7 @@ function readHeadroomState(fs2, stateFile) {
2172
2484
  }
2173
2485
  }
2174
2486
  function writeHeadroomState(fs2, stateFile, state) {
2175
- fs2.mkdirp(path5.dirname(stateFile));
2487
+ fs2.mkdirp(path6.dirname(stateFile));
2176
2488
  fs2.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
2177
2489
  `);
2178
2490
  }
@@ -2184,16 +2496,8 @@ function headroomAllowlist(providers) {
2184
2496
  return [...urls].sort();
2185
2497
  }
2186
2498
  function headroomUpstreams(providers, frontDoorOrigin2) {
2187
- const upstreams = [];
2188
- let hasCodex = false;
2189
- for (const provider of providers) {
2190
- if (isCodexProvider(provider)) {
2191
- hasCodex = true;
2192
- } else {
2193
- upstreams.push({ baseUrl: provider.baseUrl });
2194
- }
2195
- }
2196
- if (hasCodex && frontDoorOrigin2 !== void 0) {
2499
+ const upstreams = providers.filter((provider) => !isCodexProvider(provider)).map((provider) => ({ baseUrl: provider.baseUrl }));
2500
+ if (providers.length > 0 && frontDoorOrigin2 !== void 0) {
2197
2501
  upstreams.push({ baseUrl: frontDoorOrigin2 });
2198
2502
  }
2199
2503
  return upstreams;
@@ -2208,7 +2512,7 @@ function readAllProviders(fs2, providersDir) {
2208
2512
  continue;
2209
2513
  }
2210
2514
  try {
2211
- const parsed = parseJson(fs2.readFileUtf8(path5.join(providersDir, name)), ProviderSchema);
2515
+ const parsed = parseJson(fs2.readFileUtf8(path6.join(providersDir, name)), ProviderSchema);
2212
2516
  if (parsed !== void 0) {
2213
2517
  result.push({ name: name.slice(0, -".json".length), provider: parsed });
2214
2518
  }
@@ -2220,11 +2524,11 @@ function readAllProviders(fs2, providersDir) {
2220
2524
  }
2221
2525
  function writeSession(fs2, sessionsDir, session) {
2222
2526
  fs2.mkdirp(sessionsDir);
2223
- fs2.writeFileUtf8(path5.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2527
+ fs2.writeFileUtf8(path6.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
2224
2528
  `);
2225
2529
  }
2226
2530
  function removeSession(fs2, sessionsDir, pid) {
2227
- fs2.removeRecursive(path5.join(sessionsDir, `${String(pid)}.json`));
2531
+ fs2.removeRecursive(path6.join(sessionsDir, `${String(pid)}.json`));
2228
2532
  }
2229
2533
  function listSessions(fs2, sessionsDir) {
2230
2534
  const sessions = [];
@@ -2233,7 +2537,7 @@ function listSessions(fs2, sessionsDir) {
2233
2537
  continue;
2234
2538
  }
2235
2539
  try {
2236
- const parsed = parseJson(fs2.readFileUtf8(path5.join(sessionsDir, name)), HeadroomSessionSchema);
2540
+ const parsed = parseJson(fs2.readFileUtf8(path6.join(sessionsDir, name)), HeadroomSessionSchema);
2237
2541
  if (parsed !== void 0) {
2238
2542
  sessions.push(parsed);
2239
2543
  }
@@ -2261,6 +2565,67 @@ function readStartLock(fs2, lockFile) {
2261
2565
  }
2262
2566
  }
2263
2567
 
2568
+ // src/frontdoor/ensure.ts
2569
+ var FRONTDOOR_START_TIMEOUT_MS = 3e4;
2570
+ var FRONTDOOR_LAUNCHER_POLL_MS = 100;
2571
+ var FrontDoorStartError = class extends CliError {
2572
+ constructor(message) {
2573
+ super(message);
2574
+ this.name = "FrontDoorStartError";
2575
+ }
2576
+ };
2577
+ function ensureFrontDoor(params) {
2578
+ const { paths, ports } = params;
2579
+ const deadline = ports.now() + FRONTDOOR_START_TIMEOUT_MS;
2580
+ let spawned = false;
2581
+ const distrusted = /* @__PURE__ */ new Set();
2582
+ let lastRejection;
2583
+ for (; ; ) {
2584
+ const state = readFrontDoorState(ports.fs, paths.frontdoorStateFile);
2585
+ const supervisorPid = state?.supervisorPid;
2586
+ if (supervisorPid !== void 0 && !distrusted.has(supervisorPid) && ports.isRunning(supervisorPid)) {
2587
+ if (state?.port !== void 0 && state.connectPort !== void 0) {
2588
+ const verdict = ports.verifyListener(state.port);
2589
+ if (verdict.ok) {
2590
+ const token = randomUUID2();
2591
+ writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token });
2592
+ return { port: state.port, connectPort: state.connectPort, token };
2593
+ }
2594
+ lastRejection = `the listener on 127.0.0.1:${String(state.port)} (recorded for pid ${String(supervisorPid)}) failed authentication: ${verdict.reason}`;
2595
+ if (spawned) {
2596
+ throw new FrontDoorStartError(`claude-use: ${lastRejection}; refusing to send this session's credentials to it. Daemon log: ${paths.frontdoorLogPath}`);
2597
+ }
2598
+ distrusted.add(supervisorPid);
2599
+ continue;
2600
+ }
2601
+ if (state?.lastError !== void 0) {
2602
+ throw new FrontDoorStartError(`claude-use: the front door reported a fatal error and is not serving: ${state.lastError} (daemon log: ${paths.frontdoorLogPath})`);
2603
+ }
2604
+ } else if (!spawned) {
2605
+ ports.fs.mkdirp(paths.frontdoorDir);
2606
+ const created = ports.fs.writeFileExclusive(paths.frontdoorLockFile, `${JSON.stringify({ pid: params.launcherPid, at: ports.now() })}
2607
+ `);
2608
+ if (created) {
2609
+ ports.spawnSupervisor(paths);
2610
+ spawned = true;
2611
+ } else {
2612
+ const lock = readStartLock(ports.fs, paths.frontdoorLockFile);
2613
+ if (lock === void 0 || !ports.isRunning(lock.pid)) {
2614
+ ports.fs.removeRecursive(paths.frontdoorLockFile);
2615
+ continue;
2616
+ }
2617
+ }
2618
+ }
2619
+ if (ports.now() >= deadline) {
2620
+ const lastError = state?.lastError;
2621
+ throw new FrontDoorStartError(
2622
+ `claude-use: the front door did not become ready within ${String(FRONTDOOR_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + (lastRejection === void 0 ? "" : ` (${lastRejection})`) + `. Daemon log: ${paths.frontdoorLogPath}`
2623
+ );
2624
+ }
2625
+ ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
2626
+ }
2627
+ }
2628
+
2264
2629
  // src/headroom/ensure.ts
2265
2630
  var HEADROOM_START_TIMEOUT_MS = 12e4;
2266
2631
  var HEADROOM_LAUNCHER_POLL_MS = 250;
@@ -2277,10 +2642,10 @@ function ensureHeadroom(params) {
2277
2642
  for (; ; ) {
2278
2643
  const state = readHeadroomState(ports.fs, paths.headroomStateFile);
2279
2644
  if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
2280
- const daemonUp = state.port !== void 0 && state.mitmPort !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
2281
- if (daemonUp && state.port !== void 0 && state.mitmPort !== void 0) {
2645
+ const daemonUp = state.port !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
2646
+ if (daemonUp && state.port !== void 0) {
2282
2647
  writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now() });
2283
- return { port: state.port, mitmPort: state.mitmPort };
2648
+ return { port: state.port };
2284
2649
  }
2285
2650
  if (state.lastError !== void 0) {
2286
2651
  throw new HeadroomStartError(
@@ -2315,42 +2680,6 @@ function ensureHeadroom(params) {
2315
2680
  }
2316
2681
  }
2317
2682
 
2318
- // src/frontdoor/state.ts
2319
- import { z as z4 } from "zod";
2320
- var FrontDoorStateSchema = z4.strictObject({
2321
- /** The supervisor process serving the front door. Alive means the listener is up in that process. */
2322
- supervisorPid: z4.number().int().positive().optional(),
2323
- /** The loopback port the front-door listener serves on. Absent until the listener has bound and answered its health probe, so "port is set" is itself the ready signal a launcher polls for. */
2324
- port: z4.number().int().positive().optional(),
2325
- /**
2326
- * The sticky port preference: kept across crashes, restarts and idle shutdowns so every session, whose base URL was frozen at launch, keeps finding the front door at the same address.
2327
- */
2328
- lastPort: z4.number().int().positive().optional(),
2329
- /** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
2330
- lastError: z4.string().optional()
2331
- });
2332
- function readFrontDoorState(fs2, stateFile) {
2333
- let raw;
2334
- try {
2335
- raw = fs2.readFileUtf8(stateFile);
2336
- } catch {
2337
- return void 0;
2338
- }
2339
- if (raw === void 0 || raw.trim() === "") {
2340
- return void 0;
2341
- }
2342
- try {
2343
- const parsed = FrontDoorStateSchema.safeParse(JSON.parse(raw));
2344
- return parsed.success ? parsed.data : void 0;
2345
- } catch {
2346
- return void 0;
2347
- }
2348
- }
2349
- function frontDoorOrigin(state) {
2350
- const port = state?.port ?? state?.lastPort;
2351
- return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
2352
- }
2353
-
2354
2683
  // src/headroom/supervisor.ts
2355
2684
  function resolveSupervisorConfig(configured) {
2356
2685
  return {
@@ -2363,7 +2692,7 @@ var HEADROOM_BACKOFF_CAP_MS = 3e4;
2363
2692
  var HEADROOM_START_RETRY_BUDGET = 5;
2364
2693
  var HEADROOM_READY_TIMEOUT_MS = 15e3;
2365
2694
  var HEADROOM_POLL_MS = 1e3;
2366
- var MS_PER_MINUTE = 6e4;
2695
+ var MS_PER_MINUTE2 = 6e4;
2367
2696
  function backoffForAttempt(attempt) {
2368
2697
  return Math.min(HEADROOM_BACKOFF_CAP_MS, HEADROOM_BACKOFF_BASE_MS * 2 ** (attempt - 1));
2369
2698
  }
@@ -2423,13 +2752,7 @@ async function runSupervisor(config, ports, options = {}) {
2423
2752
  const previousState = readHeadroomState(fs2, paths.headroomStateFile);
2424
2753
  let installedSource = previousState?.installedSource;
2425
2754
  let lastPort = previousState?.lastPort;
2426
- let lastMitmPort = previousState?.lastMitmPort;
2427
- let daemonPort;
2428
- const sticky = () => ({
2429
- ...lastPort === void 0 ? {} : { lastPort },
2430
- ...lastMitmPort === void 0 ? {} : { lastMitmPort }
2431
- });
2432
- let mitm;
2755
+ const sticky = () => lastPort === void 0 ? {} : { lastPort };
2433
2756
  const fail = (message) => {
2434
2757
  writeHeadroomState(fs2, paths.headroomStateFile, {
2435
2758
  lastError: message,
@@ -2458,18 +2781,7 @@ async function runSupervisor(config, ports, options = {}) {
2458
2781
  return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
2459
2782
  }
2460
2783
  const version = ports.headroomVersion() ?? "unknown";
2461
- try {
2462
- mitm = await ports.startMitm(lastMitmPort, () => daemonPort);
2463
- } catch (error) {
2464
- return fail(`could not start the MITM proxy: ${error instanceof Error ? error.message : String(error)}`);
2465
- }
2466
- lastMitmPort = mitm.port;
2467
- if (previousState?.lastMitmPort !== void 0 && mitm.port !== previousState.lastMitmPort) {
2468
- ports.log(
2469
- `claude-use headroom supervisor: sticky MITM port ${String(previousState.lastMitmPort)} was occupied; moving to ${String(mitm.port)} (OAuth sessions launched against the old port are stale until they relaunch)`
2470
- );
2471
- }
2472
- writeHeadroomState(fs2, paths.headroomStateFile, { supervisorPid: ports.ownPid, version, installedSource, mitmPort: mitm.port, ...sticky() });
2784
+ writeHeadroomState(fs2, paths.headroomStateFile, { supervisorPid: ports.ownPid, version, installedSource, ...sticky() });
2473
2785
  ports.log(`claude-use headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
2474
2786
  const orphanPid = previousState?.headroomPid;
2475
2787
  if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
@@ -2494,13 +2806,11 @@ async function runSupervisor(config, ports, options = {}) {
2494
2806
  if (crashed) {
2495
2807
  ports.log(`claude-use headroom supervisor: headroom pid ${String(headroomPid)} died`);
2496
2808
  headroomPid = void 0;
2497
- daemonPort = void 0;
2498
2809
  runningHash = void 0;
2499
2810
  writeHeadroomState(fs2, paths.headroomStateFile, {
2500
2811
  supervisorPid: ports.ownPid,
2501
2812
  version,
2502
2813
  installedSource,
2503
- mitmPort: mitm.port,
2504
2814
  ...sticky()
2505
2815
  });
2506
2816
  }
@@ -2517,7 +2827,6 @@ async function runSupervisor(config, ports, options = {}) {
2517
2827
  if (ready) {
2518
2828
  consecutiveFailures = 0;
2519
2829
  headroomPid = pid;
2520
- daemonPort = port;
2521
2830
  runningHash = allowlistHash;
2522
2831
  lastPort = port;
2523
2832
  if (previousSticky !== void 0 && port !== previousSticky) {
@@ -2529,7 +2838,6 @@ async function runSupervisor(config, ports, options = {}) {
2529
2838
  supervisorPid: ports.ownPid,
2530
2839
  headroomPid: pid,
2531
2840
  port,
2532
- mitmPort: mitm.port,
2533
2841
  version,
2534
2842
  allowlistHash,
2535
2843
  installedSource: config.source,
@@ -2553,7 +2861,6 @@ async function runSupervisor(config, ports, options = {}) {
2553
2861
  ports.log("claude-use headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
2554
2862
  ports.stopProcess(headroomPid);
2555
2863
  headroomPid = void 0;
2556
- daemonPort = void 0;
2557
2864
  runningHash = void 0;
2558
2865
  continue;
2559
2866
  }
@@ -2562,13 +2869,11 @@ async function runSupervisor(config, ports, options = {}) {
2562
2869
  if (sessions.length === 0) {
2563
2870
  idleSince ??= ports.now();
2564
2871
  const idleMs = ports.now() - idleSince;
2565
- if (idleMs >= config.idleShutdownMinutes * MS_PER_MINUTE) {
2872
+ if (idleMs >= config.idleShutdownMinutes * MS_PER_MINUTE2) {
2566
2873
  ports.log(
2567
- `claude-use headroom supervisor: no sessions for ${String(config.idleShutdownMinutes)} minute(s); stopping headroom and the MITM proxy, and exiting`
2874
+ `claude-use headroom supervisor: no sessions for ${String(config.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
2568
2875
  );
2569
2876
  ports.stopProcess(headroomPid);
2570
- daemonPort = void 0;
2571
- await mitm.close();
2572
2877
  writeHeadroomState(fs2, paths.headroomStateFile, {
2573
2878
  version,
2574
2879
  ...sticky()
@@ -2650,15 +2955,18 @@ function evaluateAmbientCredentialGuard(params) {
2650
2955
  }
2651
2956
  export {
2652
2957
  AMBIENT_CREDENTIAL_VARS,
2958
+ CONNECT_INTERCEPT_HOST,
2959
+ CONNECT_LIMITS,
2653
2960
  FARM_MANIFEST_FILENAME,
2654
- HEADROOM_SERVED_PATH_PREFIX,
2961
+ FrontDoorStartError,
2655
2962
  HeadroomStartError,
2656
- MITM_INTERCEPT_HOST,
2963
+ ROUTED_PATH_PREFIX,
2657
2964
  buildEntryFacts,
2658
2965
  carryOver,
2659
2966
  createLeafCache,
2660
2967
  detectAmbientCredential,
2661
2968
  ensureCa,
2969
+ ensureFrontDoor,
2662
2970
  ensureHeadroom,
2663
2971
  evaluateAmbientCredentialGuard,
2664
2972
  formatAmbientCredentialGuardMessage,
@@ -2668,15 +2976,16 @@ export {
2668
2976
  mintLeaf,
2669
2977
  parseConnectTarget,
2670
2978
  readFarmManifest,
2671
- realMitmCertStore,
2672
- realMitmEffects,
2979
+ realConnectCertStore,
2980
+ realConnectEffects,
2673
2981
  recoverFarm,
2674
2982
  recoveryDiagnostics,
2675
2983
  resolveDecisions,
2676
2984
  resolveSupervisorConfig,
2677
2985
  resyncFarm,
2986
+ runFrontDoorSupervisor,
2678
2987
  runSupervisor,
2679
- servedByHeadroom,
2680
- startMitmServer,
2988
+ servedByPipeline,
2989
+ startConnectServer,
2681
2990
  topLevelNames
2682
2991
  };