import { __name } from './chunk-IBAHCH6O.js';
import { spawn, execFileSync, spawnSync } from 'child_process';
import fs2, { existsSync } from 'fs';
import path, { join } from 'path';
import { fileURLToPath } from 'url';
import net from 'net';
import crypto, { webcrypto } from 'crypto';
import os from 'os';

var _isWSL;
function isWSL() {
  if (_isWSL !== void 0) return _isWSL;
  if (process.env.WSL_DISTRO_NAME) {
    _isWSL = true;
    return true;
  }
  try {
    const version = fs2.readFileSync("/proc/version", "utf-8");
    _isWSL = /microsoft|wsl/i.test(version);
  } catch {
    _isWSL = false;
  }
  return _isWSL;
}
__name(isWSL, "isWSL");

// src/lib/local-encrypt/binary-resolver.ts
var __dirname$1 = path.dirname(fileURLToPath(import.meta.url));
function debug(msg) {
  if (process.env.VARLOCK_DEBUG) {
    process.stderr.write(`[varlock:binary-resolver] ${msg}
`);
  }
}
__name(debug, "debug");
var BINARY_NAME = "varlock-local-encrypt";
var MACOS_APP_BUNDLE = "VarlockEnclave.app";
function resolvePackageRoot() {
  let dir = __dirname$1;
  for (let i = 0; i < 10; i++) {
    const pkgJsonPath = path.join(dir, "package.json");
    if (fs2.existsSync(pkgJsonPath)) {
      try {
        const pkgJson = JSON.parse(fs2.readFileSync(pkgJsonPath, "utf-8"));
        if (pkgJson.name === "varlock") return dir;
      } catch {
      }
    }
    const parent = path.dirname(dir);
    if (parent === dir) break;
    dir = parent;
  }
  return path.resolve(__dirname$1, "..", "..", "..");
}
__name(resolvePackageRoot, "resolvePackageRoot");
function getPlatformBinaryName() {
  if (process.platform === "win32" || isWSL()) return `${BINARY_NAME}.exe`;
  return BINARY_NAME;
}
__name(getPlatformBinaryName, "getPlatformBinaryName");
function getNativeBinSubdir() {
  if (process.platform === "darwin") return "darwin";
  if (process.platform === "win32") return `win32-${process.arch}`;
  if (isWSL()) return "win32-x64";
  return `${process.platform}-${process.arch}`;
}
__name(getNativeBinSubdir, "getNativeBinSubdir");
function resolveMacOSBinary(dir) {
  const appBundlePath = path.join(dir, MACOS_APP_BUNDLE, "Contents", "MacOS", BINARY_NAME);
  if (fs2.existsSync(appBundlePath)) return appBundlePath;
  const barePath = path.join(dir, BINARY_NAME);
  if (fs2.existsSync(barePath)) return barePath;
  return void 0;
}
__name(resolveMacOSBinary, "resolveMacOSBinary");
function resolveStandardBinary(dir) {
  const binaryPath = path.join(dir, getPlatformBinaryName());
  if (fs2.existsSync(binaryPath)) return binaryPath;
  return void 0;
}
__name(resolveStandardBinary, "resolveStandardBinary");
function resolveBinaryFromDir(dir) {
  if (process.platform === "darwin") return resolveMacOSBinary(dir);
  return resolveStandardBinary(dir);
}
__name(resolveBinaryFromDir, "resolveBinaryFromDir");
function resolveSeaSibling() {
  const execDir = path.dirname(fs2.realpathSync(process.execPath));
  const sibling = resolveBinaryFromDir(execDir);
  if (sibling) return sibling;
  const libexecDir = path.join(execDir, "..", "libexec");
  return resolveBinaryFromDir(libexecDir);
}
__name(resolveSeaSibling, "resolveSeaSibling");
function resolveNpmBundled() {
  const packageRoot = resolvePackageRoot();
  const nativeBinsDir = path.join(packageRoot, "native-bins", getNativeBinSubdir());
  if (fs2.existsSync(nativeBinsDir)) return resolveBinaryFromDir(nativeBinsDir);
  const adjacentNativeBinsDir = path.join(path.dirname(packageRoot), "native-bins", getNativeBinSubdir());
  if (fs2.existsSync(adjacentNativeBinsDir)) return resolveBinaryFromDir(adjacentNativeBinsDir);
  return void 0;
}
__name(resolveNpmBundled, "resolveNpmBundled");
function resolveDevFallback() {
  let dir = __dirname$1;
  for (let i = 0; i < 10; i++) {
    const parent = path.dirname(dir);
    if (parent === dir) break;
    dir = parent;
    if (process.platform === "darwin") {
      const swiftBuild = path.join(dir, "packages", "encryption-binary-swift", "swift", ".build", "release", "VarlockEnclave");
      if (fs2.existsSync(swiftBuild)) return swiftBuild;
    }
    const rustBuild = path.join(dir, "packages", "encryption-binary-rust", "target", "release", getPlatformBinaryName());
    if (fs2.existsSync(rustBuild)) return rustBuild;
  }
  return void 0;
}
__name(resolveDevFallback, "resolveDevFallback");
function ensureExecutable(binaryPath) {
  try {
    fs2.accessSync(binaryPath, fs2.constants.X_OK);
  } catch {
    if (process.platform !== "win32") {
      fs2.chmodSync(binaryPath, 493);
    }
  }
  return binaryPath;
}
__name(ensureExecutable, "ensureExecutable");
var _cachedBinaryPath = null;
function resolveNativeBinary() {
  if (_cachedBinaryPath !== null) return _cachedBinaryPath;
  if (process.env._VARLOCK_FORCE_FILE_ENCRYPTION_FALLBACK) {
    debug("_VARLOCK_FORCE_FILE_ENCRYPTION_FALLBACK is set \u2014 skipping native binary resolution");
    _cachedBinaryPath = void 0;
    return void 0;
  }
  debug(`resolving: platform=${process.platform}, isWSL=${isWSL()}, binaryName=${getPlatformBinaryName()}, subdir=${getNativeBinSubdir()}`);
  const seaSibling = resolveSeaSibling();
  if (seaSibling) {
    debug(`resolved via SEA sibling: ${seaSibling}`);
    _cachedBinaryPath = ensureExecutable(seaSibling);
    return _cachedBinaryPath;
  }
  const npmBundled = resolveNpmBundled();
  if (npmBundled) {
    debug(`resolved via npm bundled: ${npmBundled}`);
    _cachedBinaryPath = ensureExecutable(npmBundled);
    return _cachedBinaryPath;
  }
  const devFallback = resolveDevFallback();
  if (devFallback) {
    debug(`resolved via dev fallback: ${devFallback}`);
    _cachedBinaryPath = ensureExecutable(devFallback);
    return _cachedBinaryPath;
  }
  debug("NOT FOUND: no binary resolved from any strategy");
  debug(`  SEA sibling dir: ${path.dirname(process.execPath)}`);
  const packageRoot = resolvePackageRoot();
  debug(`  npm bundled dir: ${path.join(packageRoot, "native-bins", getNativeBinSubdir())}`);
  _cachedBinaryPath = void 0;
  return void 0;
}
__name(resolveNativeBinary, "resolveNativeBinary");
function getUserVarlockDir() {
  const home = os.homedir();
  if (process.env.XDG_CONFIG_HOME) {
    return join(process.env.XDG_CONFIG_HOME, "varlock");
  }
  const legacyDir = join(home, ".varlock");
  if (existsSync(legacyDir)) {
    return legacyDir;
  }
  return join(home, ".config", "varlock");
}
__name(getUserVarlockDir, "getUserVarlockDir");

