agent-shim 9.12.0 → 9.13.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
@@ -2573,7 +2573,7 @@ function listFrontDoorSessions(fs12, sessionsDir) {
2573
2573
  try {
2574
2574
  const parsed = FrontDoorSessionSchema.safeParse(JSON.parse(fs12.readFileUtf8(path8.join(sessionsDir, name)) ?? ""));
2575
2575
  if (parsed.success) {
2576
- sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt });
2576
+ sessions.push({ pid: parsed.data.pid, startedAt: parsed.data.startedAt, ...parsed.data.supervisorPid === void 0 ? {} : { supervisorPid: parsed.data.supervisorPid } });
2577
2577
  }
2578
2578
  } catch {
2579
2579
  continue;
@@ -2599,7 +2599,7 @@ var init_state = __esm({
2599
2599
  "src/frontdoor/state.ts"() {
2600
2600
  "use strict";
2601
2601
  FRONT_DOOR_PROTOCOL = 3;
2602
- FrontDoorSessionSchema = z3.strictObject({ pid: z3.number().int().positive(), startedAt: z3.number(), token: z3.string().min(1) });
2602
+ FrontDoorSessionSchema = z3.strictObject({ pid: z3.number().int().positive(), startedAt: z3.number(), token: z3.string().min(1), supervisorPid: z3.number().int().positive().optional() });
2603
2603
  FrontDoorStateSchema = z3.strictObject({
2604
2604
  /**
2605
2605
  * The launcher-to-door wire protocol this supervisor speaks, written once it is serving; absent in state written by a release that predates the field, which `ensureFrontDoor` reads as protocol 0. A launcher replaces a door whose protocol is lower than its own (see `FRONT_DOOR_PROTOCOL`).
@@ -2639,7 +2639,7 @@ var init_package = __esm({
2639
2639
  "package.json"() {
2640
2640
  package_default = {
2641
2641
  name: "agent-shim",
2642
- version: "9.12.0",
2642
+ version: "9.13.0",
2643
2643
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
2644
2644
  license: "MIT",
2645
2645
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -2742,6 +2742,36 @@ var init_package = __esm({
2742
2742
  }
2743
2743
  });
2744
2744
 
2745
+ // src/frontdoor/supervisorProcesses.ts
2746
+ function parseFrontDoorSupervisorPids(psOutput) {
2747
+ const pids = [];
2748
+ for (const line of psOutput.split("\n")) {
2749
+ const [pidText, ...argumentsList] = line.trim().split(/\s+/);
2750
+ const pid = Number(pidText);
2751
+ if (Number.isInteger(pid) && pid > 0 && argumentsList.includes(FRONT_DOOR_SUPERVISOR_ARGUMENT)) {
2752
+ pids.push(pid);
2753
+ }
2754
+ }
2755
+ return pids.sort((a, b) => a - b);
2756
+ }
2757
+ function listFrontDoorSupervisors(run, uid) {
2758
+ const result = run.run("ps", ["-U", String(uid), "-o", "pid=,command="]);
2759
+ if (result.status === null) {
2760
+ return { ok: false, message: "ps could not be run" };
2761
+ }
2762
+ if (result.status !== 0) {
2763
+ return { ok: false, message: `ps exited ${String(result.status)}${result.stderr.trim() === "" ? "" : `: ${result.stderr.trim()}`}` };
2764
+ }
2765
+ return { ok: true, pids: parseFrontDoorSupervisorPids(result.stdout) };
2766
+ }
2767
+ var FRONT_DOOR_SUPERVISOR_ARGUMENT;
2768
+ var init_supervisorProcesses = __esm({
2769
+ "src/frontdoor/supervisorProcesses.ts"() {
2770
+ "use strict";
2771
+ FRONT_DOOR_SUPERVISOR_ARGUMENT = "__frontdoor-supervisor";
2772
+ }
2773
+ });
2774
+
2745
2775
  // src/headroom/state.ts
2746
2776
  import { createHash as createHash3 } from "node:crypto";
2747
2777
  import path11 from "node:path";
@@ -3338,9 +3368,15 @@ async function runSupervisor(initialConfig, ports, options = {}) {
3338
3368
  await ports.sleep(HEADROOM_POLL_MS);
3339
3369
  }
3340
3370
  }
3371
+ function currentHeadroomAllowlistInputs(fs12, paths) {
3372
+ return {
3373
+ providers: readAllProviders(fs12, paths.providersDir).map((entry) => entry.provider),
3374
+ frontDoorOrigin: frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile))
3375
+ };
3376
+ }
3341
3377
  function currentHeadroomAllowlist(fs12, paths) {
3342
- const providers = readAllProviders(fs12, paths.providersDir).map((entry) => entry.provider);
3343
- return headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin(readFrontDoorState(fs12, paths.frontdoorStateFile))));
3378
+ const inputs = currentHeadroomAllowlistInputs(fs12, paths);
3379
+ return headroomAllowlist(headroomUpstreams(inputs.providers, inputs.frontDoorOrigin));
3344
3380
  }
3345
3381
  function allowlistOf(ports) {
3346
3382
  return currentHeadroomAllowlist(ports.fs, ports.paths);
@@ -3408,6 +3444,10 @@ function realIsProcessZombie(pid) {
3408
3444
  function realIsProcessRunning(pid) {
3409
3445
  return realIsProcessAlive(pid) && !realIsProcessZombie(pid);
3410
3446
  }
3447
+ function realIsFrontDoorSupervisor(pid) {
3448
+ const result = spawnSync("ps", ["-o", "pid=,command=", "-p", String(pid)], { encoding: "utf8" });
3449
+ return result.status === 0 && parseFrontDoorSupervisorPids(result.stdout).includes(pid);
3450
+ }
3411
3451
  function expandHome2(filePath) {
3412
3452
  return filePath.startsWith("~/") ? path13.join(os3.homedir(), filePath.slice(1)) : filePath;
3413
3453
  }
@@ -3611,6 +3651,7 @@ var init_realPorts = __esm({
3611
3651
  "use strict";
3612
3652
  init_load();
3613
3653
  init_versionDiscovery();
3654
+ init_supervisorProcesses();
3614
3655
  init_ensure();
3615
3656
  init_supervisor();
3616
3657
  init_state2();
@@ -4645,7 +4686,7 @@ function assessIdentity(member, nowMs) {
4645
4686
  );
4646
4687
  if (blockedUntil > nowMs) {
4647
4688
  if (unified.overageStatus === "allowed") {
4648
- return { candidate: { ...base, class: "pay-per-use", reasons: [`plan exhausted until ${new Date(blockedUntil).toISOString()}, continues as extra usage`, ...windowReasons, ...planReasons] } };
4689
+ return { candidate: { ...base, class: "pay-per-use", planReturnsAtMs: blockedUntil, reasons: [`plan exhausted until ${new Date(blockedUntil).toISOString()} (in ${formatAge(blockedUntil - nowMs)}), continues as extra usage`, ...windowReasons, ...planReasons] } };
4649
4690
  }
4650
4691
  return { candidate: { ...base, class: "ineligible", blockedUntilMs: blockedUntil, reasons: [`refused until ${new Date(blockedUntil).toISOString()} (in ${formatAge(blockedUntil - nowMs)})`, ...unified.fallbackAvailable === true ? ["a fallback is on offer, so requests for some models may still be served"] : [], ...windowReasons, ...overageReasons, ...planReasons] } };
4651
4692
  }
@@ -4760,7 +4801,8 @@ function rankPool(input) {
4760
4801
  return {
4761
4802
  candidates: ordered,
4762
4803
  ...pick === void 0 ? { ...earliestReturn === void 0 ? {} : { earliestReturn } } : { pick },
4763
- ...movedOff === void 0 || pick === void 0 ? {} : { movedOff }
4804
+ ...movedOff === void 0 || pick === void 0 ? {} : { movedOff },
4805
+ ...pick?.planReturnsAtMs === void 0 ? {} : { planReturn: { identity: pick.identity, atMs: pick.planReturnsAtMs } }
4764
4806
  };
4765
4807
  }
4766
4808
  var MS_PER_SECOND4, MS_PER_HOUR2, HOURS_PER_DAY2, FIVE_HOURS, PROMPT_CACHE_TTL_HOURS, PERCENT, SEVEN_DAYS, FIVE_HOUR_WINDOW_MS, SEVEN_DAY_WINDOW_MS, PROMPT_CACHE_TTL_MS, CLASS_ORDER;
@@ -6140,32 +6182,50 @@ function ensureFrontDoor(params) {
6140
6182
  let replaced = false;
6141
6183
  const distrusted = /* @__PURE__ */ new Set();
6142
6184
  let lastRejection;
6185
+ const verifyWithRetry = (port) => {
6186
+ let verdict = ports.verifyListener(port);
6187
+ for (let attempt = 1; !verdict.ok && attempt < FRONTDOOR_PROBE_ATTEMPTS; attempt += 1) {
6188
+ ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
6189
+ verdict = ports.verifyListener(port);
6190
+ }
6191
+ return verdict;
6192
+ };
6193
+ const stopAndAwaitExit = (supervisorPid, failure) => {
6194
+ ports.stopSupervisor(supervisorPid);
6195
+ while (ports.isRunning(supervisorPid)) {
6196
+ if (ports.now() >= deadline) {
6197
+ throw new FrontDoorStartError(`${failure}. Daemon log: ${paths.frontdoorLogPath}`);
6198
+ }
6199
+ ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
6200
+ }
6201
+ };
6143
6202
  for (; ; ) {
6144
6203
  const state = readFrontDoorState(ports.fs, paths.frontdoorStateFile);
6145
6204
  const supervisorPid = state?.supervisorPid;
6146
6205
  if (supervisorPid !== void 0 && !distrusted.has(supervisorPid) && ports.isRunning(supervisorPid)) {
6147
6206
  if (state?.port !== void 0 && state.connectPort !== void 0) {
6148
- const verdict = ports.verifyListener(state.port);
6207
+ const verdict = verifyWithRetry(state.port);
6149
6208
  if (verdict.ok && !replaced && !spawned && (params.replace === true || (state.protocol ?? 0) < FRONT_DOOR_PROTOCOL)) {
6150
- ports.stopSupervisor(supervisorPid);
6151
- while (ports.isRunning(supervisorPid)) {
6152
- if (ports.now() >= deadline) {
6153
- throw new FrontDoorStartError(`the front door (pid ${String(supervisorPid)}, protocol ${String(state.protocol ?? 0)}; this launcher speaks protocol ${String(FRONT_DOOR_PROTOCOL)}) was asked to be replaced and did not exit. Daemon log: ${paths.frontdoorLogPath}`);
6154
- }
6155
- ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
6156
- }
6209
+ stopAndAwaitExit(
6210
+ supervisorPid,
6211
+ `the front door (pid ${String(supervisorPid)}, protocol ${String(state.protocol ?? 0)}; this launcher speaks protocol ${String(FRONT_DOOR_PROTOCOL)}) was asked to be replaced and did not exit`
6212
+ );
6157
6213
  replaced = true;
6158
6214
  continue;
6159
6215
  }
6160
6216
  if (verdict.ok) {
6161
6217
  const token = randomUUID3();
6162
- writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token });
6218
+ writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token, supervisorPid });
6163
6219
  return { port: state.port, connectPort: state.connectPort, token };
6164
6220
  }
6165
6221
  lastRejection = `the listener on 127.0.0.1:${String(state.port)} (recorded for pid ${String(supervisorPid)}) failed authentication: ${verdict.reason}`;
6166
6222
  if (spawned) {
6167
6223
  throw new FrontDoorStartError(`${lastRejection}; refusing to send this session's credentials to it. Daemon log: ${paths.frontdoorLogPath}`);
6168
6224
  }
6225
+ if (ports.isFrontDoorSupervisor(supervisorPid)) {
6226
+ stopAndAwaitExit(supervisorPid, `the front door (pid ${String(supervisorPid)}) stopped answering and did not exit when asked to`);
6227
+ continue;
6228
+ }
6169
6229
  distrusted.add(supervisorPid);
6170
6230
  continue;
6171
6231
  }
@@ -6196,7 +6256,7 @@ function ensureFrontDoor(params) {
6196
6256
  ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
6197
6257
  }
6198
6258
  }
6199
- var FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FrontDoorStartError;
6259
+ var FRONTDOOR_START_TIMEOUT_MS, FRONTDOOR_LAUNCHER_POLL_MS, FRONTDOOR_PROBE_ATTEMPTS, FrontDoorStartError;
6200
6260
  var init_ensure2 = __esm({
6201
6261
  "src/frontdoor/ensure.ts"() {
6202
6262
  "use strict";
@@ -6205,6 +6265,7 @@ var init_ensure2 = __esm({
6205
6265
  init_state();
6206
6266
  FRONTDOOR_START_TIMEOUT_MS = 3e4;
6207
6267
  FRONTDOOR_LAUNCHER_POLL_MS = 100;
6268
+ FRONTDOOR_PROBE_ATTEMPTS = 3;
6208
6269
  FrontDoorStartError = class extends CliError {
6209
6270
  constructor(message) {
6210
6271
  super(message);
@@ -6688,7 +6749,12 @@ function resolvePoolLaunch(params) {
6688
6749
  if (graph.ranking.candidates.length === 0) {
6689
6750
  return { ok: false, message: `agent-shim: no member of pool "${poolName}" is an existing identity.` };
6690
6751
  }
6691
- const { pick, earliestReturn, movedOff } = graph.ranking;
6752
+ const { pick, earliestReturn, movedOff, planReturn } = graph.ranking;
6753
+ if (pick !== void 0 && params.wait && planReturn !== void 0) {
6754
+ log.info(`agent-shim: pool "${poolName}" would continue ${planReturn.identity} on extra usage; waiting until ${new Date(planReturn.atMs).toISOString()} for its plan window`);
6755
+ params.sleep(Math.max(planReturn.atMs - nowMs, 0));
6756
+ continue;
6757
+ }
6692
6758
  if (pick !== void 0) {
6693
6759
  if (params.recordPick) {
6694
6760
  recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
@@ -7391,6 +7457,7 @@ function realEnsurePorts(paths, spawnDaemon) {
7391
7457
  now: () => Date.now(),
7392
7458
  sleep: realSleepSync,
7393
7459
  spawnSupervisor: (layout) => spawnDaemon(layout, "__frontdoor-supervisor", layout.frontdoorLogPath),
7460
+ isFrontDoorSupervisor: realIsFrontDoorSupervisor,
7394
7461
  stopSupervisor: (pid) => {
7395
7462
  process.kill(pid, "SIGTERM");
7396
7463
  },
@@ -8291,16 +8358,27 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
8291
8358
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http3.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
8292
8359
  let idleSince;
8293
8360
  let ticks = 0;
8361
+ const supersedingOwner = () => {
8362
+ const owner = readFrontDoorState(fs12, paths.frontdoorStateFile)?.supervisorPid;
8363
+ return owner !== void 0 && owner !== ports.ownPid && ports.isRunning(owner) ? owner : void 0;
8364
+ };
8365
+ let supersededBy;
8366
+ let served;
8294
8367
  const binaryReplaced = () => {
8295
8368
  const current = ports.statOwnExecutable();
8296
8369
  return current !== void 0 && servingBinary !== void 0 && (current.dev !== servingBinary.dev || current.ino !== servingBinary.ino || current.size !== servingBinary.size || current.mtimeMs !== servingBinary.mtimeMs);
8297
8370
  };
8298
- const shutdown = async () => {
8371
+ const closeServing = async () => {
8299
8372
  await direct.close();
8300
8373
  await connect3.close();
8301
8374
  await http3.close();
8302
8375
  ports.closeRcStreamHub();
8303
- writeFrontDoorState(fs12, paths.frontdoorStateFile, sticky());
8376
+ };
8377
+ const shutdown = async () => {
8378
+ await closeServing();
8379
+ if (supersedingOwner() === void 0) {
8380
+ writeFrontDoorState(fs12, paths.frontdoorStateFile, sticky());
8381
+ }
8304
8382
  return 0;
8305
8383
  };
8306
8384
  for (; ; ) {
@@ -8313,7 +8391,28 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
8313
8391
  ports.observeLaunchRegistry(listed, pruned);
8314
8392
  ports.checkQuotaExpiry();
8315
8393
  const prunedPids = new Set(pruned);
8316
- if (listed.filter((session) => !prunedPids.has(session.pid)).length === 0) {
8394
+ const live = listed.filter((session) => !prunedPids.has(session.pid));
8395
+ if (supersededBy === void 0) {
8396
+ supersededBy = supersedingOwner();
8397
+ if (supersededBy !== void 0) {
8398
+ ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: supervisor ${String(supersededBy)} now owns the front door; taking no new sessions and exiting once the sessions this door serves have ended`);
8399
+ ports.doorHealth.superseded(supersededBy);
8400
+ await ports.sleep(FRONTDOOR_POLL_MS);
8401
+ continue;
8402
+ }
8403
+ } else {
8404
+ const owner = supersededBy;
8405
+ served = (served ?? live.filter((session) => session.pid !== ports.ownPid && session.pid !== owner && (session.supervisorPid === void 0 || session.supervisorPid === ports.ownPid))).filter((own) => live.some((session) => session.pid === own.pid && session.startedAt === own.startedAt));
8406
+ if (served.length === 0) {
8407
+ ports.log("agent-shim frontdoor supervisor: the sessions this superseded door served have ended; closing the front door and exiting");
8408
+ ports.doorHealth.drained();
8409
+ await closeServing();
8410
+ return 0;
8411
+ }
8412
+ await ports.sleep(FRONTDOOR_POLL_MS);
8413
+ continue;
8414
+ }
8415
+ if (live.length === 0) {
8317
8416
  if (ticks > 1 && binaryReplaced()) {
8318
8417
  ports.log("agent-shim frontdoor supervisor: the installed binary changed and no sessions are live; turning the door over for the next launch");
8319
8418
  ports.doorHealth.binaryTurnover();
@@ -12467,7 +12566,55 @@ init_credential();
12467
12566
  init_credentialCache();
12468
12567
  init_realCredentialCache();
12469
12568
  init_source();
12569
+
12570
+ // src/headroom/allowlistDrift.ts
12571
+ init_state2();
12572
+ function diagnoseAllowlistDrift(params) {
12573
+ const { recordedHash, providers, frontDoorOrigin: frontDoorOrigin2 } = params;
12574
+ if (recordedHash === void 0 || recordedHash === hashAllowlist(headroomAllowlist(headroomUpstreams(providers, frontDoorOrigin2)))) {
12575
+ return void 0;
12576
+ }
12577
+ const originIsInput = providers.length > 0 && frontDoorOrigin2 !== void 0;
12578
+ if (!originIsInput) {
12579
+ return ["provider-files"];
12580
+ }
12581
+ return recordedHash === hashAllowlist(headroomAllowlist(headroomUpstreams(providers, void 0))) ? ["front-door-origin"] : ["provider-files", "front-door-origin"];
12582
+ }
12583
+
12584
+ // src/doctorReport.ts
12470
12585
  init_state2();
12586
+ init_supervisor();
12587
+ init_state();
12588
+
12589
+ // src/doctorFrontDoor.ts
12590
+ function pushFrontDoor(push, supervisors, registeredPid) {
12591
+ if (!supervisors.ok) {
12592
+ push("frontdoor", "warn", `Could not list processes to look for duplicate front door supervisors: ${supervisors.message}.`);
12593
+ return;
12594
+ }
12595
+ const { pids } = supervisors;
12596
+ if (pids.length === 0) {
12597
+ push("frontdoor", "pass", "No front door supervisor is running.");
12598
+ return;
12599
+ }
12600
+ const [only, ...rest] = pids;
12601
+ if (only !== void 0 && rest.length === 0) {
12602
+ push("frontdoor", "pass", `One front door supervisor is running (pid ${String(only)}).`);
12603
+ return;
12604
+ }
12605
+ const serving = registeredPid !== void 0 && pids.includes(registeredPid) ? `The front door state file names pid ${String(registeredPid)} as the serving supervisor.` : "The front door state file names no running supervisor.";
12606
+ for (const pid of pids.filter((candidate) => candidate !== registeredPid)) {
12607
+ push(
12608
+ "frontdoor",
12609
+ "fail",
12610
+ `Front door supervisor pid ${String(pid)} is running beside ${String(pids.length - 1)} other(s). ${serving} Stop it with \`kill ${String(pid)}\`; launches still connected to it lose their door.`,
12611
+ String(pid)
12612
+ );
12613
+ }
12614
+ }
12615
+
12616
+ // src/doctorReport.ts
12617
+ init_supervisorProcesses();
12471
12618
  init_legacy();
12472
12619
  init_providersStore();
12473
12620
  init_guard();
@@ -12490,7 +12637,8 @@ var DOCTOR_SECTIONS = [
12490
12637
  "global-config",
12491
12638
  "categories-local",
12492
12639
  "active-identity",
12493
- "headroom"
12640
+ "headroom",
12641
+ "frontdoor"
12494
12642
  ];
12495
12643
  function refinePathShadow(status, ownExecutablePath, realpath) {
12496
12644
  if (status.status !== "shadowed") {
@@ -12886,6 +13034,17 @@ function runDoctor(params) {
12886
13034
  `Headroom daemon is up on unix socket ${state.socketPath} (supervisor ${String(state.supervisorPid)}, daemon ${String(state.headroomPid)}).`
12887
13035
  );
12888
13036
  }
13037
+ const allowlist = params.headroom.allowlist;
13038
+ if (supervisorAlive && headroomAlive && state.socketPath !== void 0 && allowlist?.driftInputs?.includes("front-door-origin") === true) {
13039
+ const origin = allowlist.frontDoorOrigin ?? "";
13040
+ const certainty = allowlist.driftInputs.includes("provider-files") ? "may exclude" : "excludes";
13041
+ push(
13042
+ "headroom",
13043
+ "fail",
13044
+ `Headroom daemon ${String(state.headroomPid)} was started with an allowlist that ${certainty} the serving front door's direct origin ${origin}, so it refuses every request a provider launch sends back through the door. Its supervisor restarts it once no launch is registered against it; \`agent-shim headroom status\` lists the registered launches, and \`--no-headroom\` launches are unaffected.`,
13045
+ String(state.headroomPid)
13046
+ );
13047
+ }
12889
13048
  if (state.lastError !== void 0 && supervisorAlive) {
12890
13049
  push("headroom", "warn", `Headroom recorded a previous error: ${state.lastError}`);
12891
13050
  }
@@ -12898,6 +13057,10 @@ function runDoctor(params) {
12898
13057
  }
12899
13058
  }
12900
13059
  }
13060
+ if (params.frontDoor !== void 0) {
13061
+ const validated3 = params.frontDoor.state.raw === void 0 ? void 0 : validateJson(FrontDoorStateSchema, params.frontDoor.state);
13062
+ pushFrontDoor(push, params.frontDoor.supervisors, validated3?.ok === true ? validated3.data.supervisorPid : void 0);
13063
+ }
12901
13064
  if (params.activeIdentity.raw === void 0) {
12902
13065
  push("active-identity", "pass", "No active identity set.");
12903
13066
  } else {
@@ -12927,6 +13090,7 @@ var SECTION_TITLES = {
12927
13090
  "directory-rules": "Directory rules",
12928
13091
  "global-config": "Global config",
12929
13092
  headroom: "Headroom daemon",
13093
+ frontdoor: "Front door",
12930
13094
  "categories-local": "categories.local.json",
12931
13095
  "active-identity": "Active identity"
12932
13096
  };
@@ -12944,6 +13108,7 @@ var SECTION_ORDER = [
12944
13108
  "directory-rules",
12945
13109
  "global-config",
12946
13110
  "headroom",
13111
+ "frontdoor",
12947
13112
  "categories-local",
12948
13113
  "active-identity"
12949
13114
  ];
@@ -13021,6 +13186,9 @@ function collectDoctorReport(params) {
13021
13186
  shimState.targetPath,
13022
13187
  realpathOrSelf
13023
13188
  );
13189
+ const uid = process.getuid?.();
13190
+ const allowlistInputs = currentHeadroomAllowlistInputs(realFarmFs, paths);
13191
+ const servingHeadroom = resolveServingHeadroomState(realFarmFs, { stateFile: paths.headroomStateFile, legacyStateFile: paths.headroomLegacyStateFile }, realIsProcessRunning);
13024
13192
  const report = runDoctor({
13025
13193
  env: params.env,
13026
13194
  credentialCache: realCredentialCacheEnv(paths),
@@ -13059,8 +13227,13 @@ function collectDoctorReport(params) {
13059
13227
  const statePath = resolved?.path ?? paths.headroomStateFile;
13060
13228
  return { path: statePath, raw: realFarmFs.readFileUtf8(statePath) };
13061
13229
  })(),
13062
- isRunning: realIsProcessRunning
13063
- }
13230
+ isRunning: realIsProcessRunning,
13231
+ allowlist: {
13232
+ driftInputs: diagnoseAllowlistDrift({ recordedHash: servingHeadroom?.state.allowlistHash, ...allowlistInputs }),
13233
+ frontDoorOrigin: allowlistInputs.frontDoorOrigin
13234
+ }
13235
+ },
13236
+ ...uid === void 0 ? {} : { frontDoor: { state: { path: paths.frontdoorStateFile, raw: realFsPort.readFileUtf8(paths.frontdoorStateFile) }, supervisors: listFrontDoorSupervisors(realRunPort, uid) } }
13064
13237
  });
13065
13238
  return report;
13066
13239
  }
@@ -13762,7 +13935,9 @@ var DoorHealthEventSchema = z23.discriminatedUnion("kind", [
13762
13935
  z23.strictObject({ kind: z23.literal("generation"), pid: z23.number().int().positive(), providerPort: z23.number().int().positive(), connectPort: z23.number().int().positive(), directPort: z23.number().int().positive(), observedAt: z23.number() }),
13763
13936
  z23.strictObject({ kind: z23.literal("listenerFailed"), pid: z23.number().int().positive(), listener: z23.enum(["provider", "connect", "direct"]), message: z23.string(), observedAt: z23.number() }),
13764
13937
  z23.strictObject({ kind: z23.literal("binaryTurnover"), pid: z23.number().int().positive(), observedAt: z23.number() }),
13765
- z23.strictObject({ kind: z23.literal("idleShutdown"), pid: z23.number().int().positive(), observedAt: z23.number() })
13938
+ z23.strictObject({ kind: z23.literal("idleShutdown"), pid: z23.number().int().positive(), observedAt: z23.number() }),
13939
+ z23.strictObject({ kind: z23.literal("superseded"), pid: z23.number().int().positive(), ownerPid: z23.number().int().positive(), observedAt: z23.number() }),
13940
+ z23.strictObject({ kind: z23.literal("drained"), pid: z23.number().int().positive(), observedAt: z23.number() })
13766
13941
  ]);
13767
13942
  var QuotaExpiringEventSchema = z23.strictObject({
13768
13943
  identity: z23.string().min(1),
@@ -14259,6 +14434,12 @@ function createDoorHealthPublisher(hub, now, pid) {
14259
14434
  },
14260
14435
  binaryTurnover: () => {
14261
14436
  publisher.publish({ kind: "binaryTurnover", pid, observedAt: now() });
14437
+ },
14438
+ superseded: (ownerPid) => {
14439
+ publisher.publish({ kind: "superseded", pid, ownerPid, observedAt: now() });
14440
+ },
14441
+ drained: () => {
14442
+ publisher.publish({ kind: "drained", pid, observedAt: now() });
14262
14443
  }
14263
14444
  };
14264
14445
  }