switchroom 0.13.24 → 0.13.25

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.
@@ -13598,7 +13598,6 @@ var init_schema = __esm(() => {
13598
13598
  SessionContinuitySchema = exports_external.object({
13599
13599
  enabled: exports_external.boolean().optional().describe("Master switch for the session-handoff briefing (default true)."),
13600
13600
  show_handoff_line: exports_external.boolean().optional().describe("Whether the telegram plugin prepends a visible '\u21a9\ufe0f Picked up\u2026' " + "line to the first assistant reply after a restart (default true)."),
13601
- summarizer_model: exports_external.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._\-/\[\]:]*$/, "Model name must be alphanumeric with ._-/[]: only").optional().describe("Anthropic model used to produce the handoff briefing."),
13602
13601
  max_turns_in_briefing: exports_external.number().int().positive().optional().describe("Cap on recent user/assistant turn pairs fed to the summarizer."),
13603
13602
  resume_mode: exports_external.enum(["auto", "continue", "handoff", "none"]).optional().describe("How to resume the next session. 'handoff' (default as of #362) " + "never passes --continue; a fresh Claude starts each restart and " + "reads a briefing assembled from recent Telegram messages, Hindsight " + "recall, and today's daily memory file. 'auto' uses --continue when " + "the latest JSONL is smaller than resume_max_bytes, else falls back " + "to the handoff briefing. 'continue' always passes --continue. " + "'none' starts completely fresh every time."),
13604
13603
  resume_max_bytes: exports_external.number().int().positive().optional().describe("Byte threshold above which 'auto' mode falls back to handoff " + "instead of --continue. Default 2_000_000 (~2MB). Large transcripts " + "can blow out the context window even with prefix caching, and " + "--continue replay is known-fragile at scale.")
@@ -13645,10 +13644,9 @@ var init_schema = __esm(() => {
13645
13644
  start: exports_external.number().int().min(0).max(23),
13646
13645
  end: exports_external.number().int().min(0).max(23),
13647
13646
  tz: exports_external.string().optional()
13648
- }).optional(),
13649
- model: exports_external.string().optional()
13647
+ }).optional()
13650
13648
  })).optional()
13651
- }).optional().describe("Auto-dispatch rules: when a verified webhook event matches a rule, " + "spawn a one-shot `claude -p` turn for the agent with the rendered " + "prompt. Supports cooldowns, quiet hours, and label/action matchers. " + "Off by default \u2014 opt in per agent. See src/web/webhook-dispatch.ts."),
13649
+ }).optional().describe("Auto-dispatch rules: when a verified webhook event matches a rule, " + "inject the rendered prompt into the agent's live session (#1625). " + "Supports cooldowns, quiet hours, and label/action matchers. " + "Off by default \u2014 opt in per agent. See src/web/webhook-dispatch.ts."),
13652
13650
  webhook_rate_limit: exports_external.object({
13653
13651
  rpm: exports_external.number().int().positive()
13654
13652
  }).optional().describe("Per-source rate limit for the webhook ingest path (#714). " + "Off by default \u2014 when this key is absent the handler skips " + "rate-limit checks entirely. Opt in by setting `rpm` to an " + "integer requests-per-minute (token bucket per (agent, source); " + "burst equal to rpm). When enabled, exceeding the limit returns " + "429 with Retry-After header; first throttle event per " + "(agent, source) per 60s window is written to " + "<agent>/telegram/issues.jsonl. " + "Cascades from defaults.channels.telegram.webhook_rate_limit.")