// src/lib/local-encrypt/daemon-client.ts
var SEND_TIMEOUT_MS = 3e4;
var BIOMETRIC_TIMEOUT_MS = 9e4;
var INTERACTIVE_TIMEOUT_MS = 5 * 6e4;
var KILL_GRACE_MS = 2e3;
function debug2(msg) {
  if (process.env.VARLOCK_DEBUG) {
    process.stderr.write(`[varlock:daemon-client] ${msg}
`);
  }
}
__name(debug2, "debug");
function killDaemonProcess(pid) {
  try {
    process.kill(pid, "SIGTERM");
  } catch {
    return true;
  }
  const start = Date.now();
  while (Date.now() - start < KILL_GRACE_MS) {
    try {
      process.kill(pid, 0);
    } catch {
      return true;
    }
    Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100);
  }
  debug2(`daemon pid ${pid} didn't respond to SIGTERM, sending SIGKILL`);
  try {
    process.kill(pid, "SIGKILL");
  } catch {
    return true;
  }
  const killStart = Date.now();
  while (Date.now() - killStart < 500) {
    try {
      process.kill(pid, 0);
    } catch {
      return true;
    }
    Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 50);
  }
  debug2(`daemon pid ${pid} is unkillable (likely in uninterruptible kernel wait) \u2014 proceeding anyway`);
  return false;
}
__name(killDaemonProcess, "killDaemonProcess");
function getSocketDir() {
  return path.join(getUserVarlockDir(), "local-encrypt");
}
__name(getSocketDir, "getSocketDir");
function getSocketPath() {
  if (process.platform === "win32") {
    return "\\\\.\\pipe\\varlock-local-encrypt";
  }
  return path.join(getSocketDir(), "daemon.sock");
}
__name(getSocketPath, "getSocketPath");
function getLockPath() {
  return `${getSocketPath()}.lock`;
}
__name(getLockPath, "getLockPath");
function getPidPath() {
  return path.join(getSocketDir(), "daemon.pid");
}
__name(getPidPath, "getPidPath");
function getDaemonInfoPath() {
  return path.join(getSocketDir(), "daemon.info");
}
__name(getDaemonInfoPath, "getDaemonInfoPath");
function getDaemonStateFiles() {
  const files = [getPidPath(), getDaemonInfoPath()];
  if (process.platform !== "win32") {
    files.push(getSocketPath(), getLockPath());
  }
  return files;
}
__name(getDaemonStateFiles, "getDaemonStateFiles");
function cleanupDaemonFiles() {
  for (const file of getDaemonStateFiles()) {
    try {
      fs2.unlinkSync(file);
    } catch {
    }
  }
}
__name(cleanupDaemonFiles, "cleanupDaemonFiles");
function checkDaemonBinaryStale() {
  const infoPath = getDaemonInfoPath();
  const pidPath = getPidPath();
  let info;
  try {
    info = JSON.parse(fs2.readFileSync(infoPath, "utf-8"));
  } catch {
  }
  const currentBinaryPath = resolveNativeBinary();
  if (!currentBinaryPath) return void 0;
  if (info) {
    if (currentBinaryPath !== info.binaryPath) {
      debug2(`daemon binary path changed: ${info.binaryPath} \u2192 ${currentBinaryPath}`);
    } else {
      try {
        const stat = fs2.statSync(currentBinaryPath);
        if (stat.mtimeMs === info.binaryMtimeMs) {
          debug2("daemon binary is current \u2014 no restart needed");
          return void 0;
        }
        debug2(`daemon binary mtime changed: ${info.binaryMtimeMs} \u2192 ${stat.mtimeMs}`);
      } catch {
        return void 0;
      }
    }
  } else {
    debug2("no daemon.info file \u2014 treating running daemon as stale");
  }
  try {
    const pid = parseInt(fs2.readFileSync(pidPath, "utf-8").trim(), 10);
    process.kill(pid, 0);
    return pid;
  } catch {
    debug2("stale PID file points to dead process \u2014 cleaning up");
    cleanupDaemonFiles();
    return void 0;
  }
}
__name(checkDaemonBinaryStale, "checkDaemonBinaryStale");
function writeDaemonInfo(binaryPath) {
  try {
    const stat = fs2.statSync(binaryPath);
    fs2.writeFileSync(getDaemonInfoPath(), JSON.stringify({
      binaryPath,
      binaryMtimeMs: stat.mtimeMs
    }));
  } catch {
  }
}
__name(writeDaemonInfo, "writeDaemonInfo");
var DaemonClient = class {
  static {
    __name(this, "DaemonClient");
  }
  socket = null;
  messageQueue = /* @__PURE__ */ new Map();
  isConnected = false;
  buffer = Buffer.alloc(0);
  connectingPromise = null;
  /** Set after we spawn a daemon in this process — skip stale check to avoid restart loops */
  spawnedInThisProcess = false;
  async ensureConnected() {
    if (this.isConnected && this.socket) return;
    if (this.connectingPromise) return this.connectingPromise;
    this.connectingPromise = this.doConnect();
    try {
      await this.connectingPromise;
    } finally {
      this.connectingPromise = null;
    }
  }
  /**
   * Try to connect to an existing daemon without spawning a new one.
   * Returns true if connected, false if no daemon is running.
   */
  async tryConnect() {
    if (this.isConnected && this.socket) return true;
    const socketPath = getSocketPath();
    try {
      await this.connectToSocket(socketPath);
      return true;
    } catch {
      return false;
    }
  }
  async doConnect() {
    const socketPath = getSocketPath();
    const stalePid = this.spawnedInThisProcess ? void 0 : checkDaemonBinaryStale();
    if (stalePid) {
      debug2(`killing stale daemon (pid ${stalePid}) \u2014 binary has been updated`);
      killDaemonProcess(stalePid);
      cleanupDaemonFiles();
    } else {
      try {
        await this.connectToSocket(socketPath);
        return;
      } catch {
      }
    }
    try {
      await this.spawnDaemon();
    } catch (err) {
      debug2(`spawnDaemon failed: ${err instanceof Error ? err.message : err}`);
      await new Promise((r) => {
        setTimeout(r, 1e3);
      });
    }
    await this.connectToSocket(socketPath);
  }
  async decrypt(ciphertext, keyId = "varlock-default") {
    return this.withRetry(async () => {
      await this.ensureConnected();
      const result = await this.sendMessage({
        action: "decrypt",
        payload: { ciphertext, keyId }
      }, BIOMETRIC_TIMEOUT_MS);
      if (typeof result === "string") return result;
      if (result && typeof result === "object" && "error" in result) {
        throw new Error(String(result.error));
      }
      return String(result);
    });
  }
  async promptSecret(opts) {
    return this.withRetry(async () => {
      await this.ensureConnected();
      try {
        const result = await this.sendMessage({
          action: "prompt-secret",
          payload: {
            itemKey: opts?.itemKey,
            message: opts?.message,
            keyId: opts?.keyId
          }
        }, INTERACTIVE_TIMEOUT_MS);
        if (result && typeof result === "object" && "ciphertext" in result) {
          return result.ciphertext;
        }
        return void 0;
      } catch (err) {
        if (err instanceof Error && err.message === "cancelled") return void 0;
        throw err;
      }
    });
  }
  async invalidateSession() {
    return this.withRetry(async () => {
      await this.ensureConnected();
      await this.sendMessage({ action: "invalidate-session" });
    });
  }
  async keychainGet(opts) {
    return this.withRetry(async () => {
      await this.ensureConnected();
      const result = await this.sendMessage({
        action: "keychain-get",
        payload: opts
      }, BIOMETRIC_TIMEOUT_MS);
      if (typeof result === "string") return result;
      if (result && typeof result === "object" && "error" in result) {
        throw new Error(String(result.error));
      }
      return String(result);
    });
  }
  async keychainSearch(opts) {
    return this.withRetry(async () => {
      await this.ensureConnected();
      const result = await this.sendMessage({
        action: "keychain-search",
        payload: opts ?? {}
      });
      return result ?? [];
    });
  }
  async keychainPick(opts) {
    return this.withRetry(async () => {
      await this.ensureConnected();
      try {
        const result = await this.sendMessage({
          action: "keychain-pick",
          payload: { itemKey: opts?.itemKey }
        }, INTERACTIVE_TIMEOUT_MS);
        if (result && typeof result === "object" && "service" in result) {
          return result;
        }
        return void 0;
      } catch (err) {
        if (err instanceof Error && err.message === "cancelled") return void 0;
        throw err;
      }
    });
  }
  cleanup() {
    for (const { reject } of this.messageQueue.values()) {
      reject(new Error("Connection closed"));
    }
    this.messageQueue.clear();
    this.socket?.end();
    this.socket = null;
    this.isConnected = false;
    this.buffer = Buffer.alloc(0);
  }
  // -- Private --
  /**
   * Run an async operation, and on recoverable failure (timeout, connection
   * closed) clean up, reconnect to the daemon, and retry once.
   */
  async withRetry(fn) {
    try {
      return await fn();
    } catch (err) {
      const msg = err instanceof Error ? err.message : "";
      const recoverable = msg.includes("timed out") || msg.includes("connection closed") || msg.includes("Not connected");
      if (!recoverable) throw err;
      debug2(`recoverable error, reconnecting: ${msg}`);
      this.forceCleanup();
      await this.ensureConnected();
      return await fn();
    }
  }
  /**
   * Aggressive cleanup: kill the daemon process if we know its PID,
   * then reset client state so the next ensureConnected spawns fresh.
   */
  forceCleanup() {
    this.cleanup();
    this.spawnedInThisProcess = false;
    try {
      const pid = parseInt(fs2.readFileSync(getPidPath(), "utf-8").trim(), 10);
      killDaemonProcess(pid);
    } catch {
    }
    cleanupDaemonFiles();
  }
  connectToSocket(socketPath) {
    return new Promise((resolve, reject) => {
      const socket = new net.Socket();
      const timeout = setTimeout(() => {
        socket.destroy();
        reject(new Error("Connection timeout"));
      }, 5e3);
      socket.on("connect", () => {
        clearTimeout(timeout);
        this.socket = socket;
        this.isConnected = true;
        this.buffer = Buffer.alloc(0);
        resolve();
      });
      socket.on("data", (data) => {
        this.handleData(data);
      });
      socket.on("error", (err) => {
        clearTimeout(timeout);
        this.isConnected = false;
        reject(err);
      });
      socket.on("close", () => {
        this.isConnected = false;
        this.socket = null;
        for (const { reject: rej } of this.messageQueue.values()) {
          rej(new Error("Daemon connection closed"));
        }
        this.messageQueue.clear();
        this.buffer = Buffer.alloc(0);
      });
      socket.connect(socketPath);
    });
  }
  handleData(data) {
    this.buffer = Buffer.concat([this.buffer, data]);
    while (this.buffer.length >= 4) {
      const messageLength = this.buffer.readUInt32LE(0);
      if (this.buffer.length < 4 + messageLength) break;
      const messageData = this.buffer.subarray(4, 4 + messageLength);
      this.buffer = this.buffer.subarray(4 + messageLength);
      try {
        const message = JSON.parse(messageData.toString());
        if (message.id && this.messageQueue.has(message.id)) {
          const { resolve: res, reject: rej } = this.messageQueue.get(message.id);
          this.messageQueue.delete(message.id);
          if (message.error) {
            rej(new Error(message.error));
          } else {
            res(message.result);
          }
        }
      } catch {
      }
    }
  }
  sendMessage(message, timeoutMs = SEND_TIMEOUT_MS) {
    return new Promise((resolve, reject) => {
      if (!this.isConnected || !this.socket) {
        reject(new Error("Not connected to daemon"));
        return;
      }
      const messageId = `${Date.now().toString(36)}-${crypto.randomBytes(4).toString("hex")}`;
      const messageWithId = { ...message, id: messageId };
      const jsonData = JSON.stringify(messageWithId);
      const messageBytes = Buffer.from(jsonData, "utf-8");
      const lengthBuf = Buffer.alloc(4);
      lengthBuf.writeUInt32LE(messageBytes.length, 0);
      const timeout = setTimeout(() => {
        this.messageQueue.delete(messageId);
        reject(new Error(`Daemon message timed out after ${timeoutMs}ms (action: ${message.action})`));
      }, timeoutMs);
      this.messageQueue.set(messageId, {
        resolve: /* @__PURE__ */ __name((value) => {
          clearTimeout(timeout);
          resolve(value);
        }, "resolve"),
        reject: /* @__PURE__ */ __name((err) => {
          clearTimeout(timeout);
          reject(err);
        }, "reject")
      });
      this.socket.write(Buffer.concat([lengthBuf, messageBytes]));
    });
  }
  async spawnDaemon() {
    if (isWSL()) {
      throw new Error(
        "DaemonClient is not supported on WSL2. The Windows encryption daemon uses a Windows named pipe that Linux socket APIs cannot connect to. Use the Windows binary directly instead."
      );
    }
    const binaryPath = resolveNativeBinary();
    if (!binaryPath) {
      throw new Error("Native encryption binary not found \u2014 cannot start daemon");
    }
    const socketPath = getSocketPath();
    const pidPath = getPidPath();
    const isWindows = process.platform === "win32";
    if (!isWindows) {
      fs2.mkdirSync(path.dirname(socketPath), { recursive: true });
    }
    fs2.mkdirSync(path.dirname(pidPath), { recursive: true });
    if (fs2.existsSync(pidPath)) {
      try {
        const pid = parseInt(fs2.readFileSync(pidPath, "utf-8").trim(), 10);
        process.kill(pid, 0);
        try {
          await this.connectToSocket(socketPath);
          return;
        } catch {
          debug2(`daemon pid ${pid} alive but socket unresponsive \u2014 killing`);
          killDaemonProcess(pid);
        }
      } catch {
      }
    }
    cleanupDaemonFiles();
    if (!isWindows && fs2.existsSync(socketPath)) {
      throw new Error(`Failed to clean up stale socket file: ${socketPath}`);
    }
    return new Promise((resolve, reject) => {
      const child = spawn(binaryPath, [
        "daemon",
        "--socket-path",
        socketPath,
        "--pid-path",
        pidPath
      ], {
        detached: true,
        stdio: ["ignore", "pipe", "pipe"]
      });
      const timeout = setTimeout(() => {
        reject(new Error("Daemon failed to start within timeout"));
      }, 1e4);
      let stdoutData = "";
      let stderrData = "";
      child.stdout.on("data", (data) => {
        stdoutData += data.toString();
        try {
          const parsed = JSON.parse(stdoutData);
          if (parsed.ready) {
            clearTimeout(timeout);
            writeDaemonInfo(binaryPath);
            this.spawnedInThisProcess = true;
            child.unref();
            child.stdout.destroy();
            child.stderr.destroy();
            resolve();
          } else if (parsed.alreadyRunning) {
            clearTimeout(timeout);
            child.unref();
            child.stdout.destroy();
            child.stderr.destroy();
            resolve();
          }
        } catch {
        }
      });
      child.stderr.on("data", (data) => {
        stderrData += data.toString();
      });
      child.on("error", (err) => {
        clearTimeout(timeout);
        reject(new Error(`Failed to spawn daemon: ${err.message}`));
      });
      child.on("exit", (code) => {
        clearTimeout(timeout);
        if (code !== 0) {
          const details = [
            stderrData.trim() && `stderr: ${stderrData.trim()}`,
            stdoutData.trim() && `stdout: ${stdoutData.trim()}`,
            `binary: ${binaryPath}`,
            `socket: ${socketPath}`
          ].filter(Boolean).join("\n");
          reject(new Error(`Daemon exited with code ${code}
${details}`));
        }
      });
    });
  }
};
var subtle = webcrypto.subtle;
var PAYLOAD_VERSION = 1;
var HKDF_SALT = new TextEncoder().encode("varlock-ecies-v1");
var EC_ALGORITHM = { name: "ECDH", namedCurve: "P-256" };
var PUBLIC_KEY_LENGTH = 65;
var NONCE_LENGTH = 12;
var TAG_LENGTH = 16;
var HEADER_LENGTH = 1 + PUBLIC_KEY_LENGTH + NONCE_LENGTH;
var bs = /* @__PURE__ */ __name((data) => data, "bs");
function concatBuffers(...buffers) {
  const totalLength = buffers.reduce((sum, b) => sum + b.length, 0);
  const result = new Uint8Array(totalLength);
  let offset = 0;
  for (const buf of buffers) {
    result.set(buf, offset);
    offset += buf.length;
  }
  return result;
}
__name(concatBuffers, "concatBuffers");
function bufferToBase64(buffer) {
  if (buffer instanceof Uint8Array) {
    return Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength).toString("base64");
  }
  return Buffer.from(buffer).toString("base64");
}
__name(bufferToBase64, "bufferToBase64");
function base64ToUint8(base64) {
  const buf = Buffer.from(base64, "base64");
  return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
}
__name(base64ToUint8, "base64ToUint8");
async function hkdfSha256(ikm, salt, info, outputByteCount) {
  const saltKey = await subtle.importKey("raw", bs(salt), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
  const prk = new Uint8Array(await subtle.sign("HMAC", saltKey, bs(ikm)));
  const prkKey = await subtle.importKey("raw", bs(prk), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
  const okm = new Uint8Array(outputByteCount);
  let t = new Uint8Array(0);
  let offset = 0;
  let counter = 1;
  while (offset < outputByteCount) {
    const input = concatBuffers(t, info, new Uint8Array([counter]));
    t = new Uint8Array(await subtle.sign("HMAC", prkKey, bs(input)));
    okm.set(t.slice(0, Math.min(t.length, outputByteCount - offset)), offset);
    offset += t.length;
    counter++;
  }
  return okm;
}
__name(hkdfSha256, "hkdfSha256");
async function importPublicKey(base64) {
  return subtle.importKey("raw", bs(base64ToUint8(base64)), EC_ALGORITHM, true, []);
}
__name(importPublicKey, "importPublicKey");
async function importPrivateKey(base64) {
  return subtle.importKey("pkcs8", bs(base64ToUint8(base64)), EC_ALGORITHM, true, ["deriveBits"]);
}
__name(importPrivateKey, "importPrivateKey");
async function createKeyPair() {
  const keyPair = await subtle.generateKey(EC_ALGORITHM, true, ["deriveBits"]);
  const publicKeyRaw = await subtle.exportKey("raw", keyPair.publicKey);
  const privateKeyPkcs8 = await subtle.exportKey("pkcs8", keyPair.privateKey);
  return {
    publicKey: bufferToBase64(publicKeyRaw),
    privateKey: bufferToBase64(privateKeyPkcs8)
  };
}
__name(createKeyPair, "createKeyPair");
async function encrypt(publicKeyBase64, plaintext) {
  const recipientPublicKey = await importPublicKey(publicKeyBase64);
  const recipientPubKeyRaw = base64ToUint8(publicKeyBase64);
  const ephemeralKeyPair = await subtle.generateKey(EC_ALGORITHM, true, ["deriveBits"]);
  const ephemeralPubKeyRaw = new Uint8Array(await subtle.exportKey("raw", ephemeralKeyPair.publicKey));
  const sharedSecretBits = await subtle.deriveBits(
    { name: "ECDH", public: recipientPublicKey },
    ephemeralKeyPair.privateKey,
    256
  );
  const sharedSecret = new Uint8Array(sharedSecretBits);
  const info = concatBuffers(ephemeralPubKeyRaw, recipientPubKeyRaw);
  const aesKey = await hkdfSha256(sharedSecret, HKDF_SALT, info, 32);
  const nonce = webcrypto.getRandomValues(new Uint8Array(NONCE_LENGTH));
  const plaintextBytes = new TextEncoder().encode(plaintext);
  const cryptoKey = await subtle.importKey("raw", bs(aesKey), "AES-GCM", false, ["encrypt"]);
  const encrypted = new Uint8Array(
    await subtle.encrypt({ name: "AES-GCM", iv: bs(nonce), tagLength: TAG_LENGTH * 8 }, cryptoKey, bs(plaintextBytes))
  );
  const ciphertext = encrypted.slice(0, encrypted.length - TAG_LENGTH);
  const tag = encrypted.slice(encrypted.length - TAG_LENGTH);
  const payload = concatBuffers(
    new Uint8Array([PAYLOAD_VERSION]),
    ephemeralPubKeyRaw,
    nonce,
    ciphertext,
    tag
  );
  return bufferToBase64(payload);
}
__name(encrypt, "encrypt");
async function decrypt(privateKeyBase64, publicKeyBase64, ciphertextBase64) {
  const payloadBytes = base64ToUint8(ciphertextBase64);
  if (payloadBytes.byteLength < HEADER_LENGTH + TAG_LENGTH) {
    throw new Error("Payload too short");
  }
  const version = payloadBytes[0];
  if (version !== PAYLOAD_VERSION) {
    throw new Error(`Unsupported payload version: ${version}`);
  }
  const ephemeralPubKeyRaw = payloadBytes.slice(1, 1 + PUBLIC_KEY_LENGTH);
  const nonce = payloadBytes.slice(1 + PUBLIC_KEY_LENGTH, HEADER_LENGTH);
  const ciphertextAndTag = payloadBytes.slice(HEADER_LENGTH);
  if (ciphertextAndTag.length < TAG_LENGTH) {
    throw new Error("Payload too short for tag");
  }
  const privateKey = await importPrivateKey(privateKeyBase64);
  const ephemeralPublicKey = await subtle.importKey("raw", bs(ephemeralPubKeyRaw), EC_ALGORITHM, true, []);
  const recipientPubKeyRaw = base64ToUint8(publicKeyBase64);
  const sharedSecretBits = await subtle.deriveBits(
    { name: "ECDH", public: ephemeralPublicKey },
    privateKey,
    256
  );
  const sharedSecret = new Uint8Array(sharedSecretBits);
  const info = concatBuffers(ephemeralPubKeyRaw, recipientPubKeyRaw);
  const aesKey = await hkdfSha256(sharedSecret, HKDF_SALT, info, 32);
  const cryptoKey = await subtle.importKey("raw", bs(aesKey), "AES-GCM", false, ["decrypt"]);
  try {
    const decrypted = await subtle.decrypt(
      { name: "AES-GCM", iv: bs(nonce), tagLength: TAG_LENGTH * 8 },
      cryptoKey,
      bs(ciphertextAndTag)
      // already ciphertext || tag
    );
    return new TextDecoder().decode(decrypted);
  } catch (err) {
    throw new Error(
      "Unable to decrypt value",
      { cause: err }
    );
  }
}
__name(decrypt, "decrypt");

// src/lib/local-encrypt/file-backend.ts
var KEY_STORE_SUBDIR = "local-encrypt/keys";
var DEFAULT_KEY_ID = "varlock-default";
function getKeyStorePath() {
  return path.join(getUserVarlockDir(), KEY_STORE_SUBDIR);
}
__name(getKeyStorePath, "getKeyStorePath");
function getKeyFilePath(keyId) {
  return path.join(getKeyStorePath(), `${keyId}.json`);
}
__name(getKeyFilePath, "getKeyFilePath");
function keyExists(keyId = DEFAULT_KEY_ID) {
  return fs2.existsSync(getKeyFilePath(keyId));
}
__name(keyExists, "keyExists");
async function generateKey(keyId = DEFAULT_KEY_ID) {
  const keyPair = await createKeyPair();
  const stored = {
    keyId,
    publicKey: keyPair.publicKey,
    privateKey: keyPair.privateKey,
    createdAt: (/* @__PURE__ */ new Date()).toISOString()
  };
  const keyStorePath = getKeyStorePath();
  fs2.mkdirSync(keyStorePath, { recursive: true });
  const filePath = getKeyFilePath(keyId);
  fs2.writeFileSync(filePath, JSON.stringify(stored, null, 2), { mode: 384 });
  return { keyId, publicKey: keyPair.publicKey };
}
__name(generateKey, "generateKey");
function loadKeyPair(keyId) {
  const filePath = getKeyFilePath(keyId);
  if (!fs2.existsSync(filePath)) {
    throw new Error(`Key not found: ${keyId}`);
  }
  const data = fs2.readFileSync(filePath, "utf-8");
  const parsed = JSON.parse(data);
  const privateKey = parsed.privateKey ?? (parsed.protection === "none" ? parsed.protectedPrivateKey : void 0) ?? parsed.protectedPrivateKey;
  if (!parsed.publicKey || !privateKey) {
    throw new Error(`Invalid key file format for key: ${keyId}`);
  }
  return {
    keyId: parsed.keyId || keyId,
    publicKey: parsed.publicKey,
    privateKey,
    createdAt: parsed.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
    protection: parsed.protection,
    protectedPrivateKey: parsed.protectedPrivateKey
  };
}
__name(loadKeyPair, "loadKeyPair");
function getPublicKey(keyId) {
  return loadKeyPair(keyId).publicKey;
}
__name(getPublicKey, "getPublicKey");
async function encryptValue(plaintext, keyId = DEFAULT_KEY_ID) {
  const publicKey = getPublicKey(keyId);
  return encrypt(publicKey, plaintext);
}
__name(encryptValue, "encryptValue");
async function decryptValue(ciphertext, keyId = DEFAULT_KEY_ID) {
  const stored = loadKeyPair(keyId);
  return decrypt(stored.privateKey, stored.publicKey, ciphertext);
}
__name(decryptValue, "decryptValue");

// src/lib/local-encrypt/index.ts
var DEFAULT_KEY_ID2 = "varlock-default";
function debug3(msg) {
  if (process.env.VARLOCK_DEBUG) {
    process.stderr.write(`[varlock:local-encrypt] ${msg}
`);
  }
}
__name(debug3, "debug");
var SHELL_RUNNER_NAMES = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "dash", "fish", "ksh", "csh", "tcsh"]);
var VARLOCK_LAUNCHER_NAMES = /* @__PURE__ */ new Set(["varlock", "varlock.exe", "varlock.cmd"]);
var PACKAGE_MANAGER_RUNNER_NAMES = /* @__PURE__ */ new Set(["bun", "node", "npm", "npx", "pnpm", "pnpx", "yarn", "yarnpkg"]);
var NO_TTY_SESSION_ENV_KEYS = [
  "CODEX_THREAD_ID",
  "CLAUDE_CODE_SESSION_ID",
  "CLAUDE_SESSION_ID"
];
function getProcessName(pid) {
  try {
    const exePath = fs2.readlinkSync(`/proc/${pid}/exe`);
    return exePath.split("/").pop()?.toLowerCase();
  } catch {
  }
  try {
    return fs2.readFileSync(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
  } catch {
    return void 0;
  }
}
__name(getProcessName, "getProcessName");
function getProcessArgs(pid) {
  try {
    return fs2.readFileSync(`/proc/${pid}/cmdline`, "utf-8").split("\0").filter(Boolean);
  } catch {
    return [];
  }
}
__name(getProcessArgs, "getProcessArgs");
function processCommandLineLaunchesVarlock(pid) {
  return getProcessArgs(pid).some((arg) => {
    const name = arg.split("/").pop()?.toLowerCase();
    return Boolean(
      name && VARLOCK_LAUNCHER_NAMES.has(name) || arg.includes("/node_modules/.bin/varlock") || arg.includes("/varlock/bin/cli.js") || arg.includes("/packages/varlock/bin/cli.js")
    );
  });
}
__name(processCommandLineLaunchesVarlock, "processCommandLineLaunchesVarlock");
function isEphemeralRunner(pid) {
  const name = getProcessName(pid);
  if (!name) return false;
  if (SHELL_RUNNER_NAMES.has(name) || VARLOCK_LAUNCHER_NAMES.has(name)) return true;
  return PACKAGE_MANAGER_RUNNER_NAMES.has(name) && processCommandLineLaunchesVarlock(pid);
}
__name(isEphemeralRunner, "isEphemeralRunner");
function selectScopePidFromChain(chain) {
  if (chain.length < 2) return void 0;
  if (chain.length >= 4) {
    let scopePid = chain[chain.length - 3];
    if (isEphemeralRunner(scopePid)) {
      const fallback = chain[chain.length - 2];
      scopePid = isEphemeralRunner(fallback) ? chain[chain.length - 1] : fallback;
    }
    return scopePid;
  }
  return chain[chain.length - 1];
}
__name(selectScopePidFromChain, "selectScopePidFromChain");
function getProcessStartTime(pid) {
  try {
    const scopeStat = fs2.readFileSync(`/proc/${pid}/stat`, "utf-8");
    const scopeFields = scopeStat.split(") ");
    if (scopeFields.length >= 2) {
      return parseInt(scopeFields[1].split(" ")[19], 10) || 0;
    }
  } catch {
  }
  return 0;
}
__name(getProcessStartTime, "getProcessStartTime");
function getNoTtySessionIdFromEnv() {
  for (const key of NO_TTY_SESSION_ENV_KEYS) {
    const value = process.env[key]?.trim();
    if (value) return `env:${key}:${value}`;
  }
  return void 0;
}
__name(getNoTtySessionIdFromEnv, "getNoTtySessionIdFromEnv");
function getParentSessionId() {
  try {
    const ttyPath = fs2.readlinkSync("/proc/self/fd/0");
    if (ttyPath && ttyPath.startsWith("/dev/")) {
      return ttyPath;
    }
  } catch {
  }
  try {
    const chain = [process.pid];
    let current = process.pid;
    for (let i = 0; i < 64; i++) {
      const stat = fs2.readFileSync(`/proc/${current}/stat`, "utf-8");
      const fields = stat.split(") ");
      if (fields.length < 2) break;
      const ppid = parseInt(fields[1].split(" ")[1], 10);
      if (!ppid || ppid <= 1) break;
      chain.push(ppid);
      current = ppid;
    }
    const scopePid = selectScopePidFromChain(chain);
    if (scopePid !== void 0) {
      const startTime = getProcessStartTime(scopePid);
      return `ptree:${scopePid}:${startTime}`;
    }
  } catch {
  }
  return `pid:${process.pid}`;
}
__name(getParentSessionId, "getParentSessionId");
var _cachedSessionId;
function getSelfSessionId() {
  if (_cachedSessionId) return _cachedSessionId;
  const parentSessionId = getParentSessionId();
  const envSessionId = getNoTtySessionIdFromEnv();
  if (envSessionId) {
    _cachedSessionId = `${envSessionId}|${parentSessionId}`;
    return _cachedSessionId;
  }
  _cachedSessionId = parentSessionId;
  return _cachedSessionId;
}
__name(getSelfSessionId, "getSelfSessionId");
var _wslDaemonPrestartAttempted = false;
function toWindowsPathFromWsl(pathInWsl) {
  if (!isWSL()) return void 0;
  try {
    return execFileSync("wslpath", ["-w", pathInWsl], {
      encoding: "utf-8",
      timeout: 1e4
    }).trim();
  } catch (err) {
    debug3(`toWindowsPathFromWsl failed: ${err instanceof Error ? err.message : err}`);
    return void 0;
  }
}
__name(toWindowsPathFromWsl, "toWindowsPathFromWsl");
function tryPrestartWindowsDaemonFromWsl(binaryPath) {
  if (_wslDaemonPrestartAttempted) {
    return true;
  }
  const windowsPath = toWindowsPathFromWsl(binaryPath);
  if (!windowsPath) {
    return false;
  }
  const escapedPath = windowsPath.replaceAll("'", "''");
  const psScript = `Start-Process -WindowStyle Hidden -FilePath '${escapedPath}' -ArgumentList 'start-daemon'`;
  const proc = spawnSync("powershell.exe", [
    "-NoProfile",
    "-NonInteractive",
    "-ExecutionPolicy",
    "Bypass",
    "-Command",
    psScript
  ], {
    encoding: "utf-8",
    timeout: 2e4
  });
  if (proc.error) {
    debug3(`tryPrestartWindowsDaemonFromWsl: powershell error: ${proc.error.message}`);
    return false;
  }
  if (proc.status !== 0) {
    debug3(`tryPrestartWindowsDaemonFromWsl: powershell exit ${proc.status}: ${(proc.stderr || proc.stdout || "").trim()}`);
    return false;
  }
  debug3("tryPrestartWindowsDaemonFromWsl: start-daemon invoked via PowerShell");
  _wslDaemonPrestartAttempted = true;
  return true;
}
__name(tryPrestartWindowsDaemonFromWsl, "tryPrestartWindowsDaemonFromWsl");
function pingWindowsDaemonFromWsl(binaryPath, timeoutMs = 2e3) {
  const proc = spawnSync(binaryPath, ["ping-daemon"], {
    encoding: "utf-8",
    timeout: timeoutMs
  });
  if (proc.error || proc.status !== 0) {
    return false;
  }
  try {
    const parsed = JSON.parse((proc.stdout || "").trim());
    return parsed.ready === true;
  } catch {
    return false;
  }
}
__name(pingWindowsDaemonFromWsl, "pingWindowsDaemonFromWsl");
function waitForWindowsDaemonFromWsl(binaryPath, timeoutMs = 12e3) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    if (pingWindowsDaemonFromWsl(binaryPath)) {
      debug3("waitForWindowsDaemonFromWsl: daemon is ready");
      return true;
    }
    Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 150);
  }
  debug3("waitForWindowsDaemonFromWsl: timed out waiting for daemon readiness");
  return false;
}
__name(waitForWindowsDaemonFromWsl, "waitForWindowsDaemonFromWsl");
function redactDataArg(args) {
  const out = [...args];
  const i = out.indexOf("--data");
  if (i >= 0 && i + 1 < out.length) out[i + 1] = "<redacted>";
  return out;
}
__name(redactDataArg, "redactDataArg");
function runNativeBinary(args, opts) {
  const binaryPath = resolveNativeBinary();
  if (!binaryPath) {
    debug3("runNativeBinary: no binary found");
    throw new Error("Native binary not found");
  }
  debug3(`runNativeBinary: ${binaryPath} ${redactDataArg(args).join(" ")}`);
  const output = execFileSync(binaryPath, args, {
    encoding: "utf-8",
    timeout: opts?.timeout ?? 3e4
  }).trim();
  debug3(`runNativeBinary result: ${opts?.sensitiveOutput ? `<${output.length} chars>` : output.slice(0, 200)}`);
  return output;
}
__name(runNativeBinary, "runNativeBinary");
function runNativeBinaryJson(args, opts) {
  const output = runNativeBinary(args, opts);
  const parsed = JSON.parse(output);
  if (parsed.error) {
    throw new Error(parsed.error);
  }
  return parsed;
}
__name(runNativeBinaryJson, "runNativeBinaryJson");
var cachedBackendInfo;
var cachedStatusKeys;
function detectBackendType() {
  const binaryPath = resolveNativeBinary();
  debug3(`detectBackendType: binaryPath=${binaryPath ?? "NOT FOUND"}, isWSL=${isWSL()}, platform=${process.platform}`);
  if (!binaryPath) {
    const isFileFallback = ["darwin", "win32", "linux"].includes(process.platform);
    return { type: "file", isFileFallback };
  }
  if (isWSL()) return { type: "windows-tpm", isFileFallback: false };
  switch (process.platform) {
    case "darwin":
      return { type: "secure-enclave", isFileFallback: false };
    case "win32":
      return { type: "windows-tpm", isFileFallback: false };
    case "linux":
      return { type: "linux-tpm", isFileFallback: false };
    default:
      return { type: "file", isFileFallback: false };
  }
}
__name(detectBackendType, "detectBackendType");
function getBackendInfo() {
  if (cachedBackendInfo) return cachedBackendInfo;
  const { type, isFileFallback } = detectBackendType();
  const binaryPath = type !== "file" ? resolveNativeBinary() : void 0;
  if (type !== "file" && binaryPath) {
    try {
      const status = runNativeBinaryJson(["status"]);
      debug3(`getBackendInfo: status result: hardwareBacked=${status.hardwareBacked}, biometricAvailable=${status.biometricAvailable}, backend=${status.backend}, keys=${status.keys?.join(",")}`);
      cachedStatusKeys = status.keys;
      cachedBackendInfo = {
        type,
        platform: process.platform,
        hardwareBacked: status.hardwareBacked,
        biometricAvailable: status.biometricAvailable,
        binaryPath
      };
    } catch (err) {
      debug3(`getBackendInfo: status command failed: ${err instanceof Error ? err.message : err}`);
      cachedBackendInfo = {
        type,
        platform: process.platform,
        hardwareBacked: type === "secure-enclave",
        biometricAvailable: type === "secure-enclave",
        binaryPath
      };
    }
  } else {
    debug3(`getBackendInfo: using file backend (type=${type}, binaryPath=${binaryPath ?? "none"}, isFileFallback=${isFileFallback})`);
    cachedBackendInfo = {
      type,
      platform: process.platform,
      hardwareBacked: false,
      biometricAvailable: false,
      binaryPath: void 0,
      isFileFallback
    };
  }
  debug3(`getBackendInfo: final result: type=${cachedBackendInfo.type}, biometric=${cachedBackendInfo.biometricAvailable}, hwBacked=${cachedBackendInfo.hardwareBacked}`);
  return cachedBackendInfo;
}
__name(getBackendInfo, "getBackendInfo");
var daemonClient;
function getDaemonClient() {
  daemonClient ||= new DaemonClient();
  return daemonClient;
}
__name(getDaemonClient, "getDaemonClient");
var warnedFileFallback = false;
function warnIfFileFallback(backend) {
  if (warnedFileFallback || !backend.isFileFallback) return;
  if (process.env._VARLOCK_FORCE_FILE_ENCRYPTION_FALLBACK) return;
  warnedFileFallback = true;
  process.stderr.write(
    "[varlock] Warning: native encryption binary not found, falling back to file-based encryption (not hardware-backed)\n"
  );
}
__name(warnIfFileFallback, "warnIfFileFallback");
function keyExists2(keyId = DEFAULT_KEY_ID2) {
  const backend = getBackendInfo();
  if (backend.type === "file") {
    return keyExists(keyId);
  }
  if (cachedStatusKeys) {
    debug3(`keyExists: using cached status keys for ${keyId}`);
    return cachedStatusKeys.includes(keyId);
  }
  const result = runNativeBinaryJson(["key-exists", "--key-id", keyId]);
  return result.exists;
}
__name(keyExists2, "keyExists");
async function generateKey2(keyId = DEFAULT_KEY_ID2) {
  const backend = getBackendInfo();
  if (backend.type === "file") {
    warnIfFileFallback(backend);
    return generateKey(keyId);
  }
  return runNativeBinaryJson(["generate-key", "--key-id", keyId]);
}
__name(generateKey2, "generateKey");
async function ensureKey(keyId = DEFAULT_KEY_ID2) {
  if (!keyExists2(keyId)) {
    await generateKey2(keyId);
  }
}
__name(ensureKey, "ensureKey");
async function encryptValue2(plaintext, keyId = DEFAULT_KEY_ID2) {
  const backend = getBackendInfo();
  if (backend.type === "file") {
    warnIfFileFallback(backend);
    return encryptValue(plaintext, keyId);
  }
  const b64Input = Buffer.from(plaintext, "utf-8").toString("base64");
  const binaryPath = resolveNativeBinary();
  if (!binaryPath) throw new Error("Native binary not found");
  const proc = spawnSync(binaryPath, ["encrypt", "--key-id", keyId, "--data-stdin"], {
    input: b64Input,
    encoding: "utf-8",
    timeout: 3e4
  });
  if (proc.error) throw proc.error;
  const result = JSON.parse(proc.stdout.trim());
  if (result.error) throw new Error(result.error);
  return result.ciphertext;
}
__name(encryptValue2, "encryptValue");
async function decryptValue2(ciphertext, keyId = DEFAULT_KEY_ID2) {
  const backend = getBackendInfo();
  if (backend.type === "file") {
    debug3("decryptValue: using file backend");
    warnIfFileFallback(backend);
    return decryptValue(ciphertext, keyId);
  }
  if (backend.biometricAvailable) {
    if (isWSL()) {
      debug3("decryptValue: WSL2 biometric decrypt via --via-daemon");
      const binaryPath = resolveNativeBinary();
      if (!binaryPath) throw new Error("Native binary not found");
      const daemonAlreadyReady = pingWindowsDaemonFromWsl(binaryPath, 1500);
      const daemonPrestarted = daemonAlreadyReady || tryPrestartWindowsDaemonFromWsl(binaryPath);
      if (!daemonAlreadyReady && daemonPrestarted) {
        waitForWindowsDaemonFromWsl(binaryPath);
      }
      const stdinPayload = JSON.stringify({
        data: ciphertext,
        ttyId: getSelfSessionId()
      });
      const runViaDaemon = /* @__PURE__ */ __name((timeout) => spawnSync(binaryPath, ["decrypt", "--key-id", keyId, "--data-stdin", "--via-daemon"], {
        input: stdinPayload,
        encoding: "utf-8",
        timeout
      }), "runViaDaemon");
      let proc = runViaDaemon(daemonPrestarted ? 12e4 : 6e4);
      const output = (proc.stdout || proc.stderr || "").trim();
      const timedOut = proc.error && proc.error.code === "ETIMEDOUT";
      const needsRetry = Boolean(proc.error) || proc.status !== 0;
      const likelyDaemonStartupIssue = timedOut || /daemon is not running|daemon did not become ready within timeout|schtasks|windows hello daemon/i.test(output);
      if (needsRetry && likelyDaemonStartupIssue) {
        debug3(`decryptValue: via-daemon startup issue detected; attempting native start-daemon bridge. output=${output.slice(0, 180)}`);
        if (tryPrestartWindowsDaemonFromWsl(binaryPath)) {
          proc = runViaDaemon(12e4);
        }
      }
      if (proc.error) throw proc.error;
      if (proc.status !== 0) {
        const finalOutput = (proc.stdout || proc.stderr || "").trim();
        try {
          const parsed = JSON.parse(finalOutput);
          if (parsed.error) throw new Error(parsed.error);
        } catch {
        }
        const windowsPath = toWindowsPathFromWsl(binaryPath);
        const setupHint = windowsPath ? `
Hint: In native Windows PowerShell run:
  Start-Process -WindowStyle Hidden "${windowsPath}" start-daemon` : "";
        throw new Error(`Decrypt failed (exit ${proc.status}): ${finalOutput}${setupHint}`);
      }
      const result2 = JSON.parse(proc.stdout.trim());
      if (result2.error) throw new Error(result2.error);
      debug3(`decryptValue: WSL2 decrypt ok (<${proc.stdout.trim().length} chars>)`);
      return result2.plaintext;
    }
    debug3("decryptValue: biometric decrypt via daemon client");
    const client = getDaemonClient();
    return client.decrypt(ciphertext, keyId);
  }
  debug3("decryptValue: non-biometric one-shot decrypt");
  const result = runNativeBinaryJson(
    ["decrypt", "--key-id", keyId, "--data", ciphertext],
    { sensitiveOutput: true }
  );
  return result.plaintext;
}
__name(decryptValue2, "decryptValue");
async function lockSession() {
  const backend = getBackendInfo();
  if (!backend.biometricAvailable) return;
  const client = getDaemonClient();
  const connected = await client.tryConnect();
  if (!connected) {
    throw new Error("No encryption daemon is running");
  }
  await client.invalidateSession();
}
__name(lockSession, "lockSession");

export { decryptValue2 as decryptValue, encryptValue2 as encryptValue, ensureKey, generateKey2 as generateKey, getBackendInfo, getDaemonClient, getUserVarlockDir, isWSL, keyExists2 as keyExists, lockSession };
//# sourceMappingURL=chunk-JE2IMKMO.js.map
//# sourceMappingURL=chunk-JE2IMKMO.js.map