claude-use 4.5.0 → 5.0.1
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/README.md +1 -1
- package/dist/cli.cjs +3455 -2598
- package/dist/index.cjs +540 -162
- package/dist/index.mjs +530 -156
- package/dist/types/config/schema.d.ts +39 -0
- package/dist/types/frontdoor/capability.d.ts +19 -0
- package/dist/types/frontdoor/connect.d.ts +179 -0
- package/dist/types/frontdoor/ensure.d.ts +34 -0
- package/dist/types/frontdoor/probe.d.ts +13 -0
- package/dist/types/frontdoor/state.d.ts +32 -1
- package/dist/types/frontdoor/supervisor.d.ts +48 -0
- package/dist/types/headroom/ensure.d.ts +1 -2
- package/dist/types/headroom/settings.d.ts +13 -0
- package/dist/types/headroom/state.d.ts +3 -4
- package/dist/types/headroom/supervisor.d.ts +10 -12
- package/dist/types/index.d.ts +4 -2
- package/dist/types/launcher/ports.d.ts +22 -10
- package/dist/types/paths.d.ts +8 -6
- package/package.json +1 -1
- package/dist/types/headroom/mitm.d.ts +0 -138
package/dist/index.cjs
CHANGED
|
@@ -31,15 +31,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AMBIENT_CREDENTIAL_VARS: () => AMBIENT_CREDENTIAL_VARS,
|
|
34
|
+
CONNECT_INTERCEPT_HOST: () => CONNECT_INTERCEPT_HOST,
|
|
35
|
+
CONNECT_LIMITS: () => CONNECT_LIMITS,
|
|
34
36
|
FARM_MANIFEST_FILENAME: () => FARM_MANIFEST_FILENAME,
|
|
35
|
-
|
|
37
|
+
FrontDoorStartError: () => FrontDoorStartError,
|
|
36
38
|
HeadroomStartError: () => HeadroomStartError,
|
|
37
|
-
|
|
39
|
+
ROUTED_PATH_PREFIX: () => ROUTED_PATH_PREFIX,
|
|
38
40
|
buildEntryFacts: () => buildEntryFacts,
|
|
39
41
|
carryOver: () => carryOver,
|
|
40
42
|
createLeafCache: () => createLeafCache,
|
|
41
43
|
detectAmbientCredential: () => detectAmbientCredential,
|
|
42
44
|
ensureCa: () => ensureCa,
|
|
45
|
+
ensureFrontDoor: () => ensureFrontDoor,
|
|
43
46
|
ensureHeadroom: () => ensureHeadroom,
|
|
44
47
|
evaluateAmbientCredentialGuard: () => evaluateAmbientCredentialGuard,
|
|
45
48
|
formatAmbientCredentialGuardMessage: () => formatAmbientCredentialGuardMessage,
|
|
@@ -49,16 +52,17 @@ __export(index_exports, {
|
|
|
49
52
|
mintLeaf: () => mintLeaf,
|
|
50
53
|
parseConnectTarget: () => parseConnectTarget,
|
|
51
54
|
readFarmManifest: () => readFarmManifest,
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
realConnectCertStore: () => realConnectCertStore,
|
|
56
|
+
realConnectEffects: () => realConnectEffects,
|
|
54
57
|
recoverFarm: () => recoverFarm,
|
|
55
58
|
recoveryDiagnostics: () => recoveryDiagnostics,
|
|
56
59
|
resolveDecisions: () => resolveDecisions,
|
|
57
60
|
resolveSupervisorConfig: () => resolveSupervisorConfig,
|
|
58
61
|
resyncFarm: () => resyncFarm,
|
|
62
|
+
runFrontDoorSupervisor: () => runFrontDoorSupervisor,
|
|
59
63
|
runSupervisor: () => runSupervisor,
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
servedByPipeline: () => servedByPipeline,
|
|
65
|
+
startConnectServer: () => startConnectServer,
|
|
62
66
|
topLevelNames: () => topLevelNames
|
|
63
67
|
});
|
|
64
68
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -220,11 +224,36 @@ var PortableConfigSchema = ConfigProfileSchema.omit({ description: true }).exten
|
|
|
220
224
|
identity: import_zod.z.string().min(1).optional(),
|
|
221
225
|
when: WhenSchema.optional()
|
|
222
226
|
});
|
|
223
|
-
var
|
|
227
|
+
var HEADROOM_MODES = ["cache", "token"];
|
|
228
|
+
var HEADROOM_CCR_MODES = ["default", "lossless", "none"];
|
|
229
|
+
var HEADROOM_ROLLOUT_CHANNELS = ["beta", "canary", "dev"];
|
|
230
|
+
var INTERCEPT_CHANNELS = ["canary", "dev"];
|
|
231
|
+
var READ_MATURATION_CHANNELS = ["beta", "dev"];
|
|
232
|
+
var HeadroomGlobalConfigObjectSchema = import_zod.z.strictObject({
|
|
224
233
|
/** Install spec handed to `uv tool install`. Defaults to HEADROOM_DEFAULT_SOURCE. */
|
|
225
234
|
source: import_zod.z.string().min(1).optional(),
|
|
226
235
|
/** How long the daemon may sit with no registered sessions before the supervisor stops it. Defaults to HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES. */
|
|
227
|
-
idleShutdownMinutes: import_zod.z.number().int().positive().optional()
|
|
236
|
+
idleShutdownMinutes: import_zod.z.number().int().positive().optional(),
|
|
237
|
+
/** Optimisation mode, passed as `--mode`. Unset leaves headroom's own default (`cache`). */
|
|
238
|
+
mode: import_zod.z.enum(HEADROOM_MODES).optional(),
|
|
239
|
+
/** Keep-ratio for prose and code compression, passed as `--target-ratio`: lower is more aggressive. Unset lets headroom decide. */
|
|
240
|
+
targetRatio: import_zod.z.number().gt(0).max(1).optional(),
|
|
241
|
+
/** How compressed tool output stays recoverable. Unset leaves headroom's own default (`default`). */
|
|
242
|
+
ccr: import_zod.z.enum(HEADROOM_CCR_MODES).optional(),
|
|
243
|
+
/** Headroom's experimental release channel, exported as `HEADROOM_ROLLOUT_CHANNEL`. Required by `interceptToolResults` and `readMaturation`, which are refused without a channel that unlocks them. */
|
|
244
|
+
rolloutChannel: import_zod.z.enum(HEADROOM_ROLLOUT_CHANNELS).optional(),
|
|
245
|
+
/** Opt in to headroom's tool-result interceptors (`--intercept-tool-results`). Needs `rolloutChannel` canary or dev. */
|
|
246
|
+
interceptToolResults: import_zod.z.boolean().optional(),
|
|
247
|
+
/** Opt in to headroom's experimental read maturation (`--read-maturation`). Needs `rolloutChannel` beta or dev. */
|
|
248
|
+
readMaturation: import_zod.z.boolean().optional()
|
|
249
|
+
});
|
|
250
|
+
var HeadroomGlobalConfigSchema = HeadroomGlobalConfigObjectSchema.superRefine((config, context) => {
|
|
251
|
+
if (config.interceptToolResults === true && !INTERCEPT_CHANNELS.includes(config.rolloutChannel ?? "")) {
|
|
252
|
+
context.addIssue({ code: "custom", path: ["interceptToolResults"], message: "interceptToolResults needs rolloutChannel canary or dev" });
|
|
253
|
+
}
|
|
254
|
+
if (config.readMaturation === true && !READ_MATURATION_CHANNELS.includes(config.rolloutChannel ?? "")) {
|
|
255
|
+
context.addIssue({ code: "custom", path: ["readMaturation"], message: "readMaturation needs rolloutChannel beta or dev" });
|
|
256
|
+
}
|
|
228
257
|
});
|
|
229
258
|
var HEADROOM_DEFAULT_SOURCE = "headroom-ai[proxy] @ git+https://github.com/ExaDev/headroom@eb02fa4126450c9905a49394fdec19ae2e7c9c30";
|
|
230
259
|
var HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES = 15;
|
|
@@ -1798,15 +1827,213 @@ function recoveryDiagnostics(recovery, identity) {
|
|
|
1798
1827
|
];
|
|
1799
1828
|
}
|
|
1800
1829
|
|
|
1801
|
-
// src/
|
|
1830
|
+
// src/frontdoor/connect.ts
|
|
1802
1831
|
var fs = __toESM(require("node:fs"), 1);
|
|
1803
1832
|
var http = __toESM(require("node:http"), 1);
|
|
1804
1833
|
var https = __toESM(require("node:https"), 1);
|
|
1805
1834
|
var net = __toESM(require("node:net"), 1);
|
|
1806
1835
|
var tls = __toESM(require("node:tls"), 1);
|
|
1807
1836
|
var import_node_forge = __toESM(require("node-forge"), 1);
|
|
1808
|
-
|
|
1809
|
-
|
|
1837
|
+
|
|
1838
|
+
// src/frontdoor/capability.ts
|
|
1839
|
+
var CONNECT_PROXY_REALM = "claude-use front door";
|
|
1840
|
+
var BASIC_SCHEME = "basic";
|
|
1841
|
+
function capabilityFromProxyAuthorization(value) {
|
|
1842
|
+
const trimmed = value.trim();
|
|
1843
|
+
const space = trimmed.indexOf(" ");
|
|
1844
|
+
if (space === -1 || trimmed.slice(0, space).toLowerCase() !== BASIC_SCHEME) {
|
|
1845
|
+
return void 0;
|
|
1846
|
+
}
|
|
1847
|
+
const userPass = Buffer.from(trimmed.slice(space + 1).trim(), "base64").toString("utf8");
|
|
1848
|
+
const colon = userPass.indexOf(":");
|
|
1849
|
+
if (colon === -1) {
|
|
1850
|
+
return void 0;
|
|
1851
|
+
}
|
|
1852
|
+
const password = userPass.slice(colon + 1);
|
|
1853
|
+
return password === "" ? void 0 : password;
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
// src/frontdoor/state.ts
|
|
1857
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
1858
|
+
var import_zod3 = require("zod");
|
|
1859
|
+
var FrontDoorSessionSchema = import_zod3.z.strictObject({ pid: import_zod3.z.number().int().positive(), startedAt: import_zod3.z.number(), token: import_zod3.z.string().min(1) });
|
|
1860
|
+
var FrontDoorStateSchema = import_zod3.z.strictObject({
|
|
1861
|
+
/** The supervisor process serving the front door. Alive means both listeners are up in that process. */
|
|
1862
|
+
supervisorPid: import_zod3.z.number().int().positive().optional(),
|
|
1863
|
+
/** 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. */
|
|
1864
|
+
port: import_zod3.z.number().int().positive().optional(),
|
|
1865
|
+
/**
|
|
1866
|
+
* 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.
|
|
1867
|
+
*/
|
|
1868
|
+
lastPort: import_zod3.z.number().int().positive().optional(),
|
|
1869
|
+
/**
|
|
1870
|
+
* 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`.
|
|
1871
|
+
*/
|
|
1872
|
+
connectPort: import_zod3.z.number().int().positive().optional(),
|
|
1873
|
+
/**
|
|
1874
|
+
* 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.
|
|
1875
|
+
*/
|
|
1876
|
+
lastConnectPort: import_zod3.z.number().int().positive().optional(),
|
|
1877
|
+
/**
|
|
1878
|
+
* 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.
|
|
1879
|
+
*/
|
|
1880
|
+
directPort: import_zod3.z.number().int().positive().optional(),
|
|
1881
|
+
/** The sticky port preference for the direct listener, for the reason `directPort` gives. */
|
|
1882
|
+
lastDirectPort: import_zod3.z.number().int().positive().optional(),
|
|
1883
|
+
/** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
|
|
1884
|
+
lastError: import_zod3.z.string().optional()
|
|
1885
|
+
});
|
|
1886
|
+
function readFrontDoorState(fs2, stateFile) {
|
|
1887
|
+
let raw;
|
|
1888
|
+
try {
|
|
1889
|
+
raw = fs2.readFileUtf8(stateFile);
|
|
1890
|
+
} catch {
|
|
1891
|
+
return void 0;
|
|
1892
|
+
}
|
|
1893
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
1894
|
+
return void 0;
|
|
1895
|
+
}
|
|
1896
|
+
try {
|
|
1897
|
+
const parsed = FrontDoorStateSchema.safeParse(JSON.parse(raw));
|
|
1898
|
+
return parsed.success ? parsed.data : void 0;
|
|
1899
|
+
} catch {
|
|
1900
|
+
return void 0;
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
function writeFrontDoorState(fs2, stateFile, state) {
|
|
1904
|
+
fs2.mkdirp(import_node_path5.default.dirname(stateFile));
|
|
1905
|
+
fs2.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
|
|
1906
|
+
`);
|
|
1907
|
+
}
|
|
1908
|
+
function frontDoorOrigin(state) {
|
|
1909
|
+
const port = state?.directPort ?? state?.lastDirectPort;
|
|
1910
|
+
return port === void 0 ? void 0 : `http://127.0.0.1:${String(port)}`;
|
|
1911
|
+
}
|
|
1912
|
+
function writeFrontDoorSession(fs2, sessionsDir, session) {
|
|
1913
|
+
fs2.mkdirPrivate(sessionsDir);
|
|
1914
|
+
fs2.writeFilePrivate(import_node_path5.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
|
|
1915
|
+
`);
|
|
1916
|
+
}
|
|
1917
|
+
function listFrontDoorSessions(fs2, sessionsDir) {
|
|
1918
|
+
const sessions = [];
|
|
1919
|
+
for (const name of fs2.readdir(sessionsDir)) {
|
|
1920
|
+
if (!name.endsWith(".json")) {
|
|
1921
|
+
continue;
|
|
1922
|
+
}
|
|
1923
|
+
try {
|
|
1924
|
+
const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs2.readFileUtf8(import_node_path5.default.join(sessionsDir, name)) ?? ""));
|
|
1925
|
+
if (parsed.success) {
|
|
1926
|
+
sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
|
|
1927
|
+
}
|
|
1928
|
+
} catch {
|
|
1929
|
+
continue;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
return sessions.sort((a, b) => a.pid - b.pid);
|
|
1933
|
+
}
|
|
1934
|
+
function removeFrontDoorSession(fs2, sessionsDir, pid) {
|
|
1935
|
+
fs2.removeRecursive(import_node_path5.default.join(sessionsDir, `${String(pid)}.json`));
|
|
1936
|
+
}
|
|
1937
|
+
function pruneDeadFrontDoorSessions(fs2, sessionsDir, isRunning) {
|
|
1938
|
+
const removed = [];
|
|
1939
|
+
for (const session of listFrontDoorSessions(fs2, sessionsDir)) {
|
|
1940
|
+
if (!isRunning(session.pid)) {
|
|
1941
|
+
removeFrontDoorSession(fs2, sessionsDir, session.pid);
|
|
1942
|
+
removed.push(session.pid);
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
return removed;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// src/frontdoor/supervisor.ts
|
|
1949
|
+
var FRONTDOOR_SUPERVISOR_STILL_RUNNING = -1;
|
|
1950
|
+
var FRONTDOOR_POLL_MS = 1e3;
|
|
1951
|
+
var MS_PER_MINUTE = 6e4;
|
|
1952
|
+
async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {}) {
|
|
1953
|
+
const { fs: fs2, paths } = ports;
|
|
1954
|
+
const previous = readFrontDoorState(fs2, paths.frontdoorStateFile);
|
|
1955
|
+
let lastPort = previous?.lastPort;
|
|
1956
|
+
let lastConnectPort = previous?.lastConnectPort;
|
|
1957
|
+
let lastDirectPort = previous?.lastDirectPort;
|
|
1958
|
+
const sticky = () => ({
|
|
1959
|
+
...lastPort === void 0 ? {} : { lastPort },
|
|
1960
|
+
...lastConnectPort === void 0 ? {} : { lastConnectPort },
|
|
1961
|
+
...lastDirectPort === void 0 ? {} : { lastDirectPort }
|
|
1962
|
+
});
|
|
1963
|
+
const fail = (message) => {
|
|
1964
|
+
writeFrontDoorState(fs2, paths.frontdoorStateFile, { lastError: message, ...sticky() });
|
|
1965
|
+
fs2.removeRecursive(paths.frontdoorLockFile);
|
|
1966
|
+
ports.log(`claude-use frontdoor supervisor: ${message}`);
|
|
1967
|
+
return 1;
|
|
1968
|
+
};
|
|
1969
|
+
writeFrontDoorState(fs2, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
|
|
1970
|
+
const previousSticky = lastPort;
|
|
1971
|
+
let http2;
|
|
1972
|
+
try {
|
|
1973
|
+
http2 = await ports.startProviderListener(lastPort);
|
|
1974
|
+
} catch (error) {
|
|
1975
|
+
return fail(`could not start the provider listener: ${error instanceof Error ? error.message : String(error)}`);
|
|
1976
|
+
}
|
|
1977
|
+
if (previousSticky !== void 0 && http2.port !== previousSticky) {
|
|
1978
|
+
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)`);
|
|
1979
|
+
}
|
|
1980
|
+
lastPort = http2.port;
|
|
1981
|
+
const previousStickyConnect = lastConnectPort;
|
|
1982
|
+
let connect2;
|
|
1983
|
+
try {
|
|
1984
|
+
connect2 = await ports.startConnectListener(lastConnectPort);
|
|
1985
|
+
} catch (error) {
|
|
1986
|
+
await http2.close();
|
|
1987
|
+
return fail(`could not start the CONNECT surface: ${error instanceof Error ? error.message : String(error)}`);
|
|
1988
|
+
}
|
|
1989
|
+
if (previousStickyConnect !== void 0 && connect2.port !== previousStickyConnect) {
|
|
1990
|
+
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)`);
|
|
1991
|
+
}
|
|
1992
|
+
lastConnectPort = connect2.port;
|
|
1993
|
+
const previousStickyDirect = lastDirectPort;
|
|
1994
|
+
let direct;
|
|
1995
|
+
try {
|
|
1996
|
+
direct = await ports.startDirectListener(lastDirectPort);
|
|
1997
|
+
} catch (error) {
|
|
1998
|
+
await connect2.close();
|
|
1999
|
+
await http2.close();
|
|
2000
|
+
return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
|
|
2001
|
+
}
|
|
2002
|
+
if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
|
|
2003
|
+
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)`);
|
|
2004
|
+
}
|
|
2005
|
+
lastDirectPort = direct.port;
|
|
2006
|
+
writeFrontDoorState(fs2, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, port: http2.port, connectPort: connect2.port, directPort: direct.port, ...sticky() });
|
|
2007
|
+
fs2.removeRecursive(paths.frontdoorLockFile);
|
|
2008
|
+
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)}`);
|
|
2009
|
+
let idleSince;
|
|
2010
|
+
let ticks = 0;
|
|
2011
|
+
for (; ; ) {
|
|
2012
|
+
if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
|
|
2013
|
+
return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
|
|
2014
|
+
}
|
|
2015
|
+
ticks += 1;
|
|
2016
|
+
pruneDeadFrontDoorSessions(fs2, paths.frontdoorSessionsDir, ports.isRunning);
|
|
2017
|
+
if (listFrontDoorSessions(fs2, paths.frontdoorSessionsDir).length === 0) {
|
|
2018
|
+
idleSince ??= ports.now();
|
|
2019
|
+
if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
|
|
2020
|
+
ports.log(`claude-use frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
|
|
2021
|
+
await direct.close();
|
|
2022
|
+
await connect2.close();
|
|
2023
|
+
await http2.close();
|
|
2024
|
+
writeFrontDoorState(fs2, paths.frontdoorStateFile, sticky());
|
|
2025
|
+
return 0;
|
|
2026
|
+
}
|
|
2027
|
+
} else {
|
|
2028
|
+
idleSince = void 0;
|
|
2029
|
+
}
|
|
2030
|
+
await ports.sleep(FRONTDOOR_POLL_MS);
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
// src/frontdoor/connect.ts
|
|
2035
|
+
var CONNECT_INTERCEPT_HOST = "api.anthropic.com";
|
|
2036
|
+
var ROUTED_PATH_PREFIX = "/v1/";
|
|
1810
2037
|
var HTTPS_PORT = 443;
|
|
1811
2038
|
var MAX_PORT = 65535;
|
|
1812
2039
|
var SERIAL_NUMBER_BYTES = 16;
|
|
@@ -1816,9 +2043,22 @@ var CONNECT_LINE_TOKENS = 3;
|
|
|
1816
2043
|
var HEAD_TERMINATOR = "\r\n\r\n";
|
|
1817
2044
|
var MAX_CONNECT_HEAD_BYTES = 8192;
|
|
1818
2045
|
var CONNECT_ESTABLISHED = "HTTP/1.1 200 Connection Established\r\n\r\n";
|
|
2046
|
+
var REFUSAL = {
|
|
2047
|
+
badRequest: "400 Bad Request",
|
|
2048
|
+
proxyAuthenticationRequired: "407 Proxy Authentication Required",
|
|
2049
|
+
requestTimeout: "408 Request Timeout",
|
|
2050
|
+
headTooLarge: "431 Request Header Fields Too Large",
|
|
2051
|
+
serviceUnavailable: "503 Service Unavailable"
|
|
2052
|
+
};
|
|
2053
|
+
var CONNECT_LIMITS = {
|
|
2054
|
+
headDeadlineMs: 1e4,
|
|
2055
|
+
maxPendingHeads: 64,
|
|
2056
|
+
maxTunnels: 1024,
|
|
2057
|
+
revalidateMs: FRONTDOOR_POLL_MS
|
|
2058
|
+
};
|
|
1819
2059
|
var CA_VALIDITY_DAYS = 3650;
|
|
1820
2060
|
var LEAF_VALIDITY_DAYS = 397;
|
|
1821
|
-
var CA_SUBJECT_COMMON_NAME = "claude-use
|
|
2061
|
+
var CA_SUBJECT_COMMON_NAME = "claude-use front door CA";
|
|
1822
2062
|
var MS_PER_DAY = 864e5;
|
|
1823
2063
|
function parseConnectTarget(authority) {
|
|
1824
2064
|
const colon = authority.lastIndexOf(":");
|
|
@@ -1836,8 +2076,8 @@ function parseConnectTarget(authority) {
|
|
|
1836
2076
|
function isInterceptedHost(host, interceptHost) {
|
|
1837
2077
|
return host === interceptHost;
|
|
1838
2078
|
}
|
|
1839
|
-
function
|
|
1840
|
-
return
|
|
2079
|
+
function servedByPipeline(path7) {
|
|
2080
|
+
return path7?.startsWith(ROUTED_PATH_PREFIX) === true;
|
|
1841
2081
|
}
|
|
1842
2082
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
1843
2083
|
"connection",
|
|
@@ -1885,7 +2125,13 @@ function generateCa(now) {
|
|
|
1885
2125
|
cert.sign(keys.privateKey, import_node_forge.default.md.sha256.create());
|
|
1886
2126
|
return { certPem: import_node_forge.default.pki.certificateToPem(cert), keyPem: import_node_forge.default.pki.privateKeyToPem(keys.privateKey) };
|
|
1887
2127
|
}
|
|
1888
|
-
|
|
2128
|
+
var SAN_TYPE_DNS = 2;
|
|
2129
|
+
var SAN_TYPE_IP = 7;
|
|
2130
|
+
function mintLeaf(ca, names, now) {
|
|
2131
|
+
const [commonName] = names;
|
|
2132
|
+
if (commonName === void 0) {
|
|
2133
|
+
throw new Error("a leaf certificate needs at least one name");
|
|
2134
|
+
}
|
|
1889
2135
|
const caCert = import_node_forge.default.pki.certificateFromPem(ca.certPem);
|
|
1890
2136
|
const caKey = import_node_forge.default.pki.privateKeyFromPem(ca.keyPem);
|
|
1891
2137
|
const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
|
|
@@ -1894,13 +2140,13 @@ function mintLeaf(ca, host, now) {
|
|
|
1894
2140
|
cert.serialNumber = import_node_forge.default.util.bytesToHex(import_node_forge.default.random.getBytesSync(SERIAL_NUMBER_BYTES));
|
|
1895
2141
|
cert.validity.notBefore = new Date(now.getTime() - MS_PER_DAY);
|
|
1896
2142
|
cert.validity.notAfter = new Date(now.getTime() + LEAF_VALIDITY_DAYS * MS_PER_DAY);
|
|
1897
|
-
cert.setSubject([{ name: "commonName", value:
|
|
2143
|
+
cert.setSubject([{ name: "commonName", value: commonName }]);
|
|
1898
2144
|
cert.setIssuer(caCert.subject.attributes);
|
|
1899
2145
|
cert.setExtensions([
|
|
1900
2146
|
{ name: "basicConstraints", cA: false, critical: true },
|
|
1901
2147
|
{ name: "keyUsage", digitalSignature: true, keyEncipherment: true, critical: true },
|
|
1902
2148
|
{ name: "extKeyUsage", serverAuth: true },
|
|
1903
|
-
{ name: "subjectAltName", altNames:
|
|
2149
|
+
{ name: "subjectAltName", altNames: names.map((name) => net.isIP(name) === 0 ? { type: SAN_TYPE_DNS, value: name } : { type: SAN_TYPE_IP, ip: name }) },
|
|
1904
2150
|
{ name: "subjectKeyIdentifier" },
|
|
1905
2151
|
{ name: "authorityKeyIdentifier", keyLocatorFields: [] }
|
|
1906
2152
|
]);
|
|
@@ -1914,7 +2160,7 @@ function createLeafCache(ca, now) {
|
|
|
1914
2160
|
if (existing !== void 0) {
|
|
1915
2161
|
return existing;
|
|
1916
2162
|
}
|
|
1917
|
-
const minted = mintLeaf(ca, host, now());
|
|
2163
|
+
const minted = mintLeaf(ca, [host], now());
|
|
1918
2164
|
cache.set(host, minted);
|
|
1919
2165
|
return minted;
|
|
1920
2166
|
};
|
|
@@ -1937,17 +2183,10 @@ function caParses(ca) {
|
|
|
1937
2183
|
return false;
|
|
1938
2184
|
}
|
|
1939
2185
|
}
|
|
1940
|
-
async function
|
|
2186
|
+
async function startConnectServer(config, effects, preferredPort) {
|
|
1941
2187
|
const handler = (request3, response) => {
|
|
1942
|
-
if (
|
|
1943
|
-
|
|
1944
|
-
if (daemonPort === void 0) {
|
|
1945
|
-
const body = "claude-use headroom: the daemon is restarting";
|
|
1946
|
-
response.writeHead(HTTP_BAD_GATEWAY, { "content-type": "text/plain", "content-length": String(body.length) });
|
|
1947
|
-
response.end(body);
|
|
1948
|
-
return;
|
|
1949
|
-
}
|
|
1950
|
-
effects.forwardHttp({ host: "127.0.0.1", port: daemonPort, tls: false }, request3, response);
|
|
2188
|
+
if (servedByPipeline(request3.url)) {
|
|
2189
|
+
config.serveRouted(request3, response);
|
|
1951
2190
|
return;
|
|
1952
2191
|
}
|
|
1953
2192
|
effects.forwardHttp(config.upstream, request3, response);
|
|
@@ -1956,50 +2195,153 @@ async function startMitmServer(config, effects, preferredPort) {
|
|
|
1956
2195
|
const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(config.interceptHost), (secure) => {
|
|
1957
2196
|
httpSession.serve(secure);
|
|
1958
2197
|
});
|
|
2198
|
+
const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
|
|
1959
2199
|
const listener = await effects.listenLoopback(preferredPort, (socket) => {
|
|
1960
|
-
handleConnect(socket, config, effects, tlsAcceptor);
|
|
2200
|
+
handleConnect(socket, { config, effects, tlsAcceptor, ledger });
|
|
1961
2201
|
});
|
|
1962
2202
|
return {
|
|
1963
2203
|
port: listener.port,
|
|
1964
2204
|
close: async () => {
|
|
2205
|
+
ledger.close();
|
|
1965
2206
|
await listener.close();
|
|
1966
2207
|
tlsAcceptor.close();
|
|
1967
2208
|
httpSession.close();
|
|
1968
2209
|
}
|
|
1969
2210
|
};
|
|
1970
2211
|
}
|
|
1971
|
-
function
|
|
2212
|
+
function createConnectionLedger(limits, isLiveCapability) {
|
|
2213
|
+
const pending = /* @__PURE__ */ new Map();
|
|
2214
|
+
const authenticated = /* @__PURE__ */ new Map();
|
|
2215
|
+
let tunnels = 0;
|
|
2216
|
+
const leavePending = (socket) => {
|
|
2217
|
+
const deadline = pending.get(socket);
|
|
2218
|
+
if (deadline !== void 0) {
|
|
2219
|
+
clearTimeout(deadline);
|
|
2220
|
+
pending.delete(socket);
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
2223
|
+
const revalidation = setInterval(() => {
|
|
2224
|
+
for (const [capability, sockets] of authenticated) {
|
|
2225
|
+
if (!isLiveCapability(capability)) {
|
|
2226
|
+
for (const socket of sockets) {
|
|
2227
|
+
socket.destroy();
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
}, limits.revalidateMs);
|
|
2232
|
+
revalidation.unref();
|
|
2233
|
+
return {
|
|
2234
|
+
accept: (socket) => {
|
|
2235
|
+
const [oldest] = pending.keys();
|
|
2236
|
+
if (pending.size >= limits.maxPendingHeads && oldest !== void 0) {
|
|
2237
|
+
leavePending(oldest);
|
|
2238
|
+
refuse(oldest, REFUSAL.requestTimeout);
|
|
2239
|
+
}
|
|
2240
|
+
pending.set(
|
|
2241
|
+
socket,
|
|
2242
|
+
setTimeout(() => {
|
|
2243
|
+
leavePending(socket);
|
|
2244
|
+
refuse(socket, REFUSAL.requestTimeout);
|
|
2245
|
+
}, limits.headDeadlineMs)
|
|
2246
|
+
);
|
|
2247
|
+
socket.once("close", () => {
|
|
2248
|
+
leavePending(socket);
|
|
2249
|
+
});
|
|
2250
|
+
},
|
|
2251
|
+
headReceived: leavePending,
|
|
2252
|
+
establish: (socket, capability) => {
|
|
2253
|
+
if (tunnels >= limits.maxTunnels) {
|
|
2254
|
+
return false;
|
|
2255
|
+
}
|
|
2256
|
+
tunnels += 1;
|
|
2257
|
+
const sockets = authenticated.get(capability) ?? /* @__PURE__ */ new Set();
|
|
2258
|
+
sockets.add(socket);
|
|
2259
|
+
authenticated.set(capability, sockets);
|
|
2260
|
+
socket.once("close", () => {
|
|
2261
|
+
tunnels -= 1;
|
|
2262
|
+
sockets.delete(socket);
|
|
2263
|
+
if (sockets.size === 0 && authenticated.get(capability) === sockets) {
|
|
2264
|
+
authenticated.delete(capability);
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
return true;
|
|
2268
|
+
},
|
|
2269
|
+
close: () => {
|
|
2270
|
+
clearInterval(revalidation);
|
|
2271
|
+
for (const deadline of pending.values()) {
|
|
2272
|
+
clearTimeout(deadline);
|
|
2273
|
+
}
|
|
2274
|
+
pending.clear();
|
|
2275
|
+
}
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
function refuse(socket, status, headers = []) {
|
|
2279
|
+
socket.removeAllListeners("data");
|
|
2280
|
+
socket.pause();
|
|
2281
|
+
if (socket.destroyed || socket.writableEnded) {
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
socket.end(`HTTP/1.1 ${status}\r
|
|
2285
|
+
${headers.map((header) => `${header}\r
|
|
2286
|
+
`).join("")}content-length: 0\r
|
|
2287
|
+
connection: close\r
|
|
2288
|
+
\r
|
|
2289
|
+
`, () => {
|
|
2290
|
+
socket.destroy();
|
|
2291
|
+
});
|
|
2292
|
+
}
|
|
2293
|
+
function handleConnect(socket, context) {
|
|
2294
|
+
socket.on("error", () => {
|
|
2295
|
+
socket.destroy();
|
|
2296
|
+
});
|
|
2297
|
+
context.ledger.accept(socket);
|
|
1972
2298
|
let buffer = Buffer.alloc(0);
|
|
1973
2299
|
const onData = (chunk) => {
|
|
1974
2300
|
buffer = Buffer.concat([buffer, chunk]);
|
|
1975
2301
|
const headEnd = buffer.indexOf(HEAD_TERMINATOR);
|
|
2302
|
+
if (headEnd === -1 ? buffer.length > MAX_CONNECT_HEAD_BYTES : headEnd > MAX_CONNECT_HEAD_BYTES) {
|
|
2303
|
+
context.ledger.headReceived(socket);
|
|
2304
|
+
refuse(socket, REFUSAL.headTooLarge);
|
|
2305
|
+
return;
|
|
2306
|
+
}
|
|
1976
2307
|
if (headEnd === -1) {
|
|
1977
|
-
if (buffer.length > MAX_CONNECT_HEAD_BYTES) {
|
|
1978
|
-
socket.removeListener("data", onData);
|
|
1979
|
-
socket.pause();
|
|
1980
|
-
socket.destroy();
|
|
1981
|
-
}
|
|
1982
2308
|
return;
|
|
1983
2309
|
}
|
|
1984
2310
|
socket.removeListener("data", onData);
|
|
1985
2311
|
socket.pause();
|
|
2312
|
+
context.ledger.headReceived(socket);
|
|
1986
2313
|
const head = buffer.subarray(0, headEnd).toString("utf8");
|
|
1987
2314
|
socket.unshift(buffer.subarray(headEnd + HEAD_TERMINATOR.length));
|
|
1988
|
-
routeConnect(socket, head,
|
|
2315
|
+
routeConnect(socket, head, context);
|
|
1989
2316
|
};
|
|
1990
2317
|
socket.on("data", onData);
|
|
1991
|
-
socket.on("error", () => {
|
|
1992
|
-
socket.destroy();
|
|
1993
|
-
});
|
|
1994
2318
|
}
|
|
1995
|
-
function
|
|
2319
|
+
function proxyAuthorizationOf(head) {
|
|
2320
|
+
const values = head.split("\r\n").slice(1).flatMap((line) => {
|
|
2321
|
+
const colon = line.indexOf(":");
|
|
2322
|
+
return colon > 0 && line.slice(0, colon).trim().toLowerCase() === "proxy-authorization" ? [line.slice(colon + 1)] : [];
|
|
2323
|
+
});
|
|
2324
|
+
const [value] = values;
|
|
2325
|
+
return values.length === 1 ? value : void 0;
|
|
2326
|
+
}
|
|
2327
|
+
function routeConnect(socket, head, context) {
|
|
2328
|
+
const { config, effects, tlsAcceptor, ledger } = context;
|
|
2329
|
+
const credential = proxyAuthorizationOf(head);
|
|
2330
|
+
const capability = credential === void 0 ? void 0 : capabilityFromProxyAuthorization(credential);
|
|
2331
|
+
if (capability === void 0 || !config.isLiveCapability(capability)) {
|
|
2332
|
+
refuse(socket, REFUSAL.proxyAuthenticationRequired, [`Proxy-Authenticate: Basic realm="${CONNECT_PROXY_REALM}"`]);
|
|
2333
|
+
return;
|
|
2334
|
+
}
|
|
1996
2335
|
const requestLine = head.split("\r\n", 1)[0] ?? "";
|
|
1997
2336
|
const parts = requestLine.split(" ");
|
|
1998
2337
|
const authority = parts.length === CONNECT_LINE_TOKENS && parts[0]?.toUpperCase() === "CONNECT" ? parts[1] ?? "" : void 0;
|
|
1999
2338
|
const target = authority === void 0 ? void 0 : parseConnectTarget(authority);
|
|
2000
2339
|
if (target === void 0) {
|
|
2001
|
-
socket.
|
|
2002
|
-
|
|
2340
|
+
refuse(socket, REFUSAL.badRequest);
|
|
2341
|
+
return;
|
|
2342
|
+
}
|
|
2343
|
+
if (!ledger.establish(socket, capability)) {
|
|
2344
|
+
refuse(socket, REFUSAL.serviceUnavailable);
|
|
2003
2345
|
return;
|
|
2004
2346
|
}
|
|
2005
2347
|
socket.write(CONNECT_ESTABLISHED);
|
|
@@ -2017,6 +2359,10 @@ async function blindTunnel(socket, target, effects) {
|
|
|
2017
2359
|
socket.destroy();
|
|
2018
2360
|
return;
|
|
2019
2361
|
}
|
|
2362
|
+
if (socket.destroyed) {
|
|
2363
|
+
upstream.destroy();
|
|
2364
|
+
return;
|
|
2365
|
+
}
|
|
2020
2366
|
socket.pipe(upstream);
|
|
2021
2367
|
upstream.pipe(socket);
|
|
2022
2368
|
const drop = () => {
|
|
@@ -2032,7 +2378,7 @@ async function blindTunnel(socket, target, effects) {
|
|
|
2032
2378
|
socket.destroy();
|
|
2033
2379
|
});
|
|
2034
2380
|
}
|
|
2035
|
-
function
|
|
2381
|
+
function realConnectEffects() {
|
|
2036
2382
|
const plainAgent = new http.Agent({ keepAlive: true });
|
|
2037
2383
|
const tlsAgent = new https.Agent({ keepAlive: true });
|
|
2038
2384
|
const listenOnce = async (port, onSocket) => await new Promise((resolve, reject) => {
|
|
@@ -2161,7 +2507,7 @@ function realMitmEffects() {
|
|
|
2161
2507
|
function isEnoent(error) {
|
|
2162
2508
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
2163
2509
|
}
|
|
2164
|
-
function
|
|
2510
|
+
function realConnectCertStore(paths) {
|
|
2165
2511
|
const read = (file) => {
|
|
2166
2512
|
try {
|
|
2167
2513
|
return fs.readFileSync(file, "utf8");
|
|
@@ -2174,54 +2520,51 @@ function realMitmCertStore(paths) {
|
|
|
2174
2520
|
};
|
|
2175
2521
|
return {
|
|
2176
2522
|
loadCa: () => {
|
|
2177
|
-
const certPem = read(paths.
|
|
2178
|
-
const keyPem = read(paths.
|
|
2523
|
+
const certPem = read(paths.frontdoorCaCertFile);
|
|
2524
|
+
const keyPem = read(paths.frontdoorCaKeyFile);
|
|
2179
2525
|
return certPem === void 0 || keyPem === void 0 ? void 0 : { certPem, keyPem };
|
|
2180
2526
|
},
|
|
2181
2527
|
writeCa: (ca) => {
|
|
2182
|
-
fs.mkdirSync(paths.
|
|
2183
|
-
fs.writeFileSync(paths.
|
|
2184
|
-
fs.writeFileSync(paths.
|
|
2185
|
-
fs.chmodSync(paths.
|
|
2528
|
+
fs.mkdirSync(paths.frontdoorCaDir, { recursive: true });
|
|
2529
|
+
fs.writeFileSync(paths.frontdoorCaCertFile, ca.certPem, "utf8");
|
|
2530
|
+
fs.writeFileSync(paths.frontdoorCaKeyFile, ca.keyPem, { encoding: "utf8", mode: CA_KEY_FILE_MODE });
|
|
2531
|
+
fs.chmodSync(paths.frontdoorCaKeyFile, CA_KEY_FILE_MODE);
|
|
2186
2532
|
}
|
|
2187
2533
|
};
|
|
2188
2534
|
}
|
|
2189
2535
|
|
|
2536
|
+
// src/frontdoor/ensure.ts
|
|
2537
|
+
var import_node_crypto3 = require("node:crypto");
|
|
2538
|
+
|
|
2190
2539
|
// src/headroom/state.ts
|
|
2191
2540
|
var import_node_crypto2 = require("node:crypto");
|
|
2192
|
-
var
|
|
2193
|
-
var
|
|
2541
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
2542
|
+
var import_zod4 = require("zod");
|
|
2194
2543
|
var HEADROOM_ANTHROPIC_UPSTREAM = "https://api.anthropic.com";
|
|
2195
|
-
var HeadroomStateSchema =
|
|
2544
|
+
var HeadroomStateSchema = import_zod4.z.strictObject({
|
|
2196
2545
|
/** The supervisor process owning the daemon. Alive means someone is keeping headroom running. */
|
|
2197
|
-
supervisorPid:
|
|
2546
|
+
supervisorPid: import_zod4.z.number().int().positive().optional(),
|
|
2198
2547
|
/** The headroom proxy process itself. Absent while the supervisor is between restarts. */
|
|
2199
|
-
headroomPid:
|
|
2548
|
+
headroomPid: import_zod4.z.number().int().positive().optional(),
|
|
2200
2549
|
/** 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. */
|
|
2201
|
-
port:
|
|
2202
|
-
/**
|
|
2203
|
-
* 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`.
|
|
2204
|
-
*/
|
|
2205
|
-
mitmPort: import_zod3.z.number().int().positive().optional(),
|
|
2206
|
-
/**
|
|
2207
|
-
* 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.
|
|
2208
|
-
*/
|
|
2209
|
-
lastMitmPort: import_zod3.z.number().int().positive().optional(),
|
|
2550
|
+
port: import_zod4.z.number().int().positive().optional(),
|
|
2210
2551
|
/**
|
|
2211
|
-
* 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
|
|
2552
|
+
* 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.
|
|
2212
2553
|
*/
|
|
2213
|
-
lastPort:
|
|
2554
|
+
lastPort: import_zod4.z.number().int().positive().optional(),
|
|
2214
2555
|
/** The `headroom --version` output of the running install. */
|
|
2215
|
-
version:
|
|
2556
|
+
version: import_zod4.z.string().optional(),
|
|
2216
2557
|
/** Hash of the allowlist the running proxy was started with, so a provider-file change is detected as drift. */
|
|
2217
|
-
allowlistHash:
|
|
2558
|
+
allowlistHash: import_zod4.z.string().optional(),
|
|
2559
|
+
/** Hash of the token-saving settings the running proxy was started with, so a settings change is detected as drift. */
|
|
2560
|
+
settingsHash: import_zod4.z.string().optional(),
|
|
2218
2561
|
/** The install spec the running install was last installed from, so a `source` config change is detected as drift. */
|
|
2219
|
-
installedSource:
|
|
2562
|
+
installedSource: import_zod4.z.string().optional(),
|
|
2220
2563
|
/** The last fatal error, kept across shutdowns so `headroom status` can explain a daemon that is not running. */
|
|
2221
|
-
lastError:
|
|
2564
|
+
lastError: import_zod4.z.string().optional()
|
|
2222
2565
|
});
|
|
2223
|
-
var HeadroomSessionSchema =
|
|
2224
|
-
var HeadroomLockSchema =
|
|
2566
|
+
var HeadroomSessionSchema = import_zod4.z.strictObject({ pid: import_zod4.z.number().int().positive(), startedAt: import_zod4.z.number() });
|
|
2567
|
+
var HeadroomLockSchema = import_zod4.z.strictObject({ pid: import_zod4.z.number().int().positive(), at: import_zod4.z.number() });
|
|
2225
2568
|
function parseJson(raw, schema) {
|
|
2226
2569
|
if (raw === void 0 || raw.trim() === "") {
|
|
2227
2570
|
return void 0;
|
|
@@ -2237,7 +2580,7 @@ function readHeadroomState(fs2, stateFile) {
|
|
|
2237
2580
|
}
|
|
2238
2581
|
}
|
|
2239
2582
|
function writeHeadroomState(fs2, stateFile, state) {
|
|
2240
|
-
fs2.mkdirp(
|
|
2583
|
+
fs2.mkdirp(import_node_path6.default.dirname(stateFile));
|
|
2241
2584
|
fs2.writeFileUtf8(stateFile, `${JSON.stringify(state, null, 2)}
|
|
2242
2585
|
`);
|
|
2243
2586
|
}
|
|
@@ -2249,16 +2592,8 @@ function headroomAllowlist(providers) {
|
|
|
2249
2592
|
return [...urls].sort();
|
|
2250
2593
|
}
|
|
2251
2594
|
function headroomUpstreams(providers, frontDoorOrigin2) {
|
|
2252
|
-
const upstreams =
|
|
2253
|
-
|
|
2254
|
-
for (const provider of providers) {
|
|
2255
|
-
if (isCodexProvider(provider)) {
|
|
2256
|
-
hasCodex = true;
|
|
2257
|
-
} else {
|
|
2258
|
-
upstreams.push({ baseUrl: provider.baseUrl });
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
if (hasCodex && frontDoorOrigin2 !== void 0) {
|
|
2595
|
+
const upstreams = providers.filter((provider) => !isCodexProvider(provider)).map((provider) => ({ baseUrl: provider.baseUrl }));
|
|
2596
|
+
if (providers.length > 0 && frontDoorOrigin2 !== void 0) {
|
|
2262
2597
|
upstreams.push({ baseUrl: frontDoorOrigin2 });
|
|
2263
2598
|
}
|
|
2264
2599
|
return upstreams;
|
|
@@ -2273,7 +2608,7 @@ function readAllProviders(fs2, providersDir) {
|
|
|
2273
2608
|
continue;
|
|
2274
2609
|
}
|
|
2275
2610
|
try {
|
|
2276
|
-
const parsed = parseJson(fs2.readFileUtf8(
|
|
2611
|
+
const parsed = parseJson(fs2.readFileUtf8(import_node_path6.default.join(providersDir, name)), ProviderSchema);
|
|
2277
2612
|
if (parsed !== void 0) {
|
|
2278
2613
|
result.push({ name: name.slice(0, -".json".length), provider: parsed });
|
|
2279
2614
|
}
|
|
@@ -2285,11 +2620,11 @@ function readAllProviders(fs2, providersDir) {
|
|
|
2285
2620
|
}
|
|
2286
2621
|
function writeSession(fs2, sessionsDir, session) {
|
|
2287
2622
|
fs2.mkdirp(sessionsDir);
|
|
2288
|
-
fs2.writeFileUtf8(
|
|
2623
|
+
fs2.writeFileUtf8(import_node_path6.default.join(sessionsDir, `${String(session.pid)}.json`), `${JSON.stringify(session, null, 2)}
|
|
2289
2624
|
`);
|
|
2290
2625
|
}
|
|
2291
2626
|
function removeSession(fs2, sessionsDir, pid) {
|
|
2292
|
-
fs2.removeRecursive(
|
|
2627
|
+
fs2.removeRecursive(import_node_path6.default.join(sessionsDir, `${String(pid)}.json`));
|
|
2293
2628
|
}
|
|
2294
2629
|
function listSessions(fs2, sessionsDir) {
|
|
2295
2630
|
const sessions = [];
|
|
@@ -2298,7 +2633,7 @@ function listSessions(fs2, sessionsDir) {
|
|
|
2298
2633
|
continue;
|
|
2299
2634
|
}
|
|
2300
2635
|
try {
|
|
2301
|
-
const parsed = parseJson(fs2.readFileUtf8(
|
|
2636
|
+
const parsed = parseJson(fs2.readFileUtf8(import_node_path6.default.join(sessionsDir, name)), HeadroomSessionSchema);
|
|
2302
2637
|
if (parsed !== void 0) {
|
|
2303
2638
|
sessions.push(parsed);
|
|
2304
2639
|
}
|
|
@@ -2326,6 +2661,67 @@ function readStartLock(fs2, lockFile) {
|
|
|
2326
2661
|
}
|
|
2327
2662
|
}
|
|
2328
2663
|
|
|
2664
|
+
// src/frontdoor/ensure.ts
|
|
2665
|
+
var FRONTDOOR_START_TIMEOUT_MS = 3e4;
|
|
2666
|
+
var FRONTDOOR_LAUNCHER_POLL_MS = 100;
|
|
2667
|
+
var FrontDoorStartError = class extends CliError {
|
|
2668
|
+
constructor(message) {
|
|
2669
|
+
super(message);
|
|
2670
|
+
this.name = "FrontDoorStartError";
|
|
2671
|
+
}
|
|
2672
|
+
};
|
|
2673
|
+
function ensureFrontDoor(params) {
|
|
2674
|
+
const { paths, ports } = params;
|
|
2675
|
+
const deadline = ports.now() + FRONTDOOR_START_TIMEOUT_MS;
|
|
2676
|
+
let spawned = false;
|
|
2677
|
+
const distrusted = /* @__PURE__ */ new Set();
|
|
2678
|
+
let lastRejection;
|
|
2679
|
+
for (; ; ) {
|
|
2680
|
+
const state = readFrontDoorState(ports.fs, paths.frontdoorStateFile);
|
|
2681
|
+
const supervisorPid = state?.supervisorPid;
|
|
2682
|
+
if (supervisorPid !== void 0 && !distrusted.has(supervisorPid) && ports.isRunning(supervisorPid)) {
|
|
2683
|
+
if (state?.port !== void 0 && state.connectPort !== void 0) {
|
|
2684
|
+
const verdict = ports.verifyListener(state.port);
|
|
2685
|
+
if (verdict.ok) {
|
|
2686
|
+
const token = (0, import_node_crypto3.randomUUID)();
|
|
2687
|
+
writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token });
|
|
2688
|
+
return { port: state.port, connectPort: state.connectPort, token };
|
|
2689
|
+
}
|
|
2690
|
+
lastRejection = `the listener on 127.0.0.1:${String(state.port)} (recorded for pid ${String(supervisorPid)}) failed authentication: ${verdict.reason}`;
|
|
2691
|
+
if (spawned) {
|
|
2692
|
+
throw new FrontDoorStartError(`claude-use: ${lastRejection}; refusing to send this session's credentials to it. Daemon log: ${paths.frontdoorLogPath}`);
|
|
2693
|
+
}
|
|
2694
|
+
distrusted.add(supervisorPid);
|
|
2695
|
+
continue;
|
|
2696
|
+
}
|
|
2697
|
+
if (state?.lastError !== void 0) {
|
|
2698
|
+
throw new FrontDoorStartError(`claude-use: the front door reported a fatal error and is not serving: ${state.lastError} (daemon log: ${paths.frontdoorLogPath})`);
|
|
2699
|
+
}
|
|
2700
|
+
} else if (!spawned) {
|
|
2701
|
+
ports.fs.mkdirp(paths.frontdoorDir);
|
|
2702
|
+
const created = ports.fs.writeFileExclusive(paths.frontdoorLockFile, `${JSON.stringify({ pid: params.launcherPid, at: ports.now() })}
|
|
2703
|
+
`);
|
|
2704
|
+
if (created) {
|
|
2705
|
+
ports.spawnSupervisor(paths);
|
|
2706
|
+
spawned = true;
|
|
2707
|
+
} else {
|
|
2708
|
+
const lock = readStartLock(ports.fs, paths.frontdoorLockFile);
|
|
2709
|
+
if (lock === void 0 || !ports.isRunning(lock.pid)) {
|
|
2710
|
+
ports.fs.removeRecursive(paths.frontdoorLockFile);
|
|
2711
|
+
continue;
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
if (ports.now() >= deadline) {
|
|
2716
|
+
const lastError = state?.lastError;
|
|
2717
|
+
throw new FrontDoorStartError(
|
|
2718
|
+
`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}`
|
|
2719
|
+
);
|
|
2720
|
+
}
|
|
2721
|
+
ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2329
2725
|
// src/headroom/ensure.ts
|
|
2330
2726
|
var HEADROOM_START_TIMEOUT_MS = 12e4;
|
|
2331
2727
|
var HEADROOM_LAUNCHER_POLL_MS = 250;
|
|
@@ -2342,10 +2738,10 @@ function ensureHeadroom(params) {
|
|
|
2342
2738
|
for (; ; ) {
|
|
2343
2739
|
const state = readHeadroomState(ports.fs, paths.headroomStateFile);
|
|
2344
2740
|
if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
|
|
2345
|
-
const daemonUp = state.port !== void 0 && state.
|
|
2346
|
-
if (daemonUp && state.port !== void 0
|
|
2741
|
+
const daemonUp = state.port !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
|
|
2742
|
+
if (daemonUp && state.port !== void 0) {
|
|
2347
2743
|
writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now() });
|
|
2348
|
-
return { port: state.port
|
|
2744
|
+
return { port: state.port };
|
|
2349
2745
|
}
|
|
2350
2746
|
if (state.lastError !== void 0) {
|
|
2351
2747
|
throw new HeadroomStartError(
|
|
@@ -2380,47 +2776,41 @@ function ensureHeadroom(params) {
|
|
|
2380
2776
|
}
|
|
2381
2777
|
}
|
|
2382
2778
|
|
|
2383
|
-
// src/
|
|
2384
|
-
var
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
/** The last fatal error, kept across shutdowns so `frontdoor status` can explain a front door that is not running. */
|
|
2395
|
-
lastError: import_zod4.z.string().optional()
|
|
2396
|
-
});
|
|
2397
|
-
function readFrontDoorState(fs2, stateFile) {
|
|
2398
|
-
let raw;
|
|
2399
|
-
try {
|
|
2400
|
-
raw = fs2.readFileUtf8(stateFile);
|
|
2401
|
-
} catch {
|
|
2402
|
-
return void 0;
|
|
2403
|
-
}
|
|
2404
|
-
if (raw === void 0 || raw.trim() === "") {
|
|
2405
|
-
return void 0;
|
|
2406
|
-
}
|
|
2407
|
-
try {
|
|
2408
|
-
const parsed = FrontDoorStateSchema.safeParse(JSON.parse(raw));
|
|
2409
|
-
return parsed.success ? parsed.data : void 0;
|
|
2410
|
-
} catch {
|
|
2411
|
-
return void 0;
|
|
2412
|
-
}
|
|
2779
|
+
// src/headroom/settings.ts
|
|
2780
|
+
var import_node_crypto4 = require("node:crypto");
|
|
2781
|
+
function settingsOf(config) {
|
|
2782
|
+
return {
|
|
2783
|
+
...config.mode === void 0 ? {} : { mode: config.mode },
|
|
2784
|
+
...config.targetRatio === void 0 ? {} : { targetRatio: config.targetRatio },
|
|
2785
|
+
...config.ccr === void 0 ? {} : { ccr: config.ccr },
|
|
2786
|
+
...config.rolloutChannel === void 0 ? {} : { rolloutChannel: config.rolloutChannel },
|
|
2787
|
+
...config.interceptToolResults === void 0 ? {} : { interceptToolResults: config.interceptToolResults },
|
|
2788
|
+
...config.readMaturation === void 0 ? {} : { readMaturation: config.readMaturation }
|
|
2789
|
+
};
|
|
2413
2790
|
}
|
|
2414
|
-
function
|
|
2415
|
-
|
|
2416
|
-
|
|
2791
|
+
function settingsArgs(settings) {
|
|
2792
|
+
return [
|
|
2793
|
+
...settings.mode === void 0 ? [] : ["--mode", settings.mode],
|
|
2794
|
+
...settings.targetRatio === void 0 ? [] : ["--target-ratio", String(settings.targetRatio)],
|
|
2795
|
+
...settings.ccr === "lossless" ? ["--lossless"] : [],
|
|
2796
|
+
...settings.ccr === "none" ? ["--no-ccr"] : [],
|
|
2797
|
+
...settings.interceptToolResults === true ? ["--intercept-tool-results"] : [],
|
|
2798
|
+
...settings.readMaturation === true ? ["--read-maturation"] : []
|
|
2799
|
+
];
|
|
2800
|
+
}
|
|
2801
|
+
function settingsEnv(settings) {
|
|
2802
|
+
return settings.rolloutChannel === void 0 ? {} : { HEADROOM_ROLLOUT_CHANNEL: settings.rolloutChannel };
|
|
2803
|
+
}
|
|
2804
|
+
function hashSettings(settings) {
|
|
2805
|
+
return (0, import_node_crypto4.createHash)("sha256").update(JSON.stringify([...settingsArgs(settings), JSON.stringify(settingsEnv(settings))])).digest("hex");
|
|
2417
2806
|
}
|
|
2418
2807
|
|
|
2419
2808
|
// src/headroom/supervisor.ts
|
|
2420
2809
|
function resolveSupervisorConfig(configured) {
|
|
2421
2810
|
return {
|
|
2422
2811
|
source: configured.source ?? HEADROOM_DEFAULT_SOURCE,
|
|
2423
|
-
idleShutdownMinutes: configured.idleShutdownMinutes ?? HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES
|
|
2812
|
+
idleShutdownMinutes: configured.idleShutdownMinutes ?? HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES,
|
|
2813
|
+
settings: settingsOf(configured)
|
|
2424
2814
|
};
|
|
2425
2815
|
}
|
|
2426
2816
|
var HEADROOM_BACKOFF_BASE_MS = 500;
|
|
@@ -2428,7 +2818,7 @@ var HEADROOM_BACKOFF_CAP_MS = 3e4;
|
|
|
2428
2818
|
var HEADROOM_START_RETRY_BUDGET = 5;
|
|
2429
2819
|
var HEADROOM_READY_TIMEOUT_MS = 15e3;
|
|
2430
2820
|
var HEADROOM_POLL_MS = 1e3;
|
|
2431
|
-
var
|
|
2821
|
+
var MS_PER_MINUTE2 = 6e4;
|
|
2432
2822
|
function backoffForAttempt(attempt) {
|
|
2433
2823
|
return Math.min(HEADROOM_BACKOFF_CAP_MS, HEADROOM_BACKOFF_BASE_MS * 2 ** (attempt - 1));
|
|
2434
2824
|
}
|
|
@@ -2483,18 +2873,13 @@ function compareVersions(a, b) {
|
|
|
2483
2873
|
return 0;
|
|
2484
2874
|
}
|
|
2485
2875
|
var HEADROOM_SUPERVISOR_STILL_RUNNING = -1;
|
|
2486
|
-
async function runSupervisor(
|
|
2876
|
+
async function runSupervisor(initialConfig, ports, options = {}) {
|
|
2487
2877
|
const { fs: fs2, paths } = ports;
|
|
2878
|
+
let config = initialConfig;
|
|
2488
2879
|
const previousState = readHeadroomState(fs2, paths.headroomStateFile);
|
|
2489
2880
|
let installedSource = previousState?.installedSource;
|
|
2490
2881
|
let lastPort = previousState?.lastPort;
|
|
2491
|
-
|
|
2492
|
-
let daemonPort;
|
|
2493
|
-
const sticky = () => ({
|
|
2494
|
-
...lastPort === void 0 ? {} : { lastPort },
|
|
2495
|
-
...lastMitmPort === void 0 ? {} : { lastMitmPort }
|
|
2496
|
-
});
|
|
2497
|
-
let mitm;
|
|
2882
|
+
const sticky = () => lastPort === void 0 ? {} : { lastPort };
|
|
2498
2883
|
const fail = (message) => {
|
|
2499
2884
|
writeHeadroomState(fs2, paths.headroomStateFile, {
|
|
2500
2885
|
lastError: message,
|
|
@@ -2523,18 +2908,7 @@ async function runSupervisor(config, ports, options = {}) {
|
|
|
2523
2908
|
return fail(`could not install headroom from ${config.source}: install failed (is uv installed and on PATH?)`);
|
|
2524
2909
|
}
|
|
2525
2910
|
const version = ports.headroomVersion() ?? "unknown";
|
|
2526
|
-
|
|
2527
|
-
mitm = await ports.startMitm(lastMitmPort, () => daemonPort);
|
|
2528
|
-
} catch (error) {
|
|
2529
|
-
return fail(`could not start the MITM proxy: ${error instanceof Error ? error.message : String(error)}`);
|
|
2530
|
-
}
|
|
2531
|
-
lastMitmPort = mitm.port;
|
|
2532
|
-
if (previousState?.lastMitmPort !== void 0 && mitm.port !== previousState.lastMitmPort) {
|
|
2533
|
-
ports.log(
|
|
2534
|
-
`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)`
|
|
2535
|
-
);
|
|
2536
|
-
}
|
|
2537
|
-
writeHeadroomState(fs2, paths.headroomStateFile, { supervisorPid: ports.ownPid, version, installedSource, mitmPort: mitm.port, ...sticky() });
|
|
2911
|
+
writeHeadroomState(fs2, paths.headroomStateFile, { supervisorPid: ports.ownPid, version, installedSource, ...sticky() });
|
|
2538
2912
|
ports.log(`claude-use headroom supervisor ${String(ports.ownPid)}: managing headroom on allowlist [${allowlistOf(ports).join(", ")}]`);
|
|
2539
2913
|
const orphanPid = previousState?.headroomPid;
|
|
2540
2914
|
if (orphanPid !== void 0 && ports.isRunning(orphanPid)) {
|
|
@@ -2543,6 +2917,7 @@ async function runSupervisor(config, ports, options = {}) {
|
|
|
2543
2917
|
}
|
|
2544
2918
|
let headroomPid;
|
|
2545
2919
|
let runningHash;
|
|
2920
|
+
let runningSettingsHash;
|
|
2546
2921
|
let consecutiveFailures = 0;
|
|
2547
2922
|
let idleSince;
|
|
2548
2923
|
let ticks = 0;
|
|
@@ -2551,6 +2926,8 @@ async function runSupervisor(config, ports, options = {}) {
|
|
|
2551
2926
|
return HEADROOM_SUPERVISOR_STILL_RUNNING;
|
|
2552
2927
|
}
|
|
2553
2928
|
ticks += 1;
|
|
2929
|
+
config = ports.readConfig();
|
|
2930
|
+
const settingsHash = hashSettings(config.settings);
|
|
2554
2931
|
const allowlist = allowlistOf(ports);
|
|
2555
2932
|
const allowlistHash = hashAllowlist(allowlist);
|
|
2556
2933
|
pruneDeadSessions(fs2, paths.headroomSessionsDir, ports.isRunning);
|
|
@@ -2559,13 +2936,12 @@ async function runSupervisor(config, ports, options = {}) {
|
|
|
2559
2936
|
if (crashed) {
|
|
2560
2937
|
ports.log(`claude-use headroom supervisor: headroom pid ${String(headroomPid)} died`);
|
|
2561
2938
|
headroomPid = void 0;
|
|
2562
|
-
daemonPort = void 0;
|
|
2563
2939
|
runningHash = void 0;
|
|
2940
|
+
runningSettingsHash = void 0;
|
|
2564
2941
|
writeHeadroomState(fs2, paths.headroomStateFile, {
|
|
2565
2942
|
supervisorPid: ports.ownPid,
|
|
2566
2943
|
version,
|
|
2567
2944
|
installedSource,
|
|
2568
|
-
mitmPort: mitm.port,
|
|
2569
2945
|
...sticky()
|
|
2570
2946
|
});
|
|
2571
2947
|
}
|
|
@@ -2577,13 +2953,13 @@ async function runSupervisor(config, ports, options = {}) {
|
|
|
2577
2953
|
}
|
|
2578
2954
|
const previousSticky = lastPort;
|
|
2579
2955
|
const port = lastPort !== void 0 && await ports.isPortFree(lastPort) ? lastPort : await ports.freePort();
|
|
2580
|
-
const pid = ports.spawnHeadroom(port, allowlist);
|
|
2956
|
+
const pid = ports.spawnHeadroom(port, allowlist, config.settings);
|
|
2581
2957
|
const ready = await waitUntilReady(ports, port);
|
|
2582
2958
|
if (ready) {
|
|
2583
2959
|
consecutiveFailures = 0;
|
|
2584
2960
|
headroomPid = pid;
|
|
2585
|
-
daemonPort = port;
|
|
2586
2961
|
runningHash = allowlistHash;
|
|
2962
|
+
runningSettingsHash = settingsHash;
|
|
2587
2963
|
lastPort = port;
|
|
2588
2964
|
if (previousSticky !== void 0 && port !== previousSticky) {
|
|
2589
2965
|
ports.log(
|
|
@@ -2594,9 +2970,9 @@ async function runSupervisor(config, ports, options = {}) {
|
|
|
2594
2970
|
supervisorPid: ports.ownPid,
|
|
2595
2971
|
headroomPid: pid,
|
|
2596
2972
|
port,
|
|
2597
|
-
mitmPort: mitm.port,
|
|
2598
2973
|
version,
|
|
2599
2974
|
allowlistHash,
|
|
2975
|
+
settingsHash,
|
|
2600
2976
|
installedSource: config.source,
|
|
2601
2977
|
...sticky()
|
|
2602
2978
|
});
|
|
@@ -2613,13 +2989,13 @@ async function runSupervisor(config, ports, options = {}) {
|
|
|
2613
2989
|
continue;
|
|
2614
2990
|
}
|
|
2615
2991
|
} else {
|
|
2616
|
-
if (runningHash !== allowlistHash || installedSource !== config.source) {
|
|
2992
|
+
if (runningHash !== allowlistHash || runningSettingsHash !== settingsHash || installedSource !== config.source) {
|
|
2617
2993
|
if (listSessions(fs2, paths.headroomSessionsDir).length === 0) {
|
|
2618
2994
|
ports.log("claude-use headroom supervisor: configuration drifted and no sessions are live; restarting headroom");
|
|
2619
2995
|
ports.stopProcess(headroomPid);
|
|
2620
2996
|
headroomPid = void 0;
|
|
2621
|
-
daemonPort = void 0;
|
|
2622
2997
|
runningHash = void 0;
|
|
2998
|
+
runningSettingsHash = void 0;
|
|
2623
2999
|
continue;
|
|
2624
3000
|
}
|
|
2625
3001
|
}
|
|
@@ -2627,13 +3003,11 @@ async function runSupervisor(config, ports, options = {}) {
|
|
|
2627
3003
|
if (sessions.length === 0) {
|
|
2628
3004
|
idleSince ??= ports.now();
|
|
2629
3005
|
const idleMs = ports.now() - idleSince;
|
|
2630
|
-
if (idleMs >= config.idleShutdownMinutes *
|
|
3006
|
+
if (idleMs >= config.idleShutdownMinutes * MS_PER_MINUTE2) {
|
|
2631
3007
|
ports.log(
|
|
2632
|
-
`claude-use headroom supervisor: no sessions for ${String(config.idleShutdownMinutes)} minute(s); stopping headroom and
|
|
3008
|
+
`claude-use headroom supervisor: no sessions for ${String(config.idleShutdownMinutes)} minute(s); stopping headroom and exiting`
|
|
2633
3009
|
);
|
|
2634
3010
|
ports.stopProcess(headroomPid);
|
|
2635
|
-
daemonPort = void 0;
|
|
2636
|
-
await mitm.close();
|
|
2637
3011
|
writeHeadroomState(fs2, paths.headroomStateFile, {
|
|
2638
3012
|
version,
|
|
2639
3013
|
...sticky()
|
|
@@ -2716,15 +3090,18 @@ function evaluateAmbientCredentialGuard(params) {
|
|
|
2716
3090
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2717
3091
|
0 && (module.exports = {
|
|
2718
3092
|
AMBIENT_CREDENTIAL_VARS,
|
|
3093
|
+
CONNECT_INTERCEPT_HOST,
|
|
3094
|
+
CONNECT_LIMITS,
|
|
2719
3095
|
FARM_MANIFEST_FILENAME,
|
|
2720
|
-
|
|
3096
|
+
FrontDoorStartError,
|
|
2721
3097
|
HeadroomStartError,
|
|
2722
|
-
|
|
3098
|
+
ROUTED_PATH_PREFIX,
|
|
2723
3099
|
buildEntryFacts,
|
|
2724
3100
|
carryOver,
|
|
2725
3101
|
createLeafCache,
|
|
2726
3102
|
detectAmbientCredential,
|
|
2727
3103
|
ensureCa,
|
|
3104
|
+
ensureFrontDoor,
|
|
2728
3105
|
ensureHeadroom,
|
|
2729
3106
|
evaluateAmbientCredentialGuard,
|
|
2730
3107
|
formatAmbientCredentialGuardMessage,
|
|
@@ -2734,15 +3111,16 @@ function evaluateAmbientCredentialGuard(params) {
|
|
|
2734
3111
|
mintLeaf,
|
|
2735
3112
|
parseConnectTarget,
|
|
2736
3113
|
readFarmManifest,
|
|
2737
|
-
|
|
2738
|
-
|
|
3114
|
+
realConnectCertStore,
|
|
3115
|
+
realConnectEffects,
|
|
2739
3116
|
recoverFarm,
|
|
2740
3117
|
recoveryDiagnostics,
|
|
2741
3118
|
resolveDecisions,
|
|
2742
3119
|
resolveSupervisorConfig,
|
|
2743
3120
|
resyncFarm,
|
|
3121
|
+
runFrontDoorSupervisor,
|
|
2744
3122
|
runSupervisor,
|
|
2745
|
-
|
|
2746
|
-
|
|
3123
|
+
servedByPipeline,
|
|
3124
|
+
startConnectServer,
|
|
2747
3125
|
topLevelNames
|
|
2748
3126
|
});
|