@@ -21049,6 +21047,7 @@ __export(exports_vault, {
21049
21047
  setStringSecret: () => setStringSecret,
21050
21048
  setSecret: () => setSecret,
21051
21049
  setFilesSecret: () => setFilesSecret,
21050
+ setBinarySecret: () => setBinarySecret,
21052
21051
  saveVault: () => saveVault,
21053
21052
  removeSecret: () => removeSecret,
21054
21053
  openVault: () => openVault,
@@ -21312,6 +21311,13 @@ function setStringSecret(passphrase, vaultPath, key, value, format, scope) {
21312
21311
  }
21313
21312
  setSecret(passphrase, vaultPath, key, entry);
21314
21313
  }
21314
+ function setBinarySecret(passphrase, vaultPath, key, value, format, scope) {
21315
+ const entry = format ? { kind: "binary", value, format } : { kind: "binary", value };
21316
+ if (scope !== undefined) {
21317
+ entry.scope = scope;
21318
+ }
21319
+ setSecret(passphrase, vaultPath, key, entry);
21320
+ }
21315
21321
  function getStringSecret(passphrase, vaultPath, key) {
21316
21322
  const entry = getSecret(passphrase, vaultPath, key);
21317
21323
  if (entry === null)
@@ -21369,6 +21375,315 @@ var init_vault = __esm(() => {
21369
21375
  ];
21370
21376
  });
21371
21377
 
21378
+ // src/vault/broker/peercred-ffi.ts
21379
+ function getPeerCred(fd) {
21380
+ if (process.platform !== "linux")
21381
+ return null;
21382
+ try {
21383
+ const ffi = __require("bun:ffi");
21384
+ const { dlopen, FFIType, ptr } = ffi;
21385
+ const SOL_SOCKET = 1;
21386
+ const SO_PEERCRED = 17;
21387
+ const UCRED_SIZE = 12;
21388
+ const cache = getPeerCred;
21389
+ const lib = cache._lib ?? (() => {
21390
+ const candidates = ["libc.so.6", "libc.so"];
21391
+ const symbolSpec = {
21392
+ getsockopt: {
21393
+ args: [FFIType.i32, FFIType.i32, FFIType.i32, FFIType.ptr, FFIType.ptr],
21394
+ returns: FFIType.i32
21395
+ }
21396
+ };
21397
+ const errors2 = [];
21398
+ for (const name of candidates) {
21399
+ try {
21400
+ const opened = dlopen(name, symbolSpec);
21401
+ cache._lib = opened;
21402
+ return opened;
21403
+ } catch (e) {
21404
+ errors2.push(`${name}: ${e instanceof Error ? e.message : String(e)}`);
21405
+ }
21406
+ }
21407
+ process.stderr.write(`[vault-broker] peercred-ffi: dlopen failed for all libc candidates ` + `(${errors2.join("; ")}); falling back to ss-parsing.
21408
+ `);
21409
+ throw new Error("no libc candidate could be opened");
21410
+ })();
21411
+ const credBuf = new ArrayBuffer(UCRED_SIZE);
21412
+ const lenBuf = new Uint32Array(1);
21413
+ lenBuf[0] = UCRED_SIZE;
21414
+ const rc = lib.symbols.getsockopt(fd, SOL_SOCKET, SO_PEERCRED, ptr(credBuf), ptr(lenBuf.buffer));
21415
+ if (rc !== 0)
21416
+ return null;
21417
+ if (lenBuf[0] !== UCRED_SIZE)
21418
+ return null;
21419
+ const view = new DataView(credBuf);
21420
+ return {
21421
+ pid: view.getInt32(0, true),
21422
+ uid: view.getInt32(4, true),
21423
+ gid: view.getInt32(8, true)
21424
+ };
21425
+ } catch {
21426
+ return null;
21427
+ }
21428
+ }
21429
+
21430
+ // src/vault/broker/peercred.ts
21431
+ import { execFileSync } from "node:child_process";
21432
+ import { readFileSync as readFileSync8, readlinkSync as readlinkSync3, fstatSync } from "node:fs";
21433
+ function socketPathToIdentity(socketPath) {
21434
+ if (typeof socketPath !== "string" || socketPath.length === 0)
21435
+ return null;
21436
+ const m = socketPath.match(SOCKET_PATH_AGENT_RE) ?? socketPath.match(SOCKET_PATH_AGENT_SUBDIR_RE);
21437
+ if (!m)
21438
+ return null;
21439
+ const name = m[1];
21440
+ if (name === "operator")
21441
+ return { kind: "operator" };
21442
+ if (RESERVED_AGENT_NAMES.has(name))
21443
+ return null;
21444
+ return { kind: "agent", name };
21445
+ }
21446
+ function socketPathToAgent(socketPath) {
21447
+ const identity = socketPathToIdentity(socketPath);
21448
+ return identity?.kind === "agent" ? identity.name : null;
21449
+ }
21450
+ function isReservedAgentName(name) {
21451
+ return RESERVED_AGENT_NAMES.has(name);
21452
+ }
21453
+ function unlockSocketFor(dataSocketPath) {
21454
+ if (dataSocketPath.endsWith("/sock")) {
21455
+ return dataSocketPath.slice(0, -"/sock".length) + "/unlock";
21456
+ }
21457
+ return dataSocketPath.replace(/\.sock$/, ".unlock.sock");
21458
+ }
21459
+ function parseSsRows(output) {
21460
+ const rows = [];
21461
+ const lines = output.split(`
21462
+ `);
21463
+ for (const line of lines) {
21464
+ if (!line.trim() || line.startsWith("Netid"))
21465
+ continue;
21466
+ const tokens = line.split(/\s+/).filter((t) => t.length > 0);
21467
+ if (tokens.length < 8)
21468
+ continue;
21469
+ const localAddr = tokens[4];
21470
+ const localInode = tokens[5];
21471
+ const peerAddr = tokens[6];
21472
+ const peerInode = tokens[7];
21473
+ const usersToken = tokens.slice(8).join(" ");
21474
+ const m = usersToken.match(/users:\(\(".*?",pid=(\d+),fd=\d+\)\)/);
21475
+ const pid = m ? parseInt(m[1], 10) : null;
21476
+ rows.push({ localAddr, localInode, peerAddr, peerInode, pid });
21477
+ }
21478
+ return rows;
21479
+ }
21480
+ function findClientPids(rows, socketPath) {
21481
+ const pids = [];
21482
+ for (const serverRow of rows) {
21483
+ if (serverRow.localAddr !== socketPath)
21484
+ continue;
21485
+ for (const clientRow of rows) {
21486
+ if (clientRow.localAddr !== "*")
21487
+ continue;
21488
+ if (clientRow.localInode !== serverRow.peerInode)
21489
+ continue;
21490
+ if (clientRow.pid === null)
21491
+ continue;
21492
+ pids.push(clientRow.pid);
21493
+ break;
21494
+ }
21495
+ }
21496
+ return pids;
21497
+ }
21498
+ function findClientPidByServerInode(rows, socketPath, serverInode) {
21499
+ const serverInodeStr = String(serverInode);
21500
+ for (const serverRow of rows) {
21501
+ if (serverRow.localAddr !== socketPath)
21502
+ continue;
21503
+ if (serverRow.localInode !== serverInodeStr)
21504
+ continue;
21505
+ for (const clientRow of rows) {
21506
+ if (clientRow.localAddr !== "*")
21507
+ continue;
21508
+ if (clientRow.localInode !== serverRow.peerInode)
21509
+ continue;
21510
+ if (clientRow.pid === null)
21511
+ continue;
21512
+ return clientRow.pid;
21513
+ }
21514
+ return null;
21515
+ }
21516
+ return null;
21517
+ }
21518
+ function readUid(pid) {
21519
+ try {
21520
+ const status = readFileSync8(`/proc/${pid}/status`, "utf8");
21521
+ const m = status.match(/^Uid:\s+(\d+)/m);
21522
+ if (!m)
21523
+ return null;
21524
+ return parseInt(m[1], 10);
21525
+ } catch {
21526
+ return null;
21527
+ }
21528
+ }
21529
+ function readExe(pid) {
21530
+ try {
21531
+ return readlinkSync3(`/proc/${pid}/exe`);
21532
+ } catch {
21533
+ return null;
21534
+ }
21535
+ }
21536
+ function readSystemdUnit(pid) {
21537
+ try {
21538
+ const content = readFileSync8(`/proc/${pid}/cgroup`, "utf8");
21539
+ const lines = content.split(`
21540
+ `);
21541
+ for (const line of lines) {
21542
+ if (!line.trim())
21543
+ continue;
21544
+ const parts = line.split(":");
21545
+ if (parts.length < 3)
21546
+ continue;
21547
+ const controller = parts[1];
21548
+ const isV2 = parts[0] === "0" && controller === "";
21549
+ const isV1Systemd = controller === "name=systemd";
21550
+ if (!isV2 && !isV1Systemd)
21551
+ continue;
21552
+ const cgroupPath = parts.slice(2).join(":");
21553
+ const segments = cgroupPath.split("/");
21554
+ const lastSegment = segments[segments.length - 1];
21555
+ if (!lastSegment)
21556
+ continue;
21557
+ if (/^switchroom-[a-zA-Z0-9_-]+(-cron-\d+)?\.service$/.test(lastSegment)) {
21558
+ return lastSegment;
21559
+ }
21560
+ }
21561
+ return null;
21562
+ } catch {
21563
+ return null;
21564
+ }
21565
+ }
21566
+ function verifySystemdUnit(unitName, runner) {
21567
+ let raw;
21568
+ try {
21569
+ const out = runner("systemctl", [
21570
+ "--user",
21571
+ "show",
21572
+ unitName,
21573
+ "--property=LoadState,ActiveState"
21574
+ ], { timeout: 500, encoding: "utf8" });
21575
+ raw = typeof out === "string" ? out : out.toString("utf8");
21576
+ } catch {
21577
+ return false;
21578
+ }
21579
+ const props = {};
21580
+ for (const line of raw.split(`
21581
+ `)) {
21582
+ const m = line.match(/^([A-Za-z]+)=(.*)$/);
21583
+ if (m)
21584
+ props[m[1]] = m[2];
21585
+ }
21586
+ if (props.LoadState !== "loaded")
21587
+ return false;
21588
+ if (props.ActiveState !== "active" && props.ActiveState !== "activating") {
21589
+ return false;
21590
+ }
21591
+ return true;
21592
+ }
21593
+ function readFdInode(fd) {
21594
+ try {
21595
+ const stat = fstatSync(fd);
21596
+ return stat.ino;
21597
+ } catch {
21598
+ return null;
21599
+ }
21600
+ }
21601
+ function fdFromSocket(socket) {
21602
+ const handle = socket._handle;
21603
+ if (!handle || typeof handle.fd !== "number" || handle.fd < 0)
21604
+ return null;
21605
+ return handle.fd;
21606
+ }
21607
+ function identify(socketPath, socket, execFileSyncOverride) {
21608
+ if (process.platform !== "linux") {
21609
+ return null;
21610
+ }
21611
+ const runner = execFileSyncOverride ?? execFileSync;
21612
+ let pid = null;
21613
+ if (socket !== undefined) {
21614
+ const fd = fdFromSocket(socket);
21615
+ if (fd !== null) {
21616
+ const cred = getPeerCred(fd);
21617
+ if (cred !== null)
21618
+ pid = cred.pid;
21619
+ }
21620
+ }
21621
+ if (pid === null) {
21622
+ let ssOutput;
21623
+ try {
21624
+ const raw = runner("ss", ["-xpn"], {
21625
+ timeout: 200,
21626
+ encoding: "utf8"
21627
+ });
21628
+ ssOutput = typeof raw === "string" ? raw : raw.toString("utf8");
21629
+ } catch {
21630
+ return null;
21631
+ }
21632
+ const rows = parseSsRows(ssOutput);
21633
+ let serverInode = null;
21634
+ if (socket !== undefined) {
21635
+ const fd = fdFromSocket(socket);
21636
+ if (fd !== null)
21637
+ serverInode = readFdInode(fd);
21638
+ }
21639
+ if (serverInode !== null) {
21640
+ pid = findClientPidByServerInode(rows, socketPath, serverInode);
21641
+ } else {
21642
+ const clientPids = findClientPids(rows, socketPath);
21643
+ if (clientPids.length === 0)
21644
+ return null;
21645
+ if (clientPids.length > 1) {
21646
+ process.stderr.write(`[vault-broker] peercred: ${clientPids.length} connected peers found for ${socketPath}; ` + `using pid=${clientPids[0]}. ` + `Multiple simultaneous connections reduce identification accuracy. ` + `(This warning means identify() was called without a socket arg \u2014 likely a stale call site.)
21647
+ `);
21648
+ }
21649
+ pid = clientPids[0];
21650
+ }
21651
+ }
21652
+ if (pid === null)
21653
+ return null;
21654
+ const uid = readUid(pid);
21655
+ if (uid === null) {
21656
+ return null;
21657
+ }
21658
+ const brokerUid = typeof process.getuid === "function" ? process.getuid() : null;
21659
+ if (brokerUid !== null && uid !== brokerUid) {
21660
+ process.stderr.write(`[vault-broker] peercred: UID mismatch \u2014 caller uid=${uid}, broker uid=${brokerUid}; denying
21661
+ `);
21662
+ return null;
21663
+ }
21664
+ const exe = readExe(pid);
21665
+ if (exe === null) {
21666
+ return null;
21667
+ }
21668
+ const cgroupClaim = readSystemdUnit(pid);
21669
+ let systemdUnit = null;
21670
+ if (cgroupClaim !== null) {
21671
+ if (verifySystemdUnit(cgroupClaim, runner)) {
21672
+ systemdUnit = cgroupClaim;
21673
+ } else {
21674
+ process.stderr.write(`[vault-broker] peercred: cgroup claims unit=${cgroupClaim} but systemd-user does not report it as loaded+running; treating caller as unidentified
21675
+ `);
21676
+ }
21677
+ }
21678
+ return { uid, pid, exe, systemdUnit };
21679
+ }
21680
+ var SOCKET_PATH_AGENT_RE, SOCKET_PATH_AGENT_SUBDIR_RE, RESERVED_AGENT_NAMES;
21681
+ var init_peercred = __esm(() => {
21682
+ SOCKET_PATH_AGENT_RE = /^\/run\/switchroom\/broker\/([a-zA-Z0-9][a-zA-Z0-9_-]*)\.sock$/;
21683
+ SOCKET_PATH_AGENT_SUBDIR_RE = /^\/run\/switchroom\/broker\/([a-zA-Z0-9][a-zA-Z0-9_-]*)\/sock$/;
21684
+ RESERVED_AGENT_NAMES = new Set(["operator", "hostd"]);
21685
+ });
21686
+
21372
21687
  // src/vault/broker/protocol.ts
21373
21688
  function encodeRequest(req) {
21374
21689
  const json = JSON.stringify(req);
@@ -21420,10 +21735,14 @@ function stripWireFields(entry) {
21420
21735
  files: entry.files
21421
21736
  };
21422
21737
  }
21423
- var MAX_FRAME_BYTES, GetRequestSchema, PutRequestSchema, ListRequestSchema, MintGrantRequestSchema, ListGrantsRequestSchema, RevokeGrantRequestSchema, StatusRequestSchema, LockRequestSchema, PreflightAccessRequestSchema, OkPreflightAccessResponseSchema, ApprovalRequestRequestSchema, ApprovalLookupRequestSchema, ApprovalConsumeRequestSchema, ApprovalRevokeRequestSchema, ApprovalListRequestSchema, ApprovalDecisionModeSchema, ApprovalRecordRequestSchema, ApprovalConsumeRecordRequestSchema, RequestSchema, VaultEntrySchema, ErrorCode, OkEntryResponseSchema, OkKeysResponseSchema, BrokerStatus, OkStatusResponseSchema, OkLockResponseSchema, OkPutResponseSchema, OkMintGrantResponseSchema, GrantMetaSchema, OkListGrantsResponseSchema, OkRevokeGrantResponseSchema, OkApprovalRequestResponseSchema, ApprovalDecisionMetaSchema, OkApprovalLookupResponseSchema, OkApprovalConsumeResponseSchema, OkApprovalRevokeResponseSchema, OkApprovalListResponseSchema, OkApprovalRecordResponseSchema, OkApprovalConsumeRecordResponseSchema, ErrorResponseSchema, ResponseSchema;
21738
+ var MAX_FRAME_BYTES, AgentNameSchema, GetRequestSchema, PutRequestSchema, ListRequestSchema, MintGrantRequestSchema, ListGrantsRequestSchema, RevokeGrantRequestSchema, StatusRequestSchema, LockRequestSchema, PreflightAccessRequestSchema, OkPreflightAccessResponseSchema, ApprovalRequestRequestSchema, ApprovalLookupRequestSchema, ApprovalConsumeRequestSchema, ApprovalRevokeRequestSchema, ApprovalListRequestSchema, ApprovalDecisionModeSchema, ApprovalRecordRequestSchema, ApprovalConsumeRecordRequestSchema, RequestSchema, VaultEntrySchema, ErrorCode, OkEntryResponseSchema, OkKeysResponseSchema, BrokerStatus, OkStatusResponseSchema, OkLockResponseSchema, OkPutResponseSchema, OkMintGrantResponseSchema, GrantMetaSchema, OkListGrantsResponseSchema, OkRevokeGrantResponseSchema, OkApprovalRequestResponseSchema, ApprovalDecisionMetaSchema, OkApprovalLookupResponseSchema, OkApprovalConsumeResponseSchema, OkApprovalRevokeResponseSchema, OkApprovalListResponseSchema, OkApprovalRecordResponseSchema, OkApprovalConsumeRecordResponseSchema, ErrorResponseSchema, ResponseSchema;
21424
21739
  var init_protocol = __esm(() => {
21425
21740
  init_zod();
21741
+ init_peercred();
21426
21742
  MAX_FRAME_BYTES = 64 * 1024;
21743
+ AgentNameSchema = exports_external.string().min(1).max(64, "agent name max 64 chars").regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/, "agent name must be kebab-case ASCII (alnum + _- only, first char alnum)").refine((s) => !isReservedAgentName(s), {
21744
+ message: "agent name is reserved"
21745
+ });
21427
21746
  GetRequestSchema = exports_external.object({
21428
21747
  v: exports_external.literal(1),
21429
21748
  op: exports_external.literal("get"),
@@ -21451,7 +21770,7 @@ var init_protocol = __esm(() => {
21451
21770
  MintGrantRequestSchema = exports_external.object({
21452
21771
  v: exports_external.literal(1),
21453
21772
  op: exports_external.literal("mint_grant"),
21454
- agent: exports_external.string().min(1),
21773
+ agent: AgentNameSchema,
21455
21774
  keys: exports_external.array(exports_external.string().min(1)),
21456
21775
  ttl_seconds: exports_external.number().int().positive().nullable(),
21457
21776
  description: exports_external.string().optional(),
@@ -21462,7 +21781,7 @@ var init_protocol = __esm(() => {
21462
21781
  ListGrantsRequestSchema = exports_external.object({
21463
21782
  v: exports_external.literal(1),
21464
21783
  op: exports_external.literal("list_grants"),
21465
- agent: exports_external.string().optional(),
21784
+ agent: AgentNameSchema.optional(),
21466
21785
  passphrase: exports_external.string().optional(),
21467
21786
  attest_via_posture: exports_external.boolean().optional()
21468
21787
  });
@@ -21482,7 +21801,7 @@ var init_protocol = __esm(() => {
21482
21801
  PreflightAccessRequestSchema = exports_external.object({
21483
21802
  v: exports_external.literal(1),
21484
21803
  op: exports_external.literal("preflight_access"),
21485
- agent: exports_external.string().min(1),
21804
+ agent: AgentNameSchema,
21486
21805
  keys: exports_external.array(exports_external.string().min(1)).min(1).max(128)
21487
21806
  });
21488
21807
  OkPreflightAccessResponseSchema = exports_external.object({
@@ -21730,315 +22049,6 @@ var init_protocol = __esm(() => {
21730
22049
  ]);
21731
22050
  });
21732
22051
 
21733
- // src/vault/broker/peercred-ffi.ts
21734
- function getPeerCred(fd) {
21735
- if (process.platform !== "linux")
21736
- return null;
21737
- try {
21738
- const ffi = __require("bun:ffi");
21739
- const { dlopen, FFIType, ptr } = ffi;
21740
- const SOL_SOCKET = 1;
21741
- const SO_PEERCRED = 17;
21742
- const UCRED_SIZE = 12;
21743
- const cache = getPeerCred;
21744
- const lib = cache._lib ?? (() => {
21745
- const candidates = ["libc.so.6", "libc.so"];
21746
- const symbolSpec = {
21747
- getsockopt: {
21748
- args: [FFIType.i32, FFIType.i32, FFIType.i32, FFIType.ptr, FFIType.ptr],
21749
- returns: FFIType.i32
21750
- }
21751
- };
21752
- const errors2 = [];
21753
- for (const name of candidates) {
21754
- try {
21755
- const opened = dlopen(name, symbolSpec);
21756
- cache._lib = opened;
21757
- return opened;
21758
- } catch (e) {
21759
- errors2.push(`${name}: ${e instanceof Error ? e.message : String(e)}`);
21760
- }
21761
- }
21762
- process.stderr.write(`[vault-broker] peercred-ffi: dlopen failed for all libc candidates ` + `(${errors2.join("; ")}); falling back to ss-parsing.
21763
- `);
21764
- throw new Error("no libc candidate could be opened");
21765
- })();
21766
- const credBuf = new ArrayBuffer(UCRED_SIZE);
21767
- const lenBuf = new Uint32Array(1);
21768
- lenBuf[0] = UCRED_SIZE;
21769
- const rc = lib.symbols.getsockopt(fd, SOL_SOCKET, SO_PEERCRED, ptr(credBuf), ptr(lenBuf.buffer));
21770
- if (rc !== 0)
21771
- return null;
21772
- if (lenBuf[0] !== UCRED_SIZE)
21773
- return null;
21774
- const view = new DataView(credBuf);
21775
- return {
21776
- pid: view.getInt32(0, true),
21777
- uid: view.getInt32(4, true),
21778
- gid: view.getInt32(8, true)
21779
- };
21780
- } catch {
21781
- return null;
21782
- }
21783
- }
21784
-
21785
- // src/vault/broker/peercred.ts
21786
- import { execFileSync } from "node:child_process";
21787
- import { readFileSync as readFileSync8, readlinkSync as readlinkSync3, fstatSync } from "node:fs";
21788
- function socketPathToIdentity(socketPath) {
21789
- if (typeof socketPath !== "string" || socketPath.length === 0)
21790
- return null;
21791
- const m = socketPath.match(SOCKET_PATH_AGENT_RE) ?? socketPath.match(SOCKET_PATH_AGENT_SUBDIR_RE);
21792
- if (!m)
21793
- return null;
21794
- const name = m[1];
21795
- if (name === "operator")
21796
- return { kind: "operator" };
21797
- if (RESERVED_AGENT_NAMES.has(name))
21798
- return null;
21799
- return { kind: "agent", name };
21800
- }
21801
- function socketPathToAgent(socketPath) {
21802
- const identity = socketPathToIdentity(socketPath);
21803
- return identity?.kind === "agent" ? identity.name : null;
21804
- }
21805
- function isReservedAgentName(name) {
21806
- return RESERVED_AGENT_NAMES.has(name);
21807
- }
21808
- function unlockSocketFor(dataSocketPath) {
21809
- if (dataSocketPath.endsWith("/sock")) {
21810
- return dataSocketPath.slice(0, -"/sock".length) + "/unlock";
21811
- }
21812
- return dataSocketPath.replace(/\.sock$/, ".unlock.sock");
21813
- }
21814
- function parseSsRows(output) {
21815
- const rows = [];
21816
- const lines = output.split(`
21817
- `);
21818
- for (const line of lines) {
21819
- if (!line.trim() || line.startsWith("Netid"))
21820
- continue;
21821
- const tokens = line.split(/\s+/).filter((t) => t.length > 0);
21822
- if (tokens.length < 8)
21823
- continue;
21824
- const localAddr = tokens[4];
21825
- const localInode = tokens[5];
21826
- const peerAddr = tokens[6];
21827
- const peerInode = tokens[7];
21828
- const usersToken = tokens.slice(8).join(" ");
21829
- const m = usersToken.match(/users:\(\(".*?",pid=(\d+),fd=\d+\)\)/);
21830
- const pid = m ? parseInt(m[1], 10) : null;
21831
- rows.push({ localAddr, localInode, peerAddr, peerInode, pid });
21832
- }
21833
- return rows;
21834
- }
21835
- function findClientPids(rows, socketPath) {
21836
- const pids = [];
21837
- for (const serverRow of rows) {
21838
- if (serverRow.localAddr !== socketPath)
21839
- continue;
21840
- for (const clientRow of rows) {
21841
- if (clientRow.localAddr !== "*")
21842
- continue;
21843
- if (clientRow.localInode !== serverRow.peerInode)
21844
- continue;
21845
- if (clientRow.pid === null)
21846
- continue;
21847
- pids.push(clientRow.pid);
21848
- break;
21849
- }
21850
- }
21851
- return pids;
21852
- }
21853
- function findClientPidByServerInode(rows, socketPath, serverInode) {
21854
- const serverInodeStr = String(serverInode);
21855
- for (const serverRow of rows) {
21856
- if (serverRow.localAddr !== socketPath)
21857
- continue;
21858
- if (serverRow.localInode !== serverInodeStr)
21859
- continue;
21860
- for (const clientRow of rows) {
21861
- if (clientRow.localAddr !== "*")
21862
- continue;
21863
- if (clientRow.localInode !== serverRow.peerInode)
21864
- continue;
21865
- if (clientRow.pid === null)
21866
- continue;
21867
- return clientRow.pid;
21868
- }
21869
- return null;
21870
- }
21871
- return null;
21872
- }
21873
- function readUid(pid) {
21874
- try {
21875
- const status = readFileSync8(`/proc/${pid}/status`, "utf8");
21876
- const m = status.match(/^Uid:\s+(\d+)/m);
21877
- if (!m)
21878
- return null;
21879
- return parseInt(m[1], 10);
21880
- } catch {
21881
- return null;
21882
- }
21883
- }
21884
- function readExe(pid) {
21885
- try {
21886
- return readlinkSync3(`/proc/${pid}/exe`);
21887
- } catch {
21888
- return null;
21889
- }
21890
- }
21891
- function readSystemdUnit(pid) {
21892
- try {
21893
- const content = readFileSync8(`/proc/${pid}/cgroup`, "utf8");
21894
- const lines = content.split(`
21895
- `);
21896
- for (const line of lines) {
21897
- if (!line.trim())
21898
- continue;
21899
- const parts = line.split(":");
21900
- if (parts.length < 3)
21901
- continue;
21902
- const controller = parts[1];
21903
- const isV2 = parts[0] === "0" && controller === "";
21904
- const isV1Systemd = controller === "name=systemd";
21905
- if (!isV2 && !isV1Systemd)
21906
- continue;
21907
- const cgroupPath = parts.slice(2).join(":");
21908
- const segments = cgroupPath.split("/");
21909
- const lastSegment = segments[segments.length - 1];
21910
- if (!lastSegment)
21911
- continue;
21912
- if (/^switchroom-[a-zA-Z0-9_-]+(-cron-\d+)?\.service$/.test(lastSegment)) {
21913
- return lastSegment;
21914
- }
21915
- }
21916
- return null;
21917
- } catch {
21918
- return null;
21919
- }
21920
- }
21921
- function verifySystemdUnit(unitName, runner) {
21922
- let raw;
21923
- try {
21924
- const out = runner("systemctl", [
21925
- "--user",
21926
- "show",
21927
- unitName,
21928
- "--property=LoadState,ActiveState"
21929
- ], { timeout: 500, encoding: "utf8" });
21930
- raw = typeof out === "string" ? out : out.toString("utf8");
21931
- } catch {
21932
- return false;
21933
- }
21934
- const props = {};
21935
- for (const line of raw.split(`
21936
- `)) {
21937
- const m = line.match(/^([A-Za-z]+)=(.*)$/);
21938
- if (m)
21939
- props[m[1]] = m[2];
21940
- }
21941
- if (props.LoadState !== "loaded")
21942
- return false;
21943
- if (props.ActiveState !== "active" && props.ActiveState !== "activating") {
21944
- return false;
21945
- }
21946
- return true;
21947
- }
21948
- function readFdInode(fd) {
21949
- try {
21950
- const stat = fstatSync(fd);
21951
- return stat.ino;
21952
- } catch {
21953
- return null;
21954
- }
21955
- }
21956
- function fdFromSocket(socket) {
21957
- const handle = socket._handle;
21958
- if (!handle || typeof handle.fd !== "number" || handle.fd < 0)
21959
- return null;
21960
- return handle.fd;
21961
- }
21962
- function identify(socketPath, socket, execFileSyncOverride) {
21963
- if (process.platform !== "linux") {
21964
- return null;
21965
- }
21966
- const runner = execFileSyncOverride ?? execFileSync;
21967
- let pid = null;
21968
- if (socket !== undefined) {
21969
- const fd = fdFromSocket(socket);
21970
- if (fd !== null) {
21971
- const cred = getPeerCred(fd);
21972
- if (cred !== null)
21973
- pid = cred.pid;
21974
- }
21975
- }
21976
- if (pid === null) {
21977
- let ssOutput;
21978
- try {
21979
- const raw = runner("ss", ["-xpn"], {
21980
- timeout: 200,
21981
- encoding: "utf8"
21982
- });
21983
- ssOutput = typeof raw === "string" ? raw : raw.toString("utf8");
21984
- } catch {
21985
- return null;
21986
- }
21987
- const rows = parseSsRows(ssOutput);
21988
- let serverInode = null;
21989
- if (socket !== undefined) {
21990
- const fd = fdFromSocket(socket);
21991
- if (fd !== null)
21992
- serverInode = readFdInode(fd);
21993
- }
21994
- if (serverInode !== null) {
21995
- pid = findClientPidByServerInode(rows, socketPath, serverInode);
21996
- } else {
21997
- const clientPids = findClientPids(rows, socketPath);
21998
- if (clientPids.length === 0)
21999
- return null;
22000
- if (clientPids.length > 1) {
22001
- process.stderr.write(`[vault-broker] peercred: ${clientPids.length} connected peers found for ${socketPath}; ` + `using pid=${clientPids[0]}. ` + `Multiple simultaneous connections reduce identification accuracy. ` + `(This warning means identify() was called without a socket arg \u2014 likely a stale call site.)
22002
- `);
22003
- }
22004
- pid = clientPids[0];
22005
- }
22006
- }
22007
- if (pid === null)
22008
- return null;
22009
- const uid = readUid(pid);
22010
- if (uid === null) {
22011
- return null;
22012
- }
22013
- const brokerUid = typeof process.getuid === "function" ? process.getuid() : null;
22014
- if (brokerUid !== null && uid !== brokerUid) {
22015
- process.stderr.write(`[vault-broker] peercred: UID mismatch \u2014 caller uid=${uid}, broker uid=${brokerUid}; denying
22016
- `);
22017
- return null;
22018
- }
22019
- const exe = readExe(pid);
22020
- if (exe === null) {
22021
- return null;
22022
- }
22023
- const cgroupClaim = readSystemdUnit(pid);
22024
- let systemdUnit = null;
22025
- if (cgroupClaim !== null) {
22026
- if (verifySystemdUnit(cgroupClaim, runner)) {
22027
- systemdUnit = cgroupClaim;
22028
- } else {
22029
- process.stderr.write(`[vault-broker] peercred: cgroup claims unit=${cgroupClaim} but systemd-user does not report it as loaded+running; treating caller as unidentified
22030
- `);
22031
- }
22032
- }
22033
- return { uid, pid, exe, systemdUnit };
22034
- }
22035
- var SOCKET_PATH_AGENT_RE, SOCKET_PATH_AGENT_SUBDIR_RE, RESERVED_AGENT_NAMES;
22036
- var init_peercred = __esm(() => {
22037
- SOCKET_PATH_AGENT_RE = /^\/run\/switchroom\/broker\/([a-zA-Z0-9][a-zA-Z0-9_-]*)\.sock$/;
22038
- SOCKET_PATH_AGENT_SUBDIR_RE = /^\/run\/switchroom\/broker\/([a-zA-Z0-9][a-zA-Z0-9_-]*)\/sock$/;
22039
- RESERVED_AGENT_NAMES = new Set(["operator", "hostd"]);
22040
- });
22041
-
22042
22052
  // src/runtime-mode.ts
22043
22053
  function isDockerRuntime() {
22044
22054
  return process.env.SWITCHROOM_RUNTIME === "docker";
@@ -25539,6 +25549,7 @@ var init_broker_call = __esm(() => {
25539
25549
 
25540
25550
  // src/auth/account-store.ts
25541
25551
  import {
25552
+ chownSync,
25542
25553
  existsSync as existsSync26,
25543
25554
  mkdirSync as mkdirSync15,
25544
25555
  readFileSync as readFileSync22,
@@ -29089,7 +29100,7 @@ function decodeResponse3(line) {
29089
29100
  const obj = JSON.parse(line);
29090
29101
  return ResponseSchema3.parse(obj);
29091
29102
  }
29092
- var MAX_FRAME_BYTES3, RequestEnvelope, AgentRestartRequestSchema, UpgradeStatusRequestSchema, GetStatusRequestSchema, AgentNameSchema, UpdateCheckRequestSchema, UpdateApplyRequestSchema, ApplyRequestSchema, AgentStartRequestSchema, AgentStopRequestSchema, AgentLogsRequestSchema, AgentExecRequestSchema, DoctorRequestSchema, AgentSmokeRequestSchema, ConfigProposeEditRequestSchema, RequestSchema3, ResultSchema, ResponseEnvelope, ResponseSchema3;
29103
+ var MAX_FRAME_BYTES3, RequestEnvelope, AgentRestartRequestSchema, UpgradeStatusRequestSchema, GetStatusRequestSchema, AgentNameSchema2, UpdateCheckRequestSchema, UpdateApplyRequestSchema, ApplyRequestSchema, AgentStartRequestSchema, AgentStopRequestSchema, AgentLogsRequestSchema, AgentExecRequestSchema, DoctorRequestSchema, AgentSmokeRequestSchema, ConfigProposeEditRequestSchema, RequestSchema3, ResultSchema, ResponseEnvelope, ResponseSchema3;
29093
29104
  var init_protocol3 = __esm(() => {
29094
29105
  init_zod();
29095
29106
  MAX_FRAME_BYTES3 = 64 * 1024;
@@ -29119,7 +29130,7 @@ var init_protocol3 = __esm(() => {
29119
29130
  target_request_id: exports_external.string().min(1).max(128)
29120
29131
  })
29121
29132
  });
29122
- AgentNameSchema = exports_external.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/, "agent name must be kebab-case ASCII");
29133
+ AgentNameSchema2 = exports_external.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/, "agent name must be kebab-case ASCII");
29123
29134
  UpdateCheckRequestSchema = exports_external.object({
29124
29135
  ...RequestEnvelope,
29125
29136
  op: exports_external.literal("update_check"),
@@ -29144,21 +29155,21 @@ var init_protocol3 = __esm(() => {
29144
29155
  ...RequestEnvelope,
29145
29156
  op: exports_external.literal("agent_start"),
29146
29157
  args: exports_external.object({
29147
- name: AgentNameSchema
29158
+ name: AgentNameSchema2
29148
29159
  })
29149
29160
  });
29150
29161
  AgentStopRequestSchema = exports_external.object({
29151
29162
  ...RequestEnvelope,
29152
29163
  op: exports_external.literal("agent_stop"),
29153
29164
  args: exports_external.object({
29154
- name: AgentNameSchema
29165
+ name: AgentNameSchema2
29155
29166
  })
29156
29167
  });
29157
29168
  AgentLogsRequestSchema = exports_external.object({
29158
29169
  ...RequestEnvelope,
29159
29170
  op: exports_external.literal("agent_logs"),
29160
29171
  args: exports_external.object({
29161
- name: AgentNameSchema,
29172
+ name: AgentNameSchema2,
29162
29173
  tail: exports_external.number().int().positive().max(2000).optional()
29163
29174
  })
29164
29175
  });
@@ -29166,7 +29177,7 @@ var init_protocol3 = __esm(() => {
29166
29177
  ...RequestEnvelope,
29167
29178
  op: exports_external.literal("agent_exec"),
29168
29179
  args: exports_external.object({
29169
- name: AgentNameSchema,
29180
+ name: AgentNameSchema2,
29170
29181
  argv: exports_external.array(exports_external.string().min(1)).min(1).max(32)
29171
29182
  })
29172
29183
  });
@@ -29179,7 +29190,7 @@ var init_protocol3 = __esm(() => {
29179
29190
  ...RequestEnvelope,
29180
29191
  op: exports_external.literal("agent_smoke"),
29181
29192
  args: exports_external.object({
29182
- name: AgentNameSchema,
29193
+ name: AgentNameSchema2,
29183
29194
  deep: exports_external.boolean().optional()
29184
29195
  })
29185
29196
  });
@@ -47331,8 +47342,8 @@ var {
47331
47342
  } = import__.default;
47332
47343
 
47333
47344
  // src/build-info.ts
47334
- var VERSION = "0.13.24";
47335
- var COMMIT_SHA = "9bfca233";
47345
+ var VERSION = "0.13.25";
47346
+ var COMMIT_SHA = "e927d05d";
47336
47347
 
47337
47348
  // src/cli/agent.ts
47338
47349
  init_source();
@@ -55825,7 +55836,7 @@ import { spawn as spawn3 } from "node:child_process";
55825
55836
  init_compose();
55826
55837
  init_vault();
55827
55838
  import * as net3 from "node:net";
55828
- import { mkdirSync as mkdirSync20, chmodSync as chmodSync7, chownSync, existsSync as existsSync33, readFileSync as readFileSync29, readdirSync as readdirSync15, statSync as statSync19, unlinkSync as unlinkSync8, writeFileSync as writeFileSync18, renameSync as renameSync9 } from "node:fs";
55839
+ import { mkdirSync as mkdirSync20, chmodSync as chmodSync7, chownSync as chownSync2, existsSync as existsSync33, readFileSync as readFileSync29, readdirSync as readdirSync15, statSync as statSync19, unlinkSync as unlinkSync8, writeFileSync as writeFileSync18, renameSync as renameSync9 } from "node:fs";
55829
55840
  import { dirname as dirname6, resolve as resolve25, basename as basename5 } from "node:path";
55830
55841
  import * as os4 from "node:os";
55831
55842
  import * as path3 from "node:path";
@@ -58622,7 +58633,7 @@ class VaultBroker {
58622
58633
  const dir = abs.slice(0, -"/sock".length);
58623
58634
  if (existsSync33(dir)) {
58624
58635
  try {
58625
- chownSync(dir, 0, 0);
58636
+ chownSync2(dir, 0, 0);
58626
58637
  } catch {}
58627
58638
  try {
58628
58639
  chmodSync7(dir, 448);
@@ -58649,12 +58660,12 @@ class VaultBroker {
58649
58660
  try {
58650
58661
  const uid = allocateAgentUid(agentName);
58651
58662
  try {
58652
- chownSync(abs, uid, uid);
58663
+ chownSync2(abs, uid, uid);
58653
58664
  } catch {}
58654
58665
  if (abs.endsWith("/sock")) {
58655
58666
  const dir = abs.slice(0, -"/sock".length);
58656
58667
  try {
58657
- chownSync(dir, uid, uid);
58668
+ chownSync2(dir, uid, uid);
58658
58669
  } catch {}
58659
58670
  }
58660
58671
  } catch {}
@@ -58689,7 +58700,7 @@ class VaultBroker {
58689
58700
  return;
58690
58701
  try {
58691
58702
  if (existsSync33(this.vaultPath))
58692
- chownSync(this.vaultPath, uid, uid);
58703
+ chownSync2(this.vaultPath, uid, uid);
58693
58704
  } catch {}
58694
58705
  }
58695
58706
  bindOperatorListener(socketPath, operatorUid) {
@@ -58703,7 +58714,7 @@ class VaultBroker {
58703
58714
  const dir = abs.slice(0, -"/sock".length);
58704
58715
  if (existsSync33(dir)) {
58705
58716
  try {
58706
- chownSync(dir, 0, 0);
58717
+ chownSync2(dir, 0, 0);
58707
58718
  } catch {}
58708
58719
  try {
58709
58720
  chmodSync7(dir, 448);
@@ -58727,7 +58738,7 @@ class VaultBroker {
58727
58738
  chmodSync7(abs, 384);
58728
58739
  } catch {}
58729
58740
  try {
58730
- chownSync(abs, operatorUid, operatorUid);
58741
+ chownSync2(abs, operatorUid, operatorUid);
58731
58742
  } catch {}
58732
58743
  const unlockServer = net3.createServer((sock) => {
58733
58744
  this._handleUnlockConnection(sock, true);
@@ -58738,12 +58749,12 @@ class VaultBroker {
58738
58749
  chmodSync7(unlockAbs, 384);
58739
58750
  } catch {}
58740
58751
  try {
58741
- chownSync(unlockAbs, operatorUid, operatorUid);
58752
+ chownSync2(unlockAbs, operatorUid, operatorUid);
58742
58753
  } catch {}
58743
58754
  if (abs.endsWith("/sock")) {
58744
58755
  const dir = abs.slice(0, -"/sock".length);
58745
58756
  try {
58746
- chownSync(dir, operatorUid, operatorUid);
58757
+ chownSync2(dir, operatorUid, operatorUid);
58747
58758
  } catch {}
58748
58759
  try {
58749
58760
  chmodSync7(dir, 448);
@@ -59586,7 +59597,7 @@ class VaultBroker {
59586
59597
  const revoked = revokeGrant(this.grantsDb, id);
59587
59598
  try {
59588
59599
  const row = this.grantsDb.query("SELECT agent_slug FROM vault_grants WHERE id = ?").get(id);
59589
- if (row) {
59600
+ if (row && AgentNameSchema.safeParse(row.agent_slug).success) {
59590
59601
  const tokenPath = path3.join(os4.homedir(), ".switchroom", "agents", row.agent_slug, ".vault-token");
59591
59602
  if (existsSync33(tokenPath)) {
59592
59603
  try {
@@ -61405,9 +61416,18 @@ function registerVaultCommand(program3) {
61405
61416
  }
61406
61417
  const passphrase = await getPassphrase();
61407
61418
  let value;
61419
+ let isBinaryFile = false;
61408
61420
  if (opts.file) {
61409
61421
  try {
61410
- value = readFileSync34(resolvePath(opts.file), "utf8");
61422
+ const buf = readFileSync34(resolvePath(opts.file));
61423
+ const asUtf8 = buf.toString("utf8");
61424
+ if (Buffer.compare(buf, Buffer.from(asUtf8, "utf8")) === 0) {
61425
+ value = asUtf8;
61426
+ } else {
61427
+ value = buf.toString("base64");
61428
+ isBinaryFile = true;
61429
+ console.error(source_default.yellow(`note: file contains non-UTF-8 bytes; storing as kind="binary" ` + `(base64-encoded). Retrieve with: switchroom vault get ${key} | base64 -d`));
61430
+ }
61411
61431
  } catch (err) {
61412
61432
  const msg = err instanceof Error ? err.message : String(err);
61413
61433
  console.error(source_default.red(`Error reading file: ${msg}`));
@@ -61422,7 +61442,7 @@ function registerVaultCommand(program3) {
61422
61442
  console.error(source_default.red("Error: Value cannot be empty"));
61423
61443
  process.exit(1);
61424
61444
  }
61425
- if (formatHint) {
61445
+ if (formatHint && !isBinaryFile) {
61426
61446
  const validationError = validateFormatHint(value, formatHint);
61427
61447
  if (validationError) {
61428
61448
  console.error(source_default.red(`Error: format validation failed for --format ${formatHint}: ${validationError}`));
@@ -61451,7 +61471,11 @@ function registerVaultCommand(program3) {
61451
61471
  }
61452
61472
  } catch {}
61453
61473
  }
61454
- setStringSecret(passphrase, vaultPath, key, value, formatHint, scope);
61474
+ if (isBinaryFile) {
61475
+ setBinarySecret(passphrase, vaultPath, key, value, formatHint, scope);
61476
+ } else {
61477
+ setStringSecret(passphrase, vaultPath, key, value, formatHint, scope);
61478
+ }
61455
61479
  if (formatHint && scope) {
61456
61480
  const scopeDesc = [
61457
61481
  scope.allow?.length ? `allow: ${scope.allow.join(", ")}` : "",
@@ -62193,13 +62217,12 @@ function registerDispatchVerb(tg, _program) {
62193
62217
  `)) {
62194
62218
  console.log(` ${line}`);
62195
62219
  }
62196
- console.log(` model: ${rule.model ?? "claude-sonnet-4-6"}`);
62197
62220
  }
62198
62221
  console.log();
62199
62222
  if (matchCount === 0) {
62200
62223
  console.log(source_default.yellow("No rules matched \u2014 no dispatch would fire."));
62201
62224
  } else {
62202
- console.log(source_default.green(`${matchCount} rule(s) matched. ` + `Run without --dry-run in production to spawn claude -p.`));
62225
+ console.log(source_default.green(`${matchCount} rule(s) matched. ` + `The webhook turn injects into the agent's live session \u2014 ` + `agent's configured model wins.`));
62203
62226
  }
62204
62227
  }));
62205
62228
  }
@@ -74040,7 +74063,7 @@ function detectInstallType() {
74040
74063
 
74041
74064
  // src/cli/operator-uid.ts
74042
74065
  import {
74043
- chownSync as chownSync2,
74066
+ chownSync as chownSync3,
74044
74067
  existsSync as existsSync66,
74045
74068
  lstatSync as lstatSync7,
74046
74069
  readdirSync as readdirSync24,
@@ -74074,7 +74097,7 @@ function operatorOwnedPaths(home2) {
74074
74097
  ];
74075
74098
  }
74076
74099
  function restoreOperatorOwnership(home2, operatorUid, deps = {}) {
74077
- const chown = deps.chown ?? ((p, u, g) => chownSync2(p, u, g));
74100
+ const chown = deps.chown ?? ((p, u, g) => chownSync3(p, u, g));
74078
74101
  const exists = deps.exists ?? ((p) => existsSync66(p));
74079
74102
  const isSymlink = deps.isSymlink ?? ((p) => {
74080
74103
  try {