@hasna/hooks 0.10.2 → 0.10.3

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/bin/index.js CHANGED
@@ -47,7 +47,7 @@ var __export = (target, all) => {
47
47
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
48
48
  var __require = import.meta.require;
49
49
 
50
- // ../hooks0102-standalone-lock/node_modules/commander/lib/error.js
50
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/error.js
51
51
  var require_error = __commonJS((exports) => {
52
52
  class CommanderError extends Error {
53
53
  constructor(exitCode, code, message) {
@@ -71,7 +71,7 @@ var require_error = __commonJS((exports) => {
71
71
  exports.InvalidArgumentError = InvalidArgumentError;
72
72
  });
73
73
 
74
- // ../hooks0102-standalone-lock/node_modules/commander/lib/argument.js
74
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/argument.js
75
75
  var require_argument = __commonJS((exports) => {
76
76
  var { InvalidArgumentError } = require_error();
77
77
 
@@ -150,7 +150,7 @@ var require_argument = __commonJS((exports) => {
150
150
  exports.humanReadableArgName = humanReadableArgName;
151
151
  });
152
152
 
153
- // ../hooks0102-standalone-lock/node_modules/commander/lib/help.js
153
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/help.js
154
154
  var require_help = __commonJS((exports) => {
155
155
  var { humanReadableArgName } = require_argument();
156
156
 
@@ -399,7 +399,7 @@ var require_help = __commonJS((exports) => {
399
399
  exports.Help = Help;
400
400
  });
401
401
 
402
- // ../hooks0102-standalone-lock/node_modules/commander/lib/option.js
402
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/option.js
403
403
  var require_option = __commonJS((exports) => {
404
404
  var { InvalidArgumentError } = require_error();
405
405
 
@@ -550,7 +550,7 @@ var require_option = __commonJS((exports) => {
550
550
  exports.DualOptions = DualOptions;
551
551
  });
552
552
 
553
- // ../hooks0102-standalone-lock/node_modules/commander/lib/suggestSimilar.js
553
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/suggestSimilar.js
554
554
  var require_suggestSimilar = __commonJS((exports) => {
555
555
  var maxDistance = 3;
556
556
  function editDistance(a, b) {
@@ -623,7 +623,7 @@ var require_suggestSimilar = __commonJS((exports) => {
623
623
  exports.suggestSimilar = suggestSimilar;
624
624
  });
625
625
 
626
- // ../hooks0102-standalone-lock/node_modules/commander/lib/command.js
626
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/command.js
627
627
  var require_command = __commonJS((exports) => {
628
628
  var EventEmitter = __require("events").EventEmitter;
629
629
  var childProcess = __require("child_process");
@@ -1866,7 +1866,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1866
1866
  exports.Command = Command;
1867
1867
  });
1868
1868
 
1869
- // ../hooks0102-standalone-lock/node_modules/commander/index.js
1869
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/index.js
1870
1870
  var require_commander = __commonJS((exports) => {
1871
1871
  var { Argument } = require_argument();
1872
1872
  var { Command } = require_command();
@@ -1887,76 +1887,76 @@ var require_commander = __commonJS((exports) => {
1887
1887
  });
1888
1888
 
1889
1889
  // src/lib/app-home.ts
1890
- import { existsSync as existsSync2 } from "fs";
1890
+ import { existsSync as existsSync3 } from "fs";
1891
1891
  import { homedir as homedir2 } from "os";
1892
- import { join as join2, resolve } from "path";
1893
- import { homedir as pathsResolverHomedir } from "os";
1894
- import { join as pathsResolverJoin } from "path";
1895
- function pathsResolverAssertApp(app) {
1892
+ import { join as join3, resolve as resolve2 } from "path";
1893
+ import { homedir as pathsResolverHomedir2 } from "os";
1894
+ import { join as pathsResolverJoin2 } from "path";
1895
+ function pathsResolverAssertApp2(app) {
1896
1896
  if (typeof app !== "string" || app.length === 0) {
1897
1897
  throw new TypeError("paths: app must be a non-empty string");
1898
1898
  }
1899
- if (!PATHS_RESOLVER_APP_SLUG_RE.test(app)) {
1899
+ if (!PATHS_RESOLVER_APP_SLUG_RE2.test(app)) {
1900
1900
  throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
1901
1901
  }
1902
1902
  }
1903
- function pathsResolverAssertKind(kind) {
1904
- if (!Object.keys(PATHS_RESOLVER_KIND_ENV).includes(kind)) {
1905
- throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${Object.keys(PATHS_RESOLVER_KIND_ENV).join(", ")}`);
1903
+ function pathsResolverAssertKind2(kind) {
1904
+ if (!Object.keys(PATHS_RESOLVER_KIND_ENV2).includes(kind)) {
1905
+ throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${Object.keys(PATHS_RESOLVER_KIND_ENV2).join(", ")}`);
1906
1906
  }
1907
1907
  }
1908
- function pathsResolverBaseDir(kind, options) {
1909
- pathsResolverAssertKind(kind);
1908
+ function pathsResolverBaseDir2(kind, options) {
1909
+ pathsResolverAssertKind2(kind);
1910
1910
  const env = options.env ?? process.env;
1911
- const override = env[PATHS_RESOLVER_KIND_ENV[kind]];
1911
+ const override = env[PATHS_RESOLVER_KIND_ENV2[kind]];
1912
1912
  if (typeof override === "string" && override.length > 0)
1913
1913
  return override;
1914
- const home = options.home ?? pathsResolverHomedir();
1914
+ const home = options.home ?? pathsResolverHomedir2();
1915
1915
  const platform = options.platform ?? process.platform;
1916
1916
  if (platform === "darwin") {
1917
1917
  switch (kind) {
1918
1918
  case "config":
1919
1919
  case "data":
1920
- return pathsResolverJoin(home, "Library", "Application Support", "Hasna");
1920
+ return pathsResolverJoin2(home, "Library", "Application Support", "Hasna");
1921
1921
  case "cache":
1922
- return pathsResolverJoin(home, "Library", "Caches", "Hasna");
1922
+ return pathsResolverJoin2(home, "Library", "Caches", "Hasna");
1923
1923
  case "state":
1924
- return pathsResolverJoin(home, "Library", "Logs", "Hasna");
1924
+ return pathsResolverJoin2(home, "Library", "Logs", "Hasna");
1925
1925
  }
1926
1926
  }
1927
1927
  switch (kind) {
1928
1928
  case "config":
1929
- return pathsResolverJoin(home, ".config", "hasna");
1929
+ return pathsResolverJoin2(home, ".config", "hasna");
1930
1930
  case "data":
1931
- return pathsResolverJoin(home, ".local", "share", "hasna");
1931
+ return pathsResolverJoin2(home, ".local", "share", "hasna");
1932
1932
  case "state":
1933
- return pathsResolverJoin(home, ".local", "state", "hasna");
1933
+ return pathsResolverJoin2(home, ".local", "state", "hasna");
1934
1934
  case "cache":
1935
- return pathsResolverJoin(home, ".cache", "hasna");
1935
+ return pathsResolverJoin2(home, ".cache", "hasna");
1936
1936
  }
1937
1937
  }
1938
- function pathsResolverResolve(kind, options) {
1939
- pathsResolverAssertApp(options.app);
1940
- const appSegment = options.internal === true ? pathsResolverJoin("internal", options.app) : options.app;
1941
- return pathsResolverJoin(pathsResolverBaseDir(kind, options), appSegment);
1938
+ function pathsResolverResolve2(kind, options) {
1939
+ pathsResolverAssertApp2(options.app);
1940
+ const appSegment = options.internal === true ? pathsResolverJoin2("internal", options.app) : options.app;
1941
+ return pathsResolverJoin2(pathsResolverBaseDir2(kind, options), appSegment);
1942
1942
  }
1943
- function dataDir(options) {
1944
- return pathsResolverResolve("data", options);
1943
+ function dataDir2(options) {
1944
+ return pathsResolverResolve2("data", options);
1945
1945
  }
1946
1946
  function getHomeDir(env = process.env) {
1947
1947
  return env.HOME || env.USERPROFILE || homedir2();
1948
1948
  }
1949
1949
  function getResolverDataRoot(env = process.env) {
1950
- return dataDir({ app: "hooks", home: getHomeDir(env), env });
1950
+ return dataDir2({ app: "hooks", home: getHomeDir(env), env });
1951
1951
  }
1952
1952
  function getLegacyDataRoot(env = process.env) {
1953
- return join2(getHomeDir(env), ".hasna", "hooks");
1953
+ return join3(getHomeDir(env), ".hasna", "hooks");
1954
1954
  }
1955
1955
  function adoptResolverDataRoot(resolved, env = process.env) {
1956
1956
  const dataOverride = env.HASNA_DATA_HOME;
1957
1957
  if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
1958
1958
  return true;
1959
- return existsSync2(join2(resolved, STORE_MARKER));
1959
+ return existsSync3(join3(resolved, STORE_MARKER));
1960
1960
  }
1961
1961
  function getExplicitDataDir(env = process.env) {
1962
1962
  const dir = env.HASNA_HOOKS_DATA_DIR ?? env.HOOKS_DATA_DIR;
@@ -1967,7 +1967,7 @@ function getExplicitDataDir(env = process.env) {
1967
1967
  function getExactDataRoot(env = process.env) {
1968
1968
  const dir = env.HASNA_HOOKS_HOME?.trim() || env.HOOKS_HOME?.trim();
1969
1969
  if (dir)
1970
- return resolve(dir);
1970
+ return resolve2(dir);
1971
1971
  return;
1972
1972
  }
1973
1973
  function getEffectiveDataRoot(env = process.env) {
@@ -1978,13 +1978,13 @@ function getEffectiveDataRoot(env = process.env) {
1978
1978
  if (exact)
1979
1979
  return exact;
1980
1980
  const resolved = getResolverDataRoot(env);
1981
- return adoptResolverDataRoot(resolved, env) ? resolve(resolved) : getLegacyDataRoot(env);
1981
+ return adoptResolverDataRoot(resolved, env) ? resolve2(resolved) : getLegacyDataRoot(env);
1982
1982
  }
1983
1983
  function getReportedDbPath(env = process.env) {
1984
1984
  const explicit = getExplicitDbPath(env);
1985
1985
  if (explicit)
1986
1986
  return explicit;
1987
- return join2(getEffectiveDataRoot(env), "hooks.db");
1987
+ return join3(getEffectiveDataRoot(env), "hooks.db");
1988
1988
  }
1989
1989
  function getExplicitDbPath(env = process.env) {
1990
1990
  const db = env.HASNA_HOOKS_DB_PATH ?? env.HOOKS_DB_PATH;
@@ -1992,15 +1992,15 @@ function getExplicitDbPath(env = process.env) {
1992
1992
  return db.trim();
1993
1993
  return;
1994
1994
  }
1995
- var PATHS_RESOLVER_KIND_ENV, PATHS_RESOLVER_APP_SLUG_RE, STORE_MARKER = "hooks.db";
1995
+ var PATHS_RESOLVER_KIND_ENV2, PATHS_RESOLVER_APP_SLUG_RE2, STORE_MARKER = "hooks.db";
1996
1996
  var init_app_home = __esm(() => {
1997
- PATHS_RESOLVER_KIND_ENV = {
1997
+ PATHS_RESOLVER_KIND_ENV2 = {
1998
1998
  config: "HASNA_CONFIG_HOME",
1999
1999
  data: "HASNA_DATA_HOME",
2000
2000
  state: "HASNA_STATE_HOME",
2001
2001
  cache: "HASNA_CACHE_HOME"
2002
2002
  };
2003
- PATHS_RESOLVER_APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2003
+ PATHS_RESOLVER_APP_SLUG_RE2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2004
2004
  });
2005
2005
 
2006
2006
  // src/lib/registry.ts
@@ -2571,7 +2571,7 @@ var init_registry = __esm(() => {
2571
2571
  ];
2572
2572
  });
2573
2573
 
2574
- // ../hooks0102-standalone-lock/node_modules/cli-spinners/spinners.json
2574
+ // ../../node_modules/.bun/cli-spinners@2.9.2/node_modules/cli-spinners/spinners.json
2575
2575
  var require_spinners = __commonJS((exports, module) => {
2576
2576
  module.exports = {
2577
2577
  dots: {
@@ -4197,7 +4197,7 @@ var require_spinners = __commonJS((exports, module) => {
4197
4197
  };
4198
4198
  });
4199
4199
 
4200
- // ../hooks0102-standalone-lock/node_modules/cli-spinners/index.js
4200
+ // ../../node_modules/.bun/cli-spinners@2.9.2/node_modules/cli-spinners/index.js
4201
4201
  var require_cli_spinners = __commonJS((exports, module) => {
4202
4202
  var spinners = Object.assign({}, require_spinners());
4203
4203
  var spinnersList = Object.keys(spinners);
@@ -4212,18 +4212,18 @@ var require_cli_spinners = __commonJS((exports, module) => {
4212
4212
  });
4213
4213
 
4214
4214
  // src/config.ts
4215
- import { join as join3 } from "path";
4215
+ import { join as join5 } from "path";
4216
4216
  function getHooksDataDir() {
4217
4217
  return getEffectiveDataRoot();
4218
4218
  }
4219
4219
  function getCustomHooksDir() {
4220
- return join3(getHooksDataDir(), "hooks");
4220
+ return join5(getHooksDataDir(), "hooks");
4221
4221
  }
4222
4222
  function getLockPath() {
4223
4223
  const explicit = process.env.HASNA_HOOKS_LOCK_PATH ?? process.env.HOOKS_LOCK_PATH;
4224
4224
  if (explicit)
4225
4225
  return explicit;
4226
- return join3(getHooksDataDir(), "hooks.lock");
4226
+ return join5(getHooksDataDir(), "hooks.lock");
4227
4227
  }
4228
4228
  var init_config = __esm(() => {
4229
4229
  init_app_home();
@@ -4253,8 +4253,8 @@ __export(exports_manifest, {
4253
4253
  ScriptContainmentError: () => ScriptContainmentError,
4254
4254
  HOOK_NAME_RE: () => HOOK_NAME_RE
4255
4255
  });
4256
- import { existsSync as existsSync3, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync } from "fs";
4257
- import { basename, dirname, isAbsolute, join as join4, normalize, resolve as resolve2, sep } from "path";
4256
+ import { existsSync as existsSync5, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync } from "fs";
4257
+ import { basename, dirname, isAbsolute, join as join6, normalize, resolve as resolve3, sep } from "path";
4258
4258
  import { z } from "zod";
4259
4259
  function parseManifest(json) {
4260
4260
  const parsed = JSON.parse(json);
@@ -4270,8 +4270,8 @@ function isWithin(child, parent) {
4270
4270
  return child === parent || child.startsWith(parent + sep);
4271
4271
  }
4272
4272
  function assertContainedLexical(target, root, raw) {
4273
- const lexical = resolve2(target);
4274
- const rootLexical = resolve2(root);
4273
+ const lexical = resolve3(target);
4274
+ const rootLexical = resolve3(root);
4275
4275
  if (!isWithin(lexical, rootLexical)) {
4276
4276
  throw new ScriptContainmentError(target, root, raw);
4277
4277
  }
@@ -4280,14 +4280,14 @@ function assertContainedLexical(target, root, raw) {
4280
4280
  function realpathNearest(path) {
4281
4281
  const tail = [];
4282
4282
  let cur = path;
4283
- while (!existsSync3(cur)) {
4283
+ while (!existsSync5(cur)) {
4284
4284
  const parent = dirname(cur);
4285
4285
  if (parent === cur)
4286
4286
  break;
4287
4287
  tail.unshift(basename(cur));
4288
4288
  cur = parent;
4289
4289
  }
4290
- return join4(realpathSync(cur), ...tail);
4290
+ return join6(realpathSync(cur), ...tail);
4291
4291
  }
4292
4292
  function assertContainedReal(root, target, raw) {
4293
4293
  const rootReal = realpathSync(root);
@@ -4320,25 +4320,25 @@ function resolveScript(manifest, manifestDir) {
4320
4320
  if (isInlineScript(manifest))
4321
4321
  return { path: scriptRelFor(manifest), content: manifest.script };
4322
4322
  const rel = scriptRelFor(manifest);
4323
- const resolved = assertContained(join4(manifestDir, rel), manifestDir, manifest.script);
4324
- if (!existsSync3(resolved)) {
4323
+ const resolved = assertContained(join6(manifestDir, rel), manifestDir, manifest.script);
4324
+ if (!existsSync5(resolved)) {
4325
4325
  throw new Error(`manifest script file not found: ${resolved}`);
4326
4326
  }
4327
4327
  return { path: rel, content: readFileSync(resolved, "utf-8") };
4328
4328
  }
4329
4329
  function customHookDir(name) {
4330
- return join4(getCustomHooksDir(), shortManifestName(name));
4330
+ return join6(getCustomHooksDir(), shortManifestName(name));
4331
4331
  }
4332
4332
  function readCustomManifest(name) {
4333
4333
  const dir = customHookDir(name);
4334
- const manifestPath = join4(dir, "manifest.json");
4335
- if (!existsSync3(manifestPath))
4334
+ const manifestPath = join6(dir, "manifest.json");
4335
+ if (!existsSync5(manifestPath))
4336
4336
  return;
4337
4337
  try {
4338
4338
  const manifest = parseManifest(readFileSync(manifestPath, "utf-8"));
4339
4339
  const script = resolveScript(manifest, dir);
4340
4340
  const scriptIsInline = isInlineScript(manifest);
4341
- return { manifest, scriptPath: join4(dir, script.path), scriptContent: script.content, scriptIsInline };
4341
+ return { manifest, scriptPath: join6(dir, script.path), scriptContent: script.content, scriptIsInline };
4342
4342
  } catch (err) {
4343
4343
  if (err instanceof ScriptContainmentError)
4344
4344
  throw err;
@@ -4347,7 +4347,7 @@ function readCustomManifest(name) {
4347
4347
  }
4348
4348
  function listCustomHooks() {
4349
4349
  const dir = getCustomHooksDir();
4350
- if (!existsSync3(dir))
4350
+ if (!existsSync5(dir))
4351
4351
  return [];
4352
4352
  const results = [];
4353
4353
  for (const entry of readdirSafe(dir)) {
@@ -4362,7 +4362,7 @@ function writeCustomHook(name, manifest, scriptContent, scriptRelPath) {
4362
4362
  if (isAbsolute(scriptRelPath)) {
4363
4363
  throw new ScriptContainmentError(scriptRelPath, dir);
4364
4364
  }
4365
- const scriptPath = scriptRelPath.includes("/") ? join4(dir, scriptRelPath) : join4(dir, scriptRelPath);
4365
+ const scriptPath = scriptRelPath.includes("/") ? join6(dir, scriptRelPath) : join6(dir, scriptRelPath);
4366
4366
  assertContainedLexical(scriptPath, dir, scriptRelPath);
4367
4367
  mkdirSync(dir, { recursive: true });
4368
4368
  assertContainedReal(dir, scriptPath, scriptRelPath);
@@ -4370,7 +4370,7 @@ function writeCustomHook(name, manifest, scriptContent, scriptRelPath) {
4370
4370
  if (scriptDir !== dir)
4371
4371
  mkdirSync(scriptDir, { recursive: true });
4372
4372
  writeFileSync(scriptPath, scriptContent, "utf-8");
4373
- writeFileSync(join4(dir, "manifest.json"), JSON.stringify(manifest, null, 2) + `
4373
+ writeFileSync(join6(dir, "manifest.json"), JSON.stringify(manifest, null, 2) + `
4374
4374
  `, "utf-8");
4375
4375
  return { dir, scriptPath };
4376
4376
  }
@@ -4414,14 +4414,14 @@ __export(exports_resolve, {
4414
4414
  resolveHook: () => resolveHook,
4415
4415
  resolveBundledHooksDir: () => resolveBundledHooksDir
4416
4416
  });
4417
- import { dirname as dirname2, join as join5 } from "path";
4418
- import { existsSync as existsSync4 } from "fs";
4417
+ import { dirname as dirname2, join as join7 } from "path";
4418
+ import { existsSync as existsSync6 } from "fs";
4419
4419
  import { fileURLToPath } from "url";
4420
4420
  function resolveBundledHooksDir(moduleDir = dirname2(fileURLToPath(import.meta.url))) {
4421
- const sourceLayout = join5(moduleDir, "..", "..", "hooks");
4422
- if (existsSync4(join5(sourceLayout, "hook-gitguard")))
4421
+ const sourceLayout = join7(moduleDir, "..", "..", "hooks");
4422
+ if (existsSync6(join7(sourceLayout, "hook-gitguard")))
4423
4423
  return sourceLayout;
4424
- return join5(moduleDir, "..", "hooks");
4424
+ return join7(moduleDir, "..", "hooks");
4425
4425
  }
4426
4426
  function resolveHookDir(name) {
4427
4427
  const custom = readCustomManifest(name);
@@ -4432,11 +4432,11 @@ function resolveHookDir(name) {
4432
4432
  return;
4433
4433
  const short = shortManifestName(name);
4434
4434
  const bundledBase = resolveBundledHooksDir();
4435
- const direct = join5(bundledBase, short);
4436
- if (existsSync4(direct))
4435
+ const direct = join7(bundledBase, short);
4436
+ if (existsSync6(direct))
4437
4437
  return direct;
4438
- const prefixed = join5(bundledBase, `hook-${short}`);
4439
- return existsSync4(prefixed) ? prefixed : undefined;
4438
+ const prefixed = join7(bundledBase, `hook-${short}`);
4439
+ return existsSync6(prefixed) ? prefixed : undefined;
4440
4440
  }
4441
4441
  function resolveScriptPath(name) {
4442
4442
  const custom = readCustomManifest(name);
@@ -4445,8 +4445,8 @@ function resolveScriptPath(name) {
4445
4445
  const dir = resolveHookDir(name);
4446
4446
  if (!dir)
4447
4447
  return;
4448
- const script = join5(dir, "src", "hook.ts");
4449
- return existsSync4(script) ? script : undefined;
4448
+ const script = join7(dir, "src", "hook.ts");
4449
+ return existsSync6(script) ? script : undefined;
4450
4450
  }
4451
4451
  function resolveHookMeta(name) {
4452
4452
  const custom = readCustomManifest(name);
@@ -4503,8 +4503,8 @@ var init_resolve = __esm(() => {
4503
4503
 
4504
4504
  // src/lib/native-safety.ts
4505
4505
  import { createHash } from "crypto";
4506
- import { closeSync, constants, existsSync as existsSync5, fstatSync, lstatSync, openSync, readFileSync as readFileSync2, realpathSync as realpathSync2 } from "fs";
4507
- import { dirname as dirname3, isAbsolute as isAbsolute2, join as join6 } from "path";
4506
+ import { closeSync, constants, existsSync as existsSync7, fstatSync, lstatSync, openSync, readFileSync as readFileSync2, realpathSync as realpathSync2 } from "fs";
4507
+ import { dirname as dirname3, isAbsolute as isAbsolute2, join as join8 } from "path";
4508
4508
  import { homedir as homedir3 } from "os";
4509
4509
  function isNativeSafetyName(name) {
4510
4510
  return name === "trash-guard" || name === "workspace-repos-guard";
@@ -4558,12 +4558,12 @@ function pinEligibleFile(file, maximum, executable = false) {
4558
4558
  function installedNativeSafetyCommand(name) {
4559
4559
  const home = realpathSync2(homedir3());
4560
4560
  const runtime = realpathSync2(process.execPath);
4561
- const candidates = [join6(import.meta.dir, "../../bin/native-safety-entry.js"), join6(import.meta.dir, "../bin/native-safety-entry.js"), join6(import.meta.dir, "native-safety-entry.js")];
4562
- const worker = candidates.find(existsSync5);
4561
+ const candidates = [join8(import.meta.dir, "../../bin/native-safety-entry.js"), join8(import.meta.dir, "../bin/native-safety-entry.js"), join8(import.meta.dir, "native-safety-entry.js")];
4562
+ const worker = candidates.find(existsSync7);
4563
4563
  if (!worker)
4564
4564
  throw new Error("Bundled native safety runner is missing; build or reinstall @hasna/hooks before installing its guards.");
4565
4565
  const canonicalWorker = realpathSync2(worker);
4566
- return buildNativeSafetyCommand({ name, runtime, runtimeSHA256: pinEligibleFile(runtime, 200000000, true), worker: canonicalWorker, workerSHA256: pinEligibleFile(canonicalWorker, 256000), home, path: `${dirname3(runtime)}:${join6(home, ".bun/bin")}:/usr/local/bin:/usr/bin:/bin` });
4566
+ return buildNativeSafetyCommand({ name, runtime, runtimeSHA256: pinEligibleFile(runtime, 200000000, true), worker: canonicalWorker, workerSHA256: pinEligibleFile(canonicalWorker, 256000), home, path: `${dirname3(runtime)}:${join8(home, ".bun/bin")}:/usr/local/bin:/usr/bin:/bin` });
4567
4567
  }
4568
4568
  var supervisorSource, quote = (value) => "'" + value.replaceAll("'", "'\\''") + "'", program2, shell, prefix;
4569
4569
  var init_native_safety = __esm(() => {
@@ -5010,8 +5010,8 @@ var init_migrations = __esm(() => {
5010
5010
  });
5011
5011
 
5012
5012
  // src/db/legacy-import.ts
5013
- import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
5014
- import { join as join7 } from "path";
5013
+ import { existsSync as existsSync8, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
5014
+ import { join as join9 } from "path";
5015
5015
  import { homedir as homedir4 } from "os";
5016
5016
  function ensureMetaTable(db) {
5017
5017
  db.exec(`
@@ -5091,20 +5091,20 @@ function runLegacyImport(db, homeDir = homedir4()) {
5091
5091
  if (isAlreadyDone(db))
5092
5092
  return;
5093
5093
  let total = 0;
5094
- const claudeProjectsDir = join7(homeDir, ".claude", "projects");
5095
- if (existsSync6(claudeProjectsDir)) {
5094
+ const claudeProjectsDir = join9(homeDir, ".claude", "projects");
5095
+ if (existsSync8(claudeProjectsDir)) {
5096
5096
  try {
5097
5097
  const projectDirs = readdirSync2(claudeProjectsDir);
5098
5098
  for (const dir of projectDirs) {
5099
- const projectDir = join7(claudeProjectsDir, dir);
5099
+ const projectDir = join9(claudeProjectsDir, dir);
5100
5100
  try {
5101
5101
  const files = readdirSync2(projectDir);
5102
5102
  for (const file of files) {
5103
5103
  if (file.match(/^session-log-\d{4}-\d{2}-\d{2}\.jsonl$/)) {
5104
- total += importJsonlFile(db, join7(projectDir, file));
5104
+ total += importJsonlFile(db, join9(projectDir, file));
5105
5105
  }
5106
5106
  if (file === "errors.log") {
5107
- total += importErrorsLog(db, join7(projectDir, file));
5107
+ total += importErrorsLog(db, join9(projectDir, file));
5108
5108
  }
5109
5109
  }
5110
5110
  } catch {}
@@ -5151,8 +5151,8 @@ __export(exports_db, {
5151
5151
  allowLocalStore: () => allowLocalStore
5152
5152
  });
5153
5153
  import { Database } from "bun:sqlite";
5154
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, cpSync } from "fs";
5155
- import { join as join8 } from "path";
5154
+ import { existsSync as existsSync9, mkdirSync as mkdirSync2, cpSync } from "fs";
5155
+ import { join as join10 } from "path";
5156
5156
  function refuseLocalStore(message) {
5157
5157
  localStoreRefusal = message;
5158
5158
  }
@@ -5167,8 +5167,8 @@ function localStoreRefusalMessage() {
5167
5167
  }
5168
5168
  function resolveDataDir() {
5169
5169
  const effective = getEffectiveDataRoot();
5170
- const oldDir = join8(getHomeDir(), ".hooks");
5171
- if (!existsSync7(effective) && existsSync7(oldDir)) {
5170
+ const oldDir = join10(getHomeDir(), ".hooks");
5171
+ if (!existsSync9(effective) && existsSync9(oldDir)) {
5172
5172
  mkdirSync2(effective, { recursive: true });
5173
5173
  cpSync(oldDir, effective, { recursive: true });
5174
5174
  }
@@ -5178,12 +5178,12 @@ function getDbPath() {
5178
5178
  const explicitDb = process.env.HASNA_HOOKS_DB_PATH ?? process.env.HOOKS_DB_PATH;
5179
5179
  if (explicitDb)
5180
5180
  return explicitDb;
5181
- const dataDir2 = resolveDataDir();
5182
- return join8(dataDir2, "hooks.db");
5181
+ const dataDir3 = resolveDataDir();
5182
+ return join10(dataDir3, "hooks.db");
5183
5183
  }
5184
5184
  function ensureDir(dbPath) {
5185
5185
  const dir = dbPath.substring(0, dbPath.lastIndexOf("/"));
5186
- if (dir && !existsSync7(dir)) {
5186
+ if (dir && !existsSync9(dir)) {
5187
5187
  mkdirSync2(dir, { recursive: true });
5188
5188
  }
5189
5189
  }
@@ -5193,7 +5193,7 @@ function getDb() {
5193
5193
  if (instance)
5194
5194
  return instance;
5195
5195
  const dbPath = getDbPath();
5196
- const isNew = dbPath === ":memory:" || !existsSync7(dbPath);
5196
+ const isNew = dbPath === ":memory:" || !existsSync9(dbPath);
5197
5197
  ensureDir(dbPath);
5198
5198
  instance = new Database(dbPath);
5199
5199
  instance.exec("PRAGMA busy_timeout=5000");
@@ -5256,7 +5256,7 @@ __export(exports_store, {
5256
5256
  LockFileError: () => LockFileError
5257
5257
  });
5258
5258
  import { createHash as createHash2 } from "crypto";
5259
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync } from "fs";
5259
+ import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync } from "fs";
5260
5260
  import { readFile as readFile2 } from "fs/promises";
5261
5261
  import { randomBytes } from "crypto";
5262
5262
  function sha256Of(input) {
@@ -5321,7 +5321,7 @@ function assertLockShape(parsed, path) {
5321
5321
  }
5322
5322
  function readLock() {
5323
5323
  const path = getLockPath();
5324
- if (!existsSync8(path))
5324
+ if (!existsSync10(path))
5325
5325
  return { hooks: {} };
5326
5326
  let raw;
5327
5327
  try {
@@ -5455,7 +5455,7 @@ var init_store = __esm(() => {
5455
5455
  });
5456
5456
 
5457
5457
  // src/lib/codex-settings.ts
5458
- import { closeSync as closeSync2, existsSync as existsSync9, lstatSync as lstatSync2, mkdirSync as mkdirSync4, openSync as openSync2, readFileSync as readFileSync5, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
5458
+ import { closeSync as closeSync2, existsSync as existsSync11, lstatSync as lstatSync2, mkdirSync as mkdirSync4, openSync as openSync2, readFileSync as readFileSync5, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
5459
5459
  import { dirname as dirname4 } from "path";
5460
5460
  import { randomUUID as randomUUID3 } from "crypto";
5461
5461
  function current(path) {
@@ -5515,7 +5515,7 @@ function writeCodexSettings(path, settings) {
5515
5515
  renameSync2(temp, path);
5516
5516
  snapshots.set(settings, { path, raw: next });
5517
5517
  } finally {
5518
- if (existsSync9(temp))
5518
+ if (existsSync11(temp))
5519
5519
  unlinkSync(temp);
5520
5520
  closeSync2(fd);
5521
5521
  unlinkSync(lock);
@@ -5526,12 +5526,12 @@ var init_codex_settings = __esm(() => {
5526
5526
  snapshots = new WeakMap;
5527
5527
  });
5528
5528
 
5529
- // ../hooks0102-standalone-lock/node_modules/@hasna/skills/dist/index.js
5530
- import { existsSync as existsSync10 } from "fs";
5529
+ // ../../node_modules/.bun/@hasna+skills@0.9.14+a00d3064559565bb/node_modules/@hasna/skills/dist/index.js
5530
+ import { existsSync as existsSync12 } from "fs";
5531
5531
  import { homedir as homedir5 } from "os";
5532
- import { join as join9, resolve as resolve3 } from "path";
5533
- import { homedir as pathsResolverHomedir2 } from "os";
5534
- import { join as pathsResolverJoin2 } from "path";
5532
+ import { join as join11, resolve as resolve4 } from "path";
5533
+ import { homedir as pathsResolverHomedir3 } from "os";
5534
+ import { join as pathsResolverJoin3 } from "path";
5535
5535
  import { createHash as createHash3 } from "crypto";
5536
5536
  import { existsSync as existsSync52, readdirSync as readdirSync3, readFileSync as readFileSync42, statSync as statSync3 } from "fs";
5537
5537
  import { join as join52, sep as sep2 } from "path";
@@ -5543,7 +5543,7 @@ import { dirname as dirname32, isAbsolute as isAbsolute3, join as join72, resolv
5543
5543
  import { lstatSync as lstatSync3, readFileSync as readFileSync6, opendirSync } from "fs";
5544
5544
  import { createHash as createHash22 } from "crypto";
5545
5545
  import { lstatSync as lstatSync4, opendirSync as opendirSync2 } from "fs";
5546
- import { dirname as dirname42, isAbsolute as isAbsolute4, join as join82, resolve as resolve4 } from "path";
5546
+ import { dirname as dirname42, isAbsolute as isAbsolute4, join as join82, resolve as resolve42 } from "path";
5547
5547
  import { createHash as createHash32 } from "crypto";
5548
5548
  import { closeSync as closeSync3, constants as constants2, fstatSync as fstatSync2, lstatSync as lstatSync5, openSync as openSync3, readSync } from "fs";
5549
5549
  import { dirname as dirname5, isAbsolute as isAbsolute5, resolve as resolve5 } from "path";
@@ -5553,7 +5553,7 @@ import { dirname as dirname6, isAbsolute as isAbsolute6, join as join92, parse,
5553
5553
  import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync17, openSync as openSync12, opendirSync as opendirSync5, readSync as readSync8 } from "fs";
5554
5554
  import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute12, join as join25, resolve as resolve12 } from "path";
5555
5555
  import { isAbsolute as isAbsolute11, join as join23, resolve as resolve11 } from "path";
5556
- import { createRequire } from "module";
5556
+ import { createRequire as createRequire2 } from "module";
5557
5557
  import { createHash as createHash10, randomUUID as randomUUID22 } from "crypto";
5558
5558
  import { existsSync as existsSync82, lstatSync as lstatSync14, statSync as statSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync11, readdirSync as readdirSync7, opendirSync as opendirSync3, readlinkSync as readlinkSync2, realpathSync as realpathSync3, renameSync as renameSync22, rmdirSync as rmdirSync2, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, chmodSync, openSync as openSync10, closeSync as closeSync10, fsyncSync as fsyncSync2, fstatSync as fstatSync10, readSync as readSync6, constants as constants7, linkSync } from "fs";
5559
5559
  import { dirname as dirname10, join as join16, resolve as resolve9, relative as relative4, isAbsolute as isAbsolute9, sep as sep4 } from "path";
@@ -5581,11 +5581,11 @@ import { createHash as createHash20 } from "crypto";
5581
5581
  function __exportSetter2(name, newValue) {
5582
5582
  this[name] = __returnValue2.bind(null, newValue);
5583
5583
  }
5584
- function pathsResolverAssertApp2(app) {
5584
+ function pathsResolverAssertApp3(app) {
5585
5585
  if (typeof app !== "string" || app.length === 0) {
5586
5586
  throw new TypeError("paths: app must be a non-empty string");
5587
5587
  }
5588
- if (!PATHS_RESOLVER_APP_SLUG_RE2.test(app)) {
5588
+ if (!PATHS_RESOLVER_APP_SLUG_RE3.test(app)) {
5589
5589
  throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
5590
5590
  }
5591
5591
  }
@@ -5594,35 +5594,35 @@ function pathsResolverDataBaseDir(options) {
5594
5594
  const override = env[PATHS_RESOLVER_DATA_ENV];
5595
5595
  if (typeof override === "string" && override.length > 0)
5596
5596
  return override;
5597
- const home = options.home ?? pathsResolverHomedir2();
5597
+ const home = options.home ?? pathsResolverHomedir3();
5598
5598
  const platform = options.platform ?? process.platform;
5599
- return platform === "darwin" ? pathsResolverJoin2(home, "Library", "Application Support", "Hasna") : pathsResolverJoin2(home, ".local", "share", "hasna");
5599
+ return platform === "darwin" ? pathsResolverJoin3(home, "Library", "Application Support", "Hasna") : pathsResolverJoin3(home, ".local", "share", "hasna");
5600
5600
  }
5601
- function dataDir2(options) {
5602
- pathsResolverAssertApp2(options.app);
5603
- const appSegment = options.internal === true ? pathsResolverJoin2("internal", options.app) : options.app;
5604
- return pathsResolverJoin2(pathsResolverDataBaseDir(options), appSegment);
5601
+ function dataDir3(options) {
5602
+ pathsResolverAssertApp3(options.app);
5603
+ const appSegment = options.internal === true ? pathsResolverJoin3("internal", options.app) : options.app;
5604
+ return pathsResolverJoin3(pathsResolverDataBaseDir(options), appSegment);
5605
5605
  }
5606
- function effectiveHome() {
5606
+ function effectiveHome2() {
5607
5607
  return process.env["HOME"] || process.env["USERPROFILE"] || homedir5() || "/tmp";
5608
5608
  }
5609
5609
  function legacyDataRoot() {
5610
- return join9(effectiveHome(), ".hasna", "skills");
5610
+ return join11(effectiveHome2(), ".hasna", "skills");
5611
5611
  }
5612
- function resolverDataRoot(home = effectiveHome(), env) {
5613
- return dataDir2({ app: "skills", home, env });
5612
+ function resolverDataRoot(home = effectiveHome2(), env) {
5613
+ return dataDir3({ app: "skills", home, env });
5614
5614
  }
5615
5615
  function adoptResolverDataRoot2(resolved, env = process.env) {
5616
5616
  const dataOverride = env.HASNA_DATA_HOME;
5617
5617
  if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
5618
5618
  return true;
5619
- return existsSync10(join9(resolved, DEFAULT_SQLITE_FILENAME)) || existsSync10(join9(resolved, GLOBAL_CONFIG_FILENAME));
5619
+ return existsSync12(join11(resolved, DEFAULT_SQLITE_FILENAME)) || existsSync12(join11(resolved, GLOBAL_CONFIG_FILENAME));
5620
5620
  }
5621
5621
  function exactDataRoot() {
5622
5622
  for (const key of [DATA_DIR_ENV, HASNA_SKILLS_HOME_ENV, SKILLS_HOME_ENV]) {
5623
5623
  const dir = process.env[key]?.trim();
5624
5624
  if (dir)
5625
- return resolve3(dir);
5625
+ return resolve4(dir);
5626
5626
  }
5627
5627
  return;
5628
5628
  }
@@ -5631,7 +5631,7 @@ function getDataRoot() {
5631
5631
  if (exact)
5632
5632
  return exact;
5633
5633
  const resolved = resolverDataRoot();
5634
- return adoptResolverDataRoot2(resolved) ? resolve3(resolved) : resolve3(legacyDataRoot());
5634
+ return adoptResolverDataRoot2(resolved) ? resolve4(resolved) : resolve4(legacyDataRoot());
5635
5635
  }
5636
5636
  function getDataDirReadOnly() {
5637
5637
  return getDataRoot();
@@ -6253,7 +6253,7 @@ function need(value, message) {
6253
6253
  throw new Error(message);
6254
6254
  }
6255
6255
  function safe(path) {
6256
- need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute4(path) && resolve4(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
6256
+ need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute4(path) && resolve42(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
6257
6257
  for (let cursor = path;; cursor = dirname42(cursor)) {
6258
6258
  need(!lstatSync4(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
6259
6259
  if (dirname42(cursor) === cursor)
@@ -15487,7 +15487,7 @@ var __defProp2, __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {}
15487
15487
  configurable: true,
15488
15488
  set: __exportSetter2.bind(all, name)
15489
15489
  });
15490
- }, __require2, require_identity, require_visit, require_directives, require_anchors, require_applyReviver, require_toJS, require_Node, require_Alias, require_Scalar, require_createNode, require_Collection, require_stringifyComment, require_foldFlowLines, require_stringifyString, require_stringify, require_stringifyPair, require_log, require_merge, require_addPairToJSMap, require_Pair, require_stringifyCollection, require_YAMLMap, require_map, require_YAMLSeq, require_seq, require_string, require_null, require_bool, require_stringifyNumber, require_float, require_int, require_schema, require_schema2, require_binary, require_pairs, require_omap, require_bool2, require_float2, require_int2, require_set, require_timestamp, require_schema3, require_tags, require_Schema, require_stringifyDocument, require_Document, require_errors, require_resolve_props, require_util_contains_newline, require_util_flow_indent_check, require_util_map_includes, require_resolve_block_map, require_resolve_block_seq, require_resolve_end, require_resolve_flow_collection, require_compose_collection, require_resolve_block_scalar, require_resolve_flow_scalar, require_compose_scalar, require_util_empty_scalar_position, require_compose_node, require_compose_doc, require_composer, require_cst_scalar, require_cst_stringify, require_cst_visit, require_cst, require_lexer, require_line_counter, require_parser, require_public_api, RETIRED_CONFIG_KEY_REASONS, PATHS_RESOLVER_DATA_ENV = "HASNA_DATA_HOME", PATHS_RESOLVER_APP_SLUG_RE2, DATA_DIR_ENV = "HASNA_SKILLS_DIR", HASNA_SKILLS_HOME_ENV = "HASNA_SKILLS_HOME", SKILLS_HOME_ENV = "SKILLS_HOME", DEFAULT_SQLITE_FILENAME = "server.db", GLOBAL_CONFIG_FILENAME = "config.json", SKILLS, HOSTED_RUNTIMES, HOSTED_SOURCES, HOSTED_METADATA_SET_EMPTY_ERROR, SLUG = "[^,{}/]+", BRACE_SOURCE_EXCLUSION, SINGLE_SOURCE_EXCLUSION, RESERVED_SKILL_ENTRIES, KNOWN_TOP_LEVEL_ENTRIES, VALID_PROVENANCE_SOURCES, CONTENT_HASH_ALGORITHM = "sha256", HASH_EXCLUDE_DIRS, HASH_COVERAGE, CONTENT_HASH_LIMITS, typedArrayPrototype, byteLengthOf, bufferOf, PORTABLE_SKILL_STANDARD = "hasna.skill.v1", SKILL_RUNTIMES, SKILL_SANDBOX_MODES, SKILL_SYSTEM_DEPS_ALLOWLIST, SEMVER_PATTERN2 = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", CONTENT_HASH_PATTERN = "^[a-f0-9]{64}$", ENV_REFERENCE_PATTERN = "^[A-Z0-9_]+$", MAX_RUNTIME_TIMEOUT_SECONDS = 900, ANY_SEGMENT_COPY_EXCLUDES, FIRST_SEGMENT_COPY_EXCLUDES, NATIVE_SKILL_ROOTS, INTEGRATION_AGENTS, AGENT_ADAPTERS, AGENT_POLICY_LIMITS, composer, Document, Schema, errors, Alias, identity, Pair, Scalar, YAMLMap, YAMLSeq, cst, lexer, lineCounter, parser, publicApi, visit, $Composer, $Document, $Schema, $YAMLError, $YAMLParseError, $YAMLWarning, $Alias, $isAlias, $isCollection, $isDocument, $isMap, $isNode, $isPair, $isScalar, $isSeq, $Pair, $Scalar, $YAMLMap, $YAMLSeq, $Lexer, $LineCounter, $Parser, $parse, $parseAllDocuments, $parseDocument, $stringify, $visit, $visitAsync, HERMES_OPT_OUT = ".no-bundled-skills", package_default, MAX_PACKAGE_BYTES, MAX_CREDENTIAL_FILE_BYTES, INSPECT_CUSTOM, CREDENTIAL_SEAL, AMBIENT_ENVIRONMENT, requireSecretsSdk, IDEMPOTENT_METHODS, AUTHORITY_OVERRIDE_HEADERS, SKILLS_APP = "skills", ENV_KEYS, SKILLS_API_URL_ENV_KEYS, SKILLS_API_KEY_ENV_KEYS, SKILLS_API_URL_ENV, SKILLS_API_KEY_ENV, SkillsFleetCredentialError, MAX_REMOTE_FILE_BYTES, MAX_PROFILE_SELECTIONS = 4096, MAX_PROFILE_DOCUMENT_BYTES, MAX_SKILL_SESSION_ID_CHARS = 256, PROFILE_SESSION_ENVELOPE_BYTES, MAX_RESOLVED_PROFILE_BYTES, BLOCK = 512, ANY_SEGMENT_EXCLUDES, ROOT_EXCLUDES, TOOL_SIDECAR_FILENAMES, CREDENTIAL_FILENAMES, ENV_TEMPLATE_NAMES, NON_DOTENV_EXTENSIONS, SKILL_BUNDLE_INSPECTION_LIMITS, SkillBundleInspectionError, SKILL_VERSION_PATTERN, SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, CLI_BRIDGE_NAME = "skills-cli", CLI_BRIDGE_VERSION = 1, markdown = `---
15490
+ }, __require2, require_identity, require_visit, require_directives, require_anchors, require_applyReviver, require_toJS, require_Node, require_Alias, require_Scalar, require_createNode, require_Collection, require_stringifyComment, require_foldFlowLines, require_stringifyString, require_stringify, require_stringifyPair, require_log, require_merge, require_addPairToJSMap, require_Pair, require_stringifyCollection, require_YAMLMap, require_map, require_YAMLSeq, require_seq, require_string, require_null, require_bool, require_stringifyNumber, require_float, require_int, require_schema, require_schema2, require_binary, require_pairs, require_omap, require_bool2, require_float2, require_int2, require_set, require_timestamp, require_schema3, require_tags, require_Schema, require_stringifyDocument, require_Document, require_errors, require_resolve_props, require_util_contains_newline, require_util_flow_indent_check, require_util_map_includes, require_resolve_block_map, require_resolve_block_seq, require_resolve_end, require_resolve_flow_collection, require_compose_collection, require_resolve_block_scalar, require_resolve_flow_scalar, require_compose_scalar, require_util_empty_scalar_position, require_compose_node, require_compose_doc, require_composer, require_cst_scalar, require_cst_stringify, require_cst_visit, require_cst, require_lexer, require_line_counter, require_parser, require_public_api, RETIRED_CONFIG_KEY_REASONS, PATHS_RESOLVER_DATA_ENV = "HASNA_DATA_HOME", PATHS_RESOLVER_APP_SLUG_RE3, DATA_DIR_ENV = "HASNA_SKILLS_DIR", HASNA_SKILLS_HOME_ENV = "HASNA_SKILLS_HOME", SKILLS_HOME_ENV = "SKILLS_HOME", DEFAULT_SQLITE_FILENAME = "server.db", GLOBAL_CONFIG_FILENAME = "config.json", SKILLS, HOSTED_RUNTIMES, HOSTED_SOURCES, HOSTED_METADATA_SET_EMPTY_ERROR, SLUG = "[^,{}/]+", BRACE_SOURCE_EXCLUSION, SINGLE_SOURCE_EXCLUSION, RESERVED_SKILL_ENTRIES, KNOWN_TOP_LEVEL_ENTRIES, VALID_PROVENANCE_SOURCES, CONTENT_HASH_ALGORITHM = "sha256", HASH_EXCLUDE_DIRS, HASH_COVERAGE, CONTENT_HASH_LIMITS, typedArrayPrototype, byteLengthOf, bufferOf, PORTABLE_SKILL_STANDARD = "hasna.skill.v1", SKILL_RUNTIMES, SKILL_SANDBOX_MODES, SKILL_SYSTEM_DEPS_ALLOWLIST, SEMVER_PATTERN2 = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", CONTENT_HASH_PATTERN = "^[a-f0-9]{64}$", ENV_REFERENCE_PATTERN = "^[A-Z0-9_]+$", MAX_RUNTIME_TIMEOUT_SECONDS = 900, ANY_SEGMENT_COPY_EXCLUDES, FIRST_SEGMENT_COPY_EXCLUDES, NATIVE_SKILL_ROOTS, INTEGRATION_AGENTS, AGENT_ADAPTERS, AGENT_POLICY_LIMITS, composer, Document, Schema, errors, Alias, identity, Pair, Scalar, YAMLMap, YAMLSeq, cst, lexer, lineCounter, parser, publicApi, visit, $Composer, $Document, $Schema, $YAMLError, $YAMLParseError, $YAMLWarning, $Alias, $isAlias, $isCollection, $isDocument, $isMap, $isNode, $isPair, $isScalar, $isSeq, $Pair, $Scalar, $YAMLMap, $YAMLSeq, $Lexer, $LineCounter, $Parser, $parse, $parseAllDocuments, $parseDocument, $stringify, $visit, $visitAsync, HERMES_OPT_OUT = ".no-bundled-skills", package_default, MAX_PACKAGE_BYTES2, MAX_CREDENTIAL_FILE_BYTES2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, AMBIENT_ENVIRONMENT2, requireSecretsSdk2, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, SKILLS_APP = "skills", ENV_KEYS, SKILLS_API_URL_ENV_KEYS, SKILLS_API_KEY_ENV_KEYS, SKILLS_API_URL_ENV, SKILLS_API_KEY_ENV, SkillsFleetCredentialError, MAX_REMOTE_FILE_BYTES, MAX_PROFILE_SELECTIONS = 4096, MAX_PROFILE_DOCUMENT_BYTES, MAX_SKILL_SESSION_ID_CHARS = 256, PROFILE_SESSION_ENVELOPE_BYTES, MAX_RESOLVED_PROFILE_BYTES, BLOCK = 512, ANY_SEGMENT_EXCLUDES, ROOT_EXCLUDES, TOOL_SIDECAR_FILENAMES, CREDENTIAL_FILENAMES, ENV_TEMPLATE_NAMES, NON_DOTENV_EXTENSIONS, SKILL_BUNDLE_INSPECTION_LIMITS, SkillBundleInspectionError, SKILL_VERSION_PATTERN, SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, CLI_BRIDGE_NAME = "skills-cli", CLI_BRIDGE_VERSION = 1, markdown = `---
15491
15491
  name: skills-cli
15492
15492
  description: Discover, load, author, and run versioned skills through the Skills CLI when a task needs reusable instructions or an executable skill.
15493
15493
  ---
@@ -29705,7 +29705,7 @@ ${end.comment}` : end.comment;
29705
29705
  mode: "Deployment modes were removed: a Skills client either resolves a credential " + "or it does not, and that is the whole of it.",
29706
29706
  apiUrl: "The service address is no longer kept in this app's config file: it is read from " + "HASNA_SKILLS_API_URL, then the macOS Keychain item hasna.credentials.skills.api-url, " + "then ~/.hasna/skills/config/credentials, then the fleet gateway."
29707
29707
  };
29708
- PATHS_RESOLVER_APP_SLUG_RE2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
29708
+ PATHS_RESOLVER_APP_SLUG_RE3 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
29709
29709
  SKILLS = [];
29710
29710
  HOSTED_RUNTIMES = new Set(["hosted"]);
29711
29711
  HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
@@ -30032,14 +30032,14 @@ ${end.comment}` : end.comment;
30032
30032
  url: "https://github.com/hasna/apps/issues"
30033
30033
  }
30034
30034
  };
30035
- MAX_PACKAGE_BYTES = 1024 * 1024;
30036
- MAX_CREDENTIAL_FILE_BYTES = 64 * 1024;
30037
- INSPECT_CUSTOM = Symbol.for("nodejs.util.inspect.custom");
30038
- CREDENTIAL_SEAL = Symbol.for("hasna:contracts:sealedCredential");
30039
- AMBIENT_ENVIRONMENT = Symbol.for("hasna:contracts:ambientClientEnvironment");
30040
- requireSecretsSdk = createRequire(import.meta.url);
30041
- IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
30042
- AUTHORITY_OVERRIDE_HEADERS = new Set([
30035
+ MAX_PACKAGE_BYTES2 = 1024 * 1024;
30036
+ MAX_CREDENTIAL_FILE_BYTES2 = 64 * 1024;
30037
+ INSPECT_CUSTOM2 = Symbol.for("nodejs.util.inspect.custom");
30038
+ CREDENTIAL_SEAL2 = Symbol.for("hasna:contracts:sealedCredential");
30039
+ AMBIENT_ENVIRONMENT2 = Symbol.for("hasna:contracts:ambientClientEnvironment");
30040
+ requireSecretsSdk2 = createRequire2(import.meta.url);
30041
+ IDEMPOTENT_METHODS2 = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
30042
+ AUTHORITY_OVERRIDE_HEADERS2 = new Set([
30043
30043
  "host",
30044
30044
  ":authority",
30045
30045
  "forwarded",
@@ -36495,8 +36495,8 @@ __export(exports_installer, {
36495
36495
  detectRewriteConflict: () => detectRewriteConflict,
36496
36496
  buildCodewithTomlFragment: () => buildCodewithTomlFragment
36497
36497
  });
36498
- import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync7, readdirSync as readdirSync4, realpathSync as realpathSync5, rmdirSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "fs";
36499
- import { join as join10, dirname as dirname7, basename as basename3, resolve as resolve7 } from "path";
36498
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync7, readdirSync as readdirSync4, realpathSync as realpathSync5, rmdirSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "fs";
36499
+ import { join as join12, dirname as dirname7, basename as basename3, resolve as resolve7 } from "path";
36500
36500
  import { homedir as homedir6 } from "os";
36501
36501
  import { fileURLToPath as fileURLToPath2 } from "url";
36502
36502
  function normalizeHookName(name) {
@@ -36544,28 +36544,28 @@ function getSettingsPath(scope = "global", target = "claude", codewithConfigPath
36544
36544
  return globalOverride;
36545
36545
  const dir = getTargetSettingsDir(target);
36546
36546
  if (target === "codex")
36547
- return join10(scope === "project" ? process.cwd() : homedir6(), dir, "hooks.json");
36547
+ return join12(scope === "project" ? process.cwd() : homedir6(), dir, "hooks.json");
36548
36548
  if (scope === "project") {
36549
- return target === "codewith" ? join10(process.cwd(), dir, "config.toml") : join10(process.cwd(), dir, "settings.json");
36549
+ return target === "codewith" ? join12(process.cwd(), dir, "config.toml") : join12(process.cwd(), dir, "settings.json");
36550
36550
  }
36551
- return target === "codewith" ? join10(homedir6(), dir, "config.toml") : join10(homedir6(), dir, "settings.json");
36551
+ return target === "codewith" ? join12(homedir6(), dir, "config.toml") : join12(homedir6(), dir, "settings.json");
36552
36552
  }
36553
36553
  function getHookPath(name) {
36554
36554
  const shortName = shortHookName(name);
36555
36555
  const resolved = resolveHookDir(shortName);
36556
36556
  if (resolved)
36557
36557
  return resolved;
36558
- return join10(HOOKS_DIR, normalizeHookName(shortName));
36558
+ return join12(HOOKS_DIR, normalizeHookName(shortName));
36559
36559
  }
36560
36560
  function hookExists(name) {
36561
- return existsSync11(getHookPath(name));
36561
+ return existsSync13(getHookPath(name));
36562
36562
  }
36563
36563
  function readSettings2(scope = "global", target = "claude") {
36564
36564
  const path = getSettingsPath(scope, target);
36565
36565
  if (target === "codex")
36566
36566
  return readCodexSettings(path);
36567
36567
  try {
36568
- if (existsSync11(path)) {
36568
+ if (existsSync13(path)) {
36569
36569
  const text3 = readFileSync7(path, "utf-8"), value = JSON.parse(text3);
36570
36570
  settingsPreimages.set(value, { path, text: text3 });
36571
36571
  return value;
@@ -36574,24 +36574,24 @@ function readSettings2(scope = "global", target = "claude") {
36574
36574
  console.warn(`[hooks] Failed to read settings at ${path}: ${error61 instanceof Error ? error61.message : String(error61)}`);
36575
36575
  }
36576
36576
  const empty = {};
36577
- if (!existsSync11(path))
36577
+ if (!existsSync13(path))
36578
36578
  settingsPreimages.set(empty, { path, text: null });
36579
36579
  return empty;
36580
36580
  }
36581
36581
  function settingsIdentity(path) {
36582
- if (existsSync11(path))
36582
+ if (existsSync13(path))
36583
36583
  return realpathSync5(path);
36584
- return existsSync11(dirname7(path)) ? join10(realpathSync5(dirname7(path)), basename3(path)) : resolve7(path);
36584
+ return existsSync13(dirname7(path)) ? join12(realpathSync5(dirname7(path)), basename3(path)) : resolve7(path);
36585
36585
  }
36586
36586
  function writeSettings(settings, scope = "global", target = "claude") {
36587
36587
  const path = getSettingsPath(scope, target);
36588
36588
  if (target === "codex")
36589
36589
  return writeCodexSettings(path, settings);
36590
- if (target === "claude" && settingsIdentity(path) === settingsIdentity(join10(homedir6(), ".claude/settings.json"))) {
36590
+ if (target === "claude" && settingsIdentity(path) === settingsIdentity(join12(homedir6(), ".claude/settings.json"))) {
36591
36591
  const before = settingsPreimages.get(settings);
36592
36592
  if (!before || before.path !== path)
36593
36593
  throw new Error("Claude settings require a valid captured preimage before installation.");
36594
- const current2 = existsSync11(path) ? readFileSync7(path, "utf8") : null;
36594
+ const current2 = existsSync13(path) ? readFileSync7(path, "utf8") : null;
36595
36595
  if (current2 !== before.text)
36596
36596
  throw new Error("Claude settings changed during installation; no settings were written.");
36597
36597
  if (coordinateClaudeSettings(before.text, JSON.stringify(settings, null, 2) + `
@@ -36599,7 +36599,7 @@ function writeSettings(settings, scope = "global", target = "claude") {
36599
36599
  return;
36600
36600
  }
36601
36601
  const dir = dirname7(path);
36602
- if (!existsSync11(dir)) {
36602
+ if (!existsSync13(dir)) {
36603
36603
  mkdirSync6(dir, { recursive: true });
36604
36604
  }
36605
36605
  writeFileSync5(path, JSON.stringify(settings, null, 2) + `
@@ -36698,7 +36698,7 @@ function buildCodewithTomlFragment(name, profile, mementos) {
36698
36698
  function readCodewithConfig(scope, configPath) {
36699
36699
  const path = getSettingsPath(scope, "codewith", configPath);
36700
36700
  try {
36701
- return existsSync11(path) ? readFileSync7(path, "utf-8") : "";
36701
+ return existsSync13(path) ? readFileSync7(path, "utf-8") : "";
36702
36702
  } catch {
36703
36703
  return "";
36704
36704
  }
@@ -36706,9 +36706,9 @@ function readCodewithConfig(scope, configPath) {
36706
36706
  function appendCodewithFragment(fragment, scope, configPath) {
36707
36707
  const path = getSettingsPath(scope, "codewith", configPath);
36708
36708
  const dir = dirname7(path);
36709
- if (!existsSync11(dir))
36709
+ if (!existsSync13(dir))
36710
36710
  mkdirSync6(dir, { recursive: true });
36711
- const existing = existsSync11(path) ? readFileSync7(path, "utf-8") : "";
36711
+ const existing = existsSync13(path) ? readFileSync7(path, "utf-8") : "";
36712
36712
  const sep3 = existing.trim() ? `
36713
36713
 
36714
36714
  ` : "";
@@ -37046,7 +37046,7 @@ function removeHookForTarget(name, scope, target) {
37046
37046
  }
37047
37047
  function readSettingsAt(path) {
37048
37048
  try {
37049
- if (!existsSync11(path))
37049
+ if (!existsSync13(path))
37050
37050
  return;
37051
37051
  const raw = readFileSync7(path, "utf-8");
37052
37052
  const settings = JSON.parse(raw);
@@ -37172,7 +37172,7 @@ function codewithHasHookEntryInText(configText, name) {
37172
37172
  }
37173
37173
  function codewithHasHookEntry(name, scope = "global") {
37174
37174
  const path = getSettingsPath(scope, "codewith");
37175
- if (!existsSync11(path))
37175
+ if (!existsSync13(path))
37176
37176
  return false;
37177
37177
  try {
37178
37178
  return codewithHasHookEntryInText(readFileSync7(path, "utf-8"), name);
@@ -37184,12 +37184,12 @@ function removeStoreDirFailClosed(dir) {
37184
37184
  const entries = readdirSync4(dir, { withFileTypes: true });
37185
37185
  for (const entry of entries) {
37186
37186
  if (entry.isDirectory()) {
37187
- removeStoreDirFailClosed(join10(dir, entry.name));
37187
+ removeStoreDirFailClosed(join12(dir, entry.name));
37188
37188
  }
37189
37189
  }
37190
37190
  for (const entry of entries) {
37191
37191
  if (!entry.isDirectory()) {
37192
- unlinkSync2(join10(dir, entry.name));
37192
+ unlinkSync2(join12(dir, entry.name));
37193
37193
  }
37194
37194
  }
37195
37195
  rmdirSync(dir);
@@ -37220,7 +37220,7 @@ function uninstallHook(name, scope = "global", target = "claude") {
37220
37220
  const registrationsRemaining = [];
37221
37221
  if (target === "codewith" || target === "all") {
37222
37222
  const codewithPath = getSettingsPath(scope, "codewith");
37223
- if (existsSync11(codewithPath)) {
37223
+ if (existsSync13(codewithPath)) {
37224
37224
  const before = readFileSync7(codewithPath, "utf-8");
37225
37225
  const after = removeCodewithHookEntry(before, shortName);
37226
37226
  if (after.removed) {
@@ -37271,7 +37271,7 @@ var init_installer = __esm(() => {
37271
37271
  init_native_safety();
37272
37272
  init_claude_skills_coordination();
37273
37273
  __dirname2 = dirname7(fileURLToPath2(import.meta.url));
37274
- HOOKS_DIR = existsSync11(join10(__dirname2, "..", "..", "hooks", "hook-gitguard")) ? join10(__dirname2, "..", "..", "hooks") : join10(__dirname2, "..", "hooks");
37274
+ HOOKS_DIR = existsSync13(join12(__dirname2, "..", "..", "hooks", "hook-gitguard")) ? join12(__dirname2, "..", "..", "hooks") : join12(__dirname2, "..", "hooks");
37275
37275
  EVENT_MAP = {
37276
37276
  claude: {
37277
37277
  PreToolUse: "PreToolUse",
@@ -37385,12 +37385,12 @@ var init_redact = __esm(() => {
37385
37385
  });
37386
37386
 
37387
37387
  // src/lib/profiles.ts
37388
- import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync8, readdirSync as readdirSync8, rmSync, cpSync as cpSync2 } from "fs";
37389
- import { join as join11 } from "path";
37388
+ import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync8, readdirSync as readdirSync8, rmSync, cpSync as cpSync2 } from "fs";
37389
+ import { join as join13 } from "path";
37390
37390
  function getProfilesDir() {
37391
- const newDir = join11(getEffectiveDataRoot(), "profiles");
37392
- const oldDir = join11(getHomeDir(), ".hooks", "profiles");
37393
- if (!existsSync12(newDir) && existsSync12(oldDir)) {
37391
+ const newDir = join13(getEffectiveDataRoot(), "profiles");
37392
+ const oldDir = join13(getHomeDir(), ".hooks", "profiles");
37393
+ if (!existsSync14(newDir) && existsSync14(oldDir)) {
37394
37394
  mkdirSync9(newDir, { recursive: true });
37395
37395
  cpSync2(oldDir, newDir, { recursive: true });
37396
37396
  }
@@ -37398,12 +37398,12 @@ function getProfilesDir() {
37398
37398
  }
37399
37399
  function ensureProfilesDir() {
37400
37400
  const dir = getProfilesDir();
37401
- if (!existsSync12(dir)) {
37401
+ if (!existsSync14(dir)) {
37402
37402
  mkdirSync9(dir, { recursive: true });
37403
37403
  }
37404
37404
  }
37405
37405
  function profilePath(id) {
37406
- return join11(getProfilesDir(), `${id}.json`);
37406
+ return join13(getProfilesDir(), `${id}.json`);
37407
37407
  }
37408
37408
  function shortUuid() {
37409
37409
  return crypto.randomUUID().slice(0, 8);
@@ -37429,7 +37429,7 @@ function createProfile(input2) {
37429
37429
  function getProfile(id) {
37430
37430
  const path = profilePath(id);
37431
37431
  try {
37432
- if (!existsSync12(path))
37432
+ if (!existsSync14(path))
37433
37433
  return null;
37434
37434
  return JSON.parse(readFileSync9(path, "utf-8"));
37435
37435
  } catch {
@@ -37438,14 +37438,14 @@ function getProfile(id) {
37438
37438
  }
37439
37439
  function listProfiles() {
37440
37440
  const dir = getProfilesDir();
37441
- if (!existsSync12(dir))
37441
+ if (!existsSync14(dir))
37442
37442
  return [];
37443
37443
  try {
37444
37444
  const files = readdirSync8(dir).filter((f) => f.endsWith(".json"));
37445
37445
  const profiles = [];
37446
37446
  for (const file2 of files) {
37447
37447
  try {
37448
- const content = readFileSync9(join11(dir, file2), "utf-8");
37448
+ const content = readFileSync9(join13(dir, file2), "utf-8");
37449
37449
  profiles.push(JSON.parse(content));
37450
37450
  } catch {}
37451
37451
  }
@@ -37475,7 +37475,7 @@ function importProfiles(profiles) {
37475
37475
  continue;
37476
37476
  }
37477
37477
  const path = profilePath(profile.agent_id);
37478
- if (existsSync12(path)) {
37478
+ if (existsSync14(path)) {
37479
37479
  skipped++;
37480
37480
  continue;
37481
37481
  }
@@ -37489,18 +37489,18 @@ var init_profiles = __esm(() => {
37489
37489
  init_app_home();
37490
37490
  });
37491
37491
 
37492
- // ../hooks0102-standalone-lock/node_modules/@hasna/contracts/dist/client/transport.js
37493
- import { isIP } from "net";
37492
+ // ../../node_modules/.bun/@hasna+contracts@1.2.2+944b86d8024e79fa/node_modules/@hasna/contracts/dist/client/transport.js
37493
+ import { isIP as isIP2 } from "net";
37494
37494
  import { spawnSync } from "child_process";
37495
37495
  import { closeSync as closeSync22, fstatSync as fstatSync22, openSync as openSync22, readFileSync as readFileSync22 } from "fs";
37496
37496
  import { O_NOFOLLOW as O_NOFOLLOW2, O_NONBLOCK as O_NONBLOCK2, O_RDONLY as O_RDONLY2 } from "constants";
37497
37497
  import { hostname as osHostname } from "os";
37498
37498
  import { isAbsolute as isAbsolute7, join as join22 } from "path";
37499
- import { createRequire as createRequire2 } from "module";
37499
+ import { createRequire as createRequire3 } from "module";
37500
37500
  import { fileURLToPath as fileURLToPath22 } from "url";
37501
37501
  import { closeSync as closeSync4, fstatSync as fstatSync3, lstatSync as lstatSync7, openSync as openSync4, readFileSync as readFileSync12, realpathSync as realpathSync7, statSync } from "fs";
37502
37502
  import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
37503
- import { basename as basename5, dirname as dirname11, join as join12, relative, sep as sep3 } from "path";
37503
+ import { basename as basename5, dirname as dirname11, join as join17, relative, sep as sep3 } from "path";
37504
37504
  import { fileURLToPath as fileURLToPath3, pathToFileURL } from "url";
37505
37505
  function envToken2(name) {
37506
37506
  return name.toUpperCase().replace(/-/g, "_");
@@ -37575,11 +37575,11 @@ function o(e2, r2, t2) {
37575
37575
  }
37576
37576
  function entryPoint(directory2) {
37577
37577
  const root = realpathSync7(directory2);
37578
- const fd = openSync4(join12(root, "package.json"), O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
37578
+ const fd = openSync4(join17(root, "package.json"), O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
37579
37579
  let pkg;
37580
37580
  try {
37581
37581
  const stat2 = fstatSync3(fd);
37582
- if (!stat2.isFile() || stat2.size > MAX_PACKAGE_BYTES2)
37582
+ if (!stat2.isFile() || stat2.size > MAX_PACKAGE_BYTES3)
37583
37583
  throw new Error("Invalid Secrets package metadata");
37584
37584
  pkg = JSON.parse(readFileSync12(fd, "utf8"));
37585
37585
  } finally {
@@ -37595,7 +37595,7 @@ function entryPoint(directory2) {
37595
37595
  if (/[\\%?#\0]/.test(target) || parts.some((part) => !part || part === "." || part === ".." || part === "node_modules")) {
37596
37596
  throw new Error("Invalid Secrets import export");
37597
37597
  }
37598
- const file2 = realpathSync7(join12(root, ...parts));
37598
+ const file2 = realpathSync7(join17(root, ...parts));
37599
37599
  const within = relative(root, file2);
37600
37600
  if (!within || within === ".." || within.startsWith(`..${sep3}`) || !statSync(file2).isFile()) {
37601
37601
  throw new Error("Secrets import export escapes its package or is not a file");
@@ -37606,7 +37606,7 @@ function resolveInstalledSecrets(parentUrl) {
37606
37606
  let directory2 = dirname11(fileURLToPath3(parentUrl));
37607
37607
  for (;; ) {
37608
37608
  if (basename5(directory2) !== "node_modules") {
37609
- const candidate = join12(directory2, "node_modules", PACKAGE);
37609
+ const candidate = join17(directory2, "node_modules", PACKAGE);
37610
37610
  let absent = false;
37611
37611
  try {
37612
37612
  lstatSync7(candidate);
@@ -37726,7 +37726,7 @@ function readAppConfigFile(path) {
37726
37726
  const uid2 = process.getuid?.() ?? process.geteuid?.();
37727
37727
  if (uid2 !== undefined && before.uid !== uid2)
37728
37728
  unsafe("the file is not owned by the current user");
37729
- if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
37729
+ if (before.size > MAX_CREDENTIAL_FILE_BYTES3)
37730
37730
  unsafe("the file exceeds the size limit");
37731
37731
  const bytes = readFileSync22(fd);
37732
37732
  const after = fstatSync22(fd);
@@ -37818,13 +37818,13 @@ function sealCredential(fields) {
37818
37818
  configurable: false
37819
37819
  });
37820
37820
  }
37821
- Object.defineProperty(sealed, INSPECT_CUSTOM2, {
37821
+ Object.defineProperty(sealed, INSPECT_CUSTOM3, {
37822
37822
  value: () => ({ ...visible, apiKey: "[redacted]" }),
37823
37823
  enumerable: false,
37824
37824
  writable: false,
37825
37825
  configurable: false
37826
37826
  });
37827
- Object.defineProperty(sealed, CREDENTIAL_SEAL2, {
37827
+ Object.defineProperty(sealed, CREDENTIAL_SEAL3, {
37828
37828
  value: true,
37829
37829
  enumerable: false,
37830
37830
  writable: false,
@@ -37855,7 +37855,7 @@ function firstEnvValue(env, keys) {
37855
37855
  return null;
37856
37856
  }
37857
37857
  function isAmbientEnvironment(env) {
37858
- return env === process.env || env[AMBIENT_ENVIRONMENT2] === true;
37858
+ return env === process.env || env[AMBIENT_ENVIRONMENT3] === true;
37859
37859
  }
37860
37860
  function defaultKeychainRunner(argv) {
37861
37861
  const result = spawnSync(KEYCHAIN_SECURITY_BIN, [...argv], {
@@ -37949,7 +37949,7 @@ function snapshotClientEnvironment(name, env) {
37949
37949
  snapshot2[key] = descriptor.value;
37950
37950
  }
37951
37951
  if (ambient) {
37952
- Object.defineProperty(snapshot2, AMBIENT_ENVIRONMENT2, {
37952
+ Object.defineProperty(snapshot2, AMBIENT_ENVIRONMENT3, {
37953
37953
  value: true,
37954
37954
  enumerable: false,
37955
37955
  writable: false,
@@ -38122,7 +38122,7 @@ async function completePointerCredential(name, pointerResolution, env = process.
38122
38122
  let secretsSdk;
38123
38123
  try {
38124
38124
  const sdkUrl = resolveInstalledSecrets(import.meta.url);
38125
- secretsSdk = requireSecretsSdk2(fileURLToPath22(sdkUrl));
38125
+ secretsSdk = requireSecretsSdk3(fileURLToPath22(sdkUrl));
38126
38126
  } catch {
38127
38127
  throw new CredentialResolutionError(name, `${pointerEnvKey} names vault item '${vaultKey}', but the secrets SDK (@hasna/secrets) is not installed ` + `in this process. A vault pointer is TERMINAL: install @hasna/secrets to resolve it, or unset ${pointerEnvKey}.`, [pointerEnvKey]);
38128
38128
  }
@@ -38206,7 +38206,7 @@ function canonicalAuthorityHostname(authority) {
38206
38206
  }
38207
38207
  assertCanonicalPort(portSuffix.slice(1));
38208
38208
  }
38209
- if (isIP(rawHostname.slice(1, -1)) !== 6) {
38209
+ if (isIP2(rawHostname.slice(1, -1)) !== 6) {
38210
38210
  throw new Error("API URL authority must contain a canonical IPv6 literal.");
38211
38211
  }
38212
38212
  } else {
@@ -38222,7 +38222,7 @@ function canonicalAuthorityHostname(authority) {
38222
38222
  } else {
38223
38223
  rawHostname = authority;
38224
38224
  }
38225
- const ipVersion = isIP(rawHostname);
38225
+ const ipVersion = isIP2(rawHostname);
38226
38226
  const numericAddressParts = rawHostname.split(".");
38227
38227
  const looksLikeNonCanonicalIpv4 = numericAddressParts.every((part) => /^(?:0x[0-9a-f]+|[0-9]+)$/i.test(part));
38228
38228
  if (ipVersion !== 4 && looksLikeNonCanonicalIpv4 || ipVersion !== 4 && !isValidDnsDomain(rawHostname.toLowerCase())) {
@@ -38358,9 +38358,9 @@ function credentialDiskSourcesForMessage(name, env) {
38358
38358
  const paths = credentialDiskSources(name, env);
38359
38359
  return paths.length > 0 ? paths.join(" or ") : "<no HOME or HASNA_HOME set in this environment, so no credential file was consulted>";
38360
38360
  }
38361
- var CREDENTIAL_PROFILE_ENV_KEY = "HASNA_PROFILE", PACKAGE = "@hasna/secrets", MAX_PACKAGE_BYTES2, CredentialResolutionError, CredentialFileUnsafeError, HASNA_HOME_ENV_KEY = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY = "HASNA_STATION", HASNA_HOME_DIR = ".hasna", CONFIG_SUBDIR = "config", CREDENTIALS_FILE = "credentials", KEYCHAIN_SECURITY_BIN = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS = 44, KEYCHAIN_SPAWN_TIMEOUT_MS = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG, SAFE_PROFILE, ILLEGAL_IN_HEADER_VALUE, VAULT_POINTER_SHAPE, CREDENTIAL_SHAPED_KEY, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, AMBIENT_ENVIRONMENT2, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN, DNS_LABEL_PATTERN, ClientTransportConfigurationError, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2;
38361
+ var CREDENTIAL_PROFILE_ENV_KEY = "HASNA_PROFILE", PACKAGE = "@hasna/secrets", MAX_PACKAGE_BYTES3, CredentialResolutionError, CredentialFileUnsafeError, HASNA_HOME_ENV_KEY = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY = "HASNA_STATION", HASNA_HOME_DIR = ".hasna", CONFIG_SUBDIR = "config", CREDENTIALS_FILE = "credentials", KEYCHAIN_SECURITY_BIN = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS = 44, KEYCHAIN_SPAWN_TIMEOUT_MS = 1e4, MAX_CREDENTIAL_FILE_BYTES3, SAFE_APP_SLUG, SAFE_PROFILE, ILLEGAL_IN_HEADER_VALUE, VAULT_POINTER_SHAPE, CREDENTIAL_SHAPED_KEY, INSPECT_CUSTOM3, CREDENTIAL_SEAL3, AMBIENT_ENVIRONMENT3, requireSecretsSdk3, DEFAULT_FLEET_GATEWAY_ORIGIN = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN, DNS_LABEL_PATTERN, ClientTransportConfigurationError, IDEMPOTENT_METHODS3, AUTHORITY_OVERRIDE_HEADERS3;
38362
38362
  var init_transport = __esm(() => {
38363
- MAX_PACKAGE_BYTES2 = 1024 * 1024;
38363
+ MAX_PACKAGE_BYTES3 = 1024 * 1024;
38364
38364
  CredentialResolutionError = class CredentialResolutionError extends Error {
38365
38365
  appName;
38366
38366
  attempted;
@@ -38379,16 +38379,16 @@ var init_transport = __esm(() => {
38379
38379
  this.path = path;
38380
38380
  }
38381
38381
  };
38382
- MAX_CREDENTIAL_FILE_BYTES2 = 64 * 1024;
38382
+ MAX_CREDENTIAL_FILE_BYTES3 = 64 * 1024;
38383
38383
  SAFE_APP_SLUG = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
38384
38384
  SAFE_PROFILE = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
38385
38385
  ILLEGAL_IN_HEADER_VALUE = /[^\t\x20-\x7e]/;
38386
38386
  VAULT_POINTER_SHAPE = /^[a-z0-9][a-z0-9-]*(?:\/[a-z0-9][a-z0-9-_.]*){2,}$/;
38387
38387
  CREDENTIAL_SHAPED_KEY = /(?:^|_)(?:API_KEY|KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)(?:_|$)/;
38388
- INSPECT_CUSTOM2 = Symbol.for("nodejs.util.inspect.custom");
38389
- CREDENTIAL_SEAL2 = Symbol.for("hasna:contracts:sealedCredential");
38390
- AMBIENT_ENVIRONMENT2 = Symbol.for("hasna:contracts:ambientClientEnvironment");
38391
- requireSecretsSdk2 = createRequire2(import.meta.url);
38388
+ INSPECT_CUSTOM3 = Symbol.for("nodejs.util.inspect.custom");
38389
+ CREDENTIAL_SEAL3 = Symbol.for("hasna:contracts:sealedCredential");
38390
+ AMBIENT_ENVIRONMENT3 = Symbol.for("hasna:contracts:ambientClientEnvironment");
38391
+ requireSecretsSdk3 = createRequire3(import.meta.url);
38392
38392
  ASCII_CONTROL_PATTERN = /[\u0000-\u001f\u007f]/;
38393
38393
  DNS_LABEL_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
38394
38394
  ClientTransportConfigurationError = class ClientTransportConfigurationError extends Error {
@@ -38401,8 +38401,8 @@ var init_transport = __esm(() => {
38401
38401
  this.sources = Object.freeze([...sources]);
38402
38402
  }
38403
38403
  };
38404
- IDEMPOTENT_METHODS2 = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
38405
- AUTHORITY_OVERRIDE_HEADERS2 = new Set([
38404
+ IDEMPOTENT_METHODS3 = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
38405
+ AUTHORITY_OVERRIDE_HEADERS3 = new Set([
38406
38406
  "host",
38407
38407
  ":authority",
38408
38408
  "forwarded",
@@ -38738,7 +38738,7 @@ var init_db_writer = __esm(() => {
38738
38738
 
38739
38739
  // src/lib/hook-env.ts
38740
38740
  import { dirname as dirname17, isAbsolute as isAbsolute15 } from "path";
38741
- import { existsSync as existsSync13, realpathSync as realpathSync8, statSync as statSync2 } from "fs";
38741
+ import { existsSync as existsSync15, realpathSync as realpathSync8, statSync as statSync2 } from "fs";
38742
38742
  import { tmpdir } from "os";
38743
38743
  function isDeniedEnvName(name) {
38744
38744
  const upper = name.toUpperCase();
@@ -38786,7 +38786,7 @@ function isUnsafePathEntry(entry, home) {
38786
38786
  }
38787
38787
  function sanitizeHookPath(pathValue, home) {
38788
38788
  const baseline = PATH_BASELINE.slice();
38789
- if (process.platform === "darwin" && existsSync13("/opt/homebrew/bin"))
38789
+ if (process.platform === "darwin" && existsSync15("/opt/homebrew/bin"))
38790
38790
  baseline.push("/opt/homebrew/bin");
38791
38791
  const bunDir = dirname17(process.execPath);
38792
38792
  const seen = new Set;
@@ -38913,7 +38913,7 @@ __export(exports_run, {
38913
38913
  });
38914
38914
  import { randomBytes as randomBytes2 } from "crypto";
38915
38915
  import { rmSync as rmSync2, writeFileSync as writeFileSync10 } from "fs";
38916
- import { basename as basename9, dirname as dirname19, isAbsolute as isAbsolute17, join as join13 } from "path";
38916
+ import { basename as basename9, dirname as dirname19, isAbsolute as isAbsolute17, join as join19 } from "path";
38917
38917
  function extensionOf(scriptPath) {
38918
38918
  const base = basename9(scriptPath);
38919
38919
  const dot = base.lastIndexOf(".");
@@ -38984,7 +38984,7 @@ async function readPipeWithDeadline(stream, deadlineMs) {
38984
38984
  async function executeVerifiedScript(options) {
38985
38985
  const scriptDir = dirname19(options.scriptPath);
38986
38986
  const interpreter = interpreterFor(options.name, options.scriptPath, options.content);
38987
- const tempPath = join13(scriptDir, `.hooks-verified-${randomBytes2(12).toString("hex")}.${interpreter.tempExt}`);
38987
+ const tempPath = join19(scriptDir, `.hooks-verified-${randomBytes2(12).toString("hex")}.${interpreter.tempExt}`);
38988
38988
  let proc = null;
38989
38989
  let timedOut = false;
38990
38990
  const timeoutTimer = options.timeout ? setTimeout(() => {
@@ -39075,12 +39075,12 @@ __export(exports_custom_install, {
39075
39075
  installCustomSource: () => installCustomSource,
39076
39076
  ensureCustomDir: () => ensureCustomDir
39077
39077
  });
39078
- import { existsSync as existsSync14, mkdirSync as mkdirSync11, mkdtempSync, readFileSync as readFileSync14, rmSync as rmSync4 } from "fs";
39079
- import { join as join17 } from "path";
39078
+ import { existsSync as existsSync16, mkdirSync as mkdirSync11, mkdtempSync, readFileSync as readFileSync14, rmSync as rmSync4 } from "fs";
39079
+ import { join as join20 } from "path";
39080
39080
  import { tmpdir as tmpdir2 } from "os";
39081
39081
  function manifestAt(dir) {
39082
- const path = join17(dir, "manifest.json");
39083
- if (!existsSync14(path))
39082
+ const path = join20(dir, "manifest.json");
39083
+ if (!existsSync16(path))
39084
39084
  return;
39085
39085
  try {
39086
39086
  return parseManifest(readFileSync14(path, "utf-8"));
@@ -39102,8 +39102,8 @@ function writeFromManifest(manifest, srcDir, source, kind) {
39102
39102
  return { name, version: manifest.version, kind, source, dir, scriptPath };
39103
39103
  }
39104
39104
  async function cloneToTemp(gitUrl) {
39105
- const tmp = mkdtempSync(join17(tmpdir2(), "hooks-install-"));
39106
- const proc = Bun.spawn(["git", "clone", "--depth", "1", "--quiet", gitUrl, join17(tmp, "repo")], {
39105
+ const tmp = mkdtempSync(join20(tmpdir2(), "hooks-install-"));
39106
+ const proc = Bun.spawn(["git", "clone", "--depth", "1", "--quiet", gitUrl, join20(tmp, "repo")], {
39107
39107
  stdout: "pipe",
39108
39108
  stderr: "pipe"
39109
39109
  });
@@ -39116,7 +39116,7 @@ async function cloneToTemp(gitUrl) {
39116
39116
  rmSync4(tmp, { recursive: true, force: true });
39117
39117
  throw new Error(`git clone failed (${exitCode}): ${stderr.trim()}`);
39118
39118
  }
39119
- return join17(tmp, "repo");
39119
+ return join20(tmp, "repo");
39120
39120
  }
39121
39121
  function isGitUrl(value) {
39122
39122
  return value.startsWith("git@") || value.startsWith("ssh://") || value.startsWith("file://") || value.endsWith(".git");
@@ -39126,7 +39126,7 @@ function isCustomSource(value) {
39126
39126
  return true;
39127
39127
  if (value.startsWith("http://") || value.startsWith("https://"))
39128
39128
  return true;
39129
- return existsSync14(value);
39129
+ return existsSync16(value);
39130
39130
  }
39131
39131
  async function installCustomSource(source) {
39132
39132
  if (isGitUrl(source)) {
@@ -39140,7 +39140,7 @@ async function installCustomSource(source) {
39140
39140
  if (source.startsWith("http://") || source.startsWith("https://")) {
39141
39141
  return installManifestUrl(source);
39142
39142
  }
39143
- if (!existsSync14(source)) {
39143
+ if (!existsSync16(source)) {
39144
39144
  throw new Error(`No such local path: ${source}`);
39145
39145
  }
39146
39146
  if (source.endsWith("manifest.json")) {
@@ -40355,11 +40355,11 @@ __export(exports_serve, {
40355
40355
  DEFAULT_SERVE_PORT: () => DEFAULT_SERVE_PORT
40356
40356
  });
40357
40357
  import { readFileSync as readFileSync17 } from "fs";
40358
- import { dirname as dirname20, join as join19 } from "path";
40358
+ import { dirname as dirname20, join as join24 } from "path";
40359
40359
  import { fileURLToPath as fileURLToPath4 } from "url";
40360
40360
  function packageVersion() {
40361
40361
  try {
40362
- const pkgPath = join19(dirname20(fileURLToPath4(import.meta.url)), "..", "package.json");
40362
+ const pkgPath = join24(dirname20(fileURLToPath4(import.meta.url)), "..", "package.json");
40363
40363
  return JSON.parse(readFileSync17(pkgPath, "utf-8")).version || "0.0.0";
40364
40364
  } catch {
40365
40365
  return "0.0.0";
@@ -40660,14 +40660,14 @@ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
40660
40660
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
40661
40661
  import { z as z3 } from "zod";
40662
40662
  import { createServer } from "http";
40663
- import { existsSync as existsSync15, readFileSync as readFileSync19 } from "fs";
40664
- import { join as join20, dirname as dirname21 } from "path";
40663
+ import { existsSync as existsSync17, readFileSync as readFileSync19 } from "fs";
40664
+ import { join as join27, dirname as dirname21 } from "path";
40665
40665
  import { fileURLToPath as fileURLToPath5 } from "url";
40666
40666
  async function runVerifiedHook(name, stdin, timeoutMs) {
40667
40667
  const { resolveHook: resolveHook2, resolveScriptPath: resolveScriptPath2 } = await Promise.resolve().then(() => (init_resolve(), exports_resolve));
40668
40668
  const resolved = resolveHook2(name);
40669
40669
  const hookScript = resolveScriptPath2(name);
40670
- if (!resolved || !hookScript || !existsSync15(hookScript)) {
40670
+ if (!resolved || !hookScript || !existsSync17(hookScript)) {
40671
40671
  throw new Error(`Hook '${name}' not found`);
40672
40672
  }
40673
40673
  const content = readFileSync19(hookScript);
@@ -40875,7 +40875,7 @@ function createHooksServer() {
40875
40875
  const settingsPath = getSettingsPath(scope);
40876
40876
  const issues = [];
40877
40877
  const healthy = [];
40878
- const settingsExist = existsSync15(settingsPath);
40878
+ const settingsExist = existsSync17(settingsPath);
40879
40879
  if (!settingsExist) {
40880
40880
  issues.push({ hook: "(settings)", issue: `${settingsPath} not found`, severity: "warning" });
40881
40881
  }
@@ -40885,7 +40885,7 @@ function createHooksServer() {
40885
40885
  const meta3 = custom2 ? resolveHookMeta(name) : getHook(name);
40886
40886
  let hookHealthy = true;
40887
40887
  if (custom2) {
40888
- if (!existsSync15(custom2.scriptPath)) {
40888
+ if (!existsSync17(custom2.scriptPath)) {
40889
40889
  issues.push({ hook: name, issue: `Custom hook script missing: ${custom2.scriptPath}`, severity: "error" });
40890
40890
  hookHealthy = false;
40891
40891
  }
@@ -40895,7 +40895,7 @@ function createHooksServer() {
40895
40895
  continue;
40896
40896
  }
40897
40897
  const hookDir = getHookPath(name);
40898
- if (!existsSync15(join20(hookDir, "src", "hook.ts"))) {
40898
+ if (!existsSync17(join27(hookDir, "src", "hook.ts"))) {
40899
40899
  issues.push({ hook: name, issue: "Missing src/hook.ts in package", severity: "error" });
40900
40900
  hookHealthy = false;
40901
40901
  }
@@ -40939,9 +40939,9 @@ function createHooksServer() {
40939
40939
  return { content: [{ type: "text", text: JSON.stringify({ error: `Hook '${name}' not found` }) }] };
40940
40940
  }
40941
40941
  const hookPath = getHookPath(name);
40942
- const readmePath = join20(hookPath, "README.md");
40942
+ const readmePath = join27(hookPath, "README.md");
40943
40943
  let readme = "";
40944
- if (existsSync15(readmePath)) {
40944
+ if (existsSync17(readmePath)) {
40945
40945
  readme = readFileSync19(readmePath, "utf-8");
40946
40946
  }
40947
40947
  if (verbose) {
@@ -41125,7 +41125,7 @@ function createHooksServer() {
41125
41125
  const ctx = {
41126
41126
  scope,
41127
41127
  settings_path: settingsPath,
41128
- settings_exists: existsSync15(settingsPath),
41128
+ settings_exists: existsSync17(settingsPath),
41129
41129
  registered_hooks: hooks,
41130
41130
  hook_count: hooks.length,
41131
41131
  healthy,
@@ -41271,7 +41271,7 @@ function createHooksServer() {
41271
41271
  const settingsPath = getSettingsPath(scope);
41272
41272
  let settings = {};
41273
41273
  try {
41274
- if (existsSync15(settingsPath))
41274
+ if (existsSync17(settingsPath))
41275
41275
  settings = JSON.parse(readFileSync19(settingsPath, "utf-8"));
41276
41276
  } catch {}
41277
41277
  if (!settings.hooks)
@@ -41294,7 +41294,7 @@ function createHooksServer() {
41294
41294
  const settingsPath = getSettingsPath(scope);
41295
41295
  let settings = {};
41296
41296
  try {
41297
- if (existsSync15(settingsPath))
41297
+ if (existsSync17(settingsPath))
41298
41298
  settings = JSON.parse(readFileSync19(settingsPath, "utf-8"));
41299
41299
  } catch {}
41300
41300
  if (settings.hooks?.__disabled) {
@@ -41669,8 +41669,8 @@ var init_server = __esm(() => {
41669
41669
  pkg = { name: "@hasna/hooks", version: "0.0.0" };
41670
41670
  try {
41671
41671
  for (const rel of ["../../package.json", "../package.json", "../../../package.json"]) {
41672
- const p = join20(__dirname3, rel);
41673
- if (existsSync15(p)) {
41672
+ const p = join27(__dirname3, rel);
41673
+ if (existsSync17(p)) {
41674
41674
  pkg = JSON.parse(readFileSync19(p, "utf-8"));
41675
41675
  break;
41676
41676
  }
@@ -41739,16 +41739,25 @@ function startMcpHttpServer(options) {
41739
41739
  var DEFAULT_MCP_HTTP_PORT = 8847, MCP_HTTP_HOST = "127.0.0.1", MCP_SERVICE_NAME = "hooks";
41740
41740
  var init_http = () => {};
41741
41741
 
41742
- // ../hooks0102-standalone-lock/node_modules/@hasna/events/dist/commander.js
41742
+ // ../events/dist/commander.js
41743
41743
  import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
41744
41744
  import { Buffer as Buffer2 } from "buffer";
41745
+ import { existsSync as existsSync2 } from "fs";
41746
+ import { join as join2 } from "path";
41745
41747
  import { existsSync } from "fs";
41746
41748
  import { homedir } from "os";
41747
- import { join } from "path";
41749
+ import { join, resolve } from "path";
41750
+ import { homedir as pathsResolverHomedir } from "os";
41751
+ import { join as pathsResolverJoin } from "path";
41748
41752
  import { createHmac, timingSafeEqual } from "crypto";
41753
+ import { lookup as dnsLookup } from "dns/promises";
41754
+ import { isIP } from "net";
41749
41755
  import { randomUUID } from "crypto";
41750
41756
  import { spawn } from "child_process";
41757
+ import { request as nodeHttpRequest } from "http";
41758
+ import { request as nodeHttpsRequest } from "https";
41751
41759
  import { randomUUID as randomUUID2 } from "crypto";
41760
+ import { createRequire } from "module";
41752
41761
  function getPathValue(input, path) {
41753
41762
  return path.split(".").reduce((value, part) => {
41754
41763
  if (value && typeof value === "object" && part in value) {
@@ -41844,13 +41853,103 @@ function channelMatchesEvent(channel, event) {
41844
41853
  return true;
41845
41854
  return channel.filters.some((filter) => eventMatchesFilter(event, filter));
41846
41855
  }
41856
+ var PATHS_RESOLVER_KIND_ENV = {
41857
+ config: "HASNA_CONFIG_HOME",
41858
+ data: "HASNA_DATA_HOME",
41859
+ state: "HASNA_STATE_HOME",
41860
+ cache: "HASNA_CACHE_HOME"
41861
+ };
41862
+ var PATHS_RESOLVER_APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
41863
+ function pathsResolverAssertApp(app) {
41864
+ if (typeof app !== "string" || app.length === 0) {
41865
+ throw new TypeError("paths: app must be a non-empty string");
41866
+ }
41867
+ if (!PATHS_RESOLVER_APP_SLUG_RE.test(app)) {
41868
+ throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
41869
+ }
41870
+ }
41871
+ function pathsResolverAssertKind(kind) {
41872
+ if (!Object.keys(PATHS_RESOLVER_KIND_ENV).includes(kind)) {
41873
+ throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${Object.keys(PATHS_RESOLVER_KIND_ENV).join(", ")}`);
41874
+ }
41875
+ }
41876
+ function pathsResolverBaseDir(kind, options) {
41877
+ pathsResolverAssertKind(kind);
41878
+ const env = options.env ?? process.env;
41879
+ const override = env[PATHS_RESOLVER_KIND_ENV[kind]];
41880
+ if (typeof override === "string" && override.length > 0)
41881
+ return override;
41882
+ const home = options.home ?? pathsResolverHomedir();
41883
+ const platform = options.platform ?? process.platform;
41884
+ if (platform === "darwin") {
41885
+ switch (kind) {
41886
+ case "config":
41887
+ case "data":
41888
+ return pathsResolverJoin(home, "Library", "Application Support", "Hasna");
41889
+ case "cache":
41890
+ return pathsResolverJoin(home, "Library", "Caches", "Hasna");
41891
+ case "state":
41892
+ return pathsResolverJoin(home, "Library", "Logs", "Hasna");
41893
+ }
41894
+ }
41895
+ switch (kind) {
41896
+ case "config":
41897
+ return pathsResolverJoin(home, ".config", "hasna");
41898
+ case "data":
41899
+ return pathsResolverJoin(home, ".local", "share", "hasna");
41900
+ case "state":
41901
+ return pathsResolverJoin(home, ".local", "state", "hasna");
41902
+ case "cache":
41903
+ return pathsResolverJoin(home, ".cache", "hasna");
41904
+ }
41905
+ }
41906
+ function pathsResolverResolve(kind, options) {
41907
+ pathsResolverAssertApp(options.app);
41908
+ const appSegment = options.internal === true ? pathsResolverJoin("internal", options.app) : options.app;
41909
+ return pathsResolverJoin(pathsResolverBaseDir(kind, options), appSegment);
41910
+ }
41911
+ function dataDir(options) {
41912
+ return pathsResolverResolve("data", options);
41913
+ }
41847
41914
  var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR";
41848
41915
  var HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME";
41916
+ var EVENTS_STORE_SENTINEL_FILE = "events.json";
41917
+ function effectiveHome() {
41918
+ return process.env["HOME"] || process.env["USERPROFILE"] || homedir();
41919
+ }
41920
+ function legacyHomeDir() {
41921
+ return join(effectiveHome(), ".hasna", "events");
41922
+ }
41923
+ function resolverHome() {
41924
+ return dataDir({ app: "events", home: effectiveHome() || undefined });
41925
+ }
41926
+ function adoptResolverHome(resolved, env = process.env) {
41927
+ const dataOverride = env.HASNA_DATA_HOME;
41928
+ if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
41929
+ return true;
41930
+ return existsSync(join(resolved, EVENTS_STORE_SENTINEL_FILE));
41931
+ }
41932
+ function exactEventsHome() {
41933
+ const dir = process.env[HASNA_EVENTS_DIR_ENV];
41934
+ if (dir && dir.trim())
41935
+ return dir.trim();
41936
+ const home = process.env[HASNA_EVENTS_HOME_ENV];
41937
+ if (home && home.trim())
41938
+ return home.trim();
41939
+ return;
41940
+ }
41941
+ function getEventsHome() {
41942
+ const exact = exactEventsHome();
41943
+ if (exact)
41944
+ return resolve(exact);
41945
+ const resolved = resolverHome();
41946
+ return adoptResolverHome(resolved) ? resolve(resolved) : resolve(legacyHomeDir());
41947
+ }
41849
41948
  var LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:";
41850
41949
  var DEFAULT_EVENT_PAGE_LIMIT = 100;
41851
41950
  var MAX_EVENT_PAGE_LIMIT = 1000;
41852
41951
  function getEventsDataDir(override) {
41853
- return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join(homedir(), ".hasna", "events");
41952
+ return override || getEventsHome();
41854
41953
  }
41855
41954
  function getActiveEventsDirEnv() {
41856
41955
  if (process.env[HASNA_EVENTS_DIR_ENV])
@@ -41866,12 +41965,12 @@ class JsonEventsStore {
41866
41965
  channelsPath;
41867
41966
  eventsPath;
41868
41967
  deliveriesPath;
41869
- constructor(dataDir = getEventsDataDir()) {
41870
- this.dataDir = dataDir;
41871
- this.runtime = localJsonRuntime(dataDir);
41872
- this.channelsPath = join(dataDir, "channels.json");
41873
- this.eventsPath = join(dataDir, "events.json");
41874
- this.deliveriesPath = join(dataDir, "deliveries.json");
41968
+ constructor(dataDir2 = getEventsDataDir()) {
41969
+ this.dataDir = dataDir2;
41970
+ this.runtime = localJsonRuntime(dataDir2);
41971
+ this.channelsPath = join2(dataDir2, "channels.json");
41972
+ this.eventsPath = join2(dataDir2, "events.json");
41973
+ this.deliveriesPath = join2(dataDir2, "deliveries.json");
41875
41974
  }
41876
41975
  async init() {
41877
41976
  await mkdir(this.dataDir, { recursive: true, mode: 448 });
@@ -41988,7 +42087,7 @@ class JsonEventsStore {
41988
42087
  };
41989
42088
  }
41990
42089
  async ensureArrayFile(path) {
41991
- if (!existsSync(path)) {
42090
+ if (!existsSync2(path)) {
41992
42091
  await writeFile(path, `[]
41993
42092
  `, { encoding: "utf-8", mode: 384 });
41994
42093
  }
@@ -42018,7 +42117,7 @@ class JsonEventsStore {
42018
42117
  });
42019
42118
  }
42020
42119
  }
42021
- function localJsonRuntime(dataDir = getEventsDataDir()) {
42120
+ function localJsonRuntime(dataDir2 = getEventsDataDir()) {
42022
42121
  return {
42023
42122
  mode: "local-files",
42024
42123
  name: "json-events-store",
@@ -42031,7 +42130,7 @@ function localJsonRuntime(dataDir = getEventsDataDir()) {
42031
42130
  durable: true,
42032
42131
  idempotency: "best-effort-local",
42033
42132
  replayCursors: true,
42034
- description: `Local JSON files in ${dataDir}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
42133
+ description: `Local JSON files in ${dataDir2}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
42035
42134
  };
42036
42135
  }
42037
42136
  function encodeLocalJsonEventCursor(offset, options = {}) {
@@ -42095,8 +42194,8 @@ function assertCursorFilter(name, cursorValue, optionValue) {
42095
42194
  function findEventByIdentity(events, identity) {
42096
42195
  return events.find((event) => identity.id !== undefined && event.id === identity.id || identity.dedupeKey !== undefined && event.dedupeKey === identity.dedupeKey);
42097
42196
  }
42098
- async function getEventsStatus(dataDir) {
42099
- const store = new JsonEventsStore(dataDir);
42197
+ async function getEventsStatus(dataDir2) {
42198
+ const store = new JsonEventsStore(dataDir2);
42100
42199
  await store.init();
42101
42200
  const [channels, events, deliveries] = await Promise.all([
42102
42201
  store.listChannels(),
@@ -42138,9 +42237,9 @@ async function getEventsStatus(dataDir) {
42138
42237
  }
42139
42238
  };
42140
42239
  }
42141
- function statusFile(dataDir, fileName, records) {
42142
- const path = join(dataDir, fileName);
42143
- return { path, exists: existsSync(path), records };
42240
+ function statusFile(dataDir2, fileName, records) {
42241
+ const path = join2(dataDir2, fileName);
42242
+ return { path, exists: existsSync2(path), records };
42144
42243
  }
42145
42244
  var DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
42146
42245
  function buildSignatureBase(timestamp, body) {
@@ -42150,6 +42249,214 @@ function signPayload(secret, timestamp, body) {
42150
42249
  const digest = createHmac("sha256", secret).update(buildSignatureBase(timestamp, body)).digest("hex");
42151
42250
  return `sha256=${digest}`;
42152
42251
  }
42252
+ var DEFAULT_MAX_REDIRECTS = 5;
42253
+ var IPV4_PRIVATE_RANGES = [
42254
+ [0, 16777215],
42255
+ [167772160, 184549375],
42256
+ [1681915904, 1686110207],
42257
+ [2130706432, 2147483647],
42258
+ [2851995648, 2852061183],
42259
+ [2886729728, 2887778303],
42260
+ [3221225472, 3221225727],
42261
+ [3221225984, 3221226239],
42262
+ [3227017984, 3227018239],
42263
+ [3232235520, 3232301055],
42264
+ [3323068416, 3323199487],
42265
+ [3325256704, 3325256959],
42266
+ [3405803776, 3405804031],
42267
+ [3758096384, 4294967295]
42268
+ ];
42269
+ var IPV6_SPECIAL_PREFIXES = [
42270
+ { groups: [0, 0, 0, 0, 0, 0, 0, 0], bits: 128 },
42271
+ { groups: [0, 0, 0, 0, 0, 0, 0, 1], bits: 128 },
42272
+ { groups: [0, 0, 0, 0, 0, 65535, 0, 0], bits: 96 },
42273
+ { groups: [100, 65435, 0, 0, 0, 0, 0, 0], bits: 96 },
42274
+ { groups: [256, 0, 0, 0, 0, 0, 0, 0], bits: 64 },
42275
+ { groups: [8193, 0, 0, 0, 0, 0, 0, 0], bits: 32 },
42276
+ { groups: [8193, 2, 0, 0, 0, 0, 0, 0], bits: 48 },
42277
+ { groups: [8193, 16, 0, 0, 0, 0, 0, 0], bits: 28 },
42278
+ { groups: [8193, 3512, 0, 0, 0, 0, 0, 0], bits: 32 },
42279
+ { groups: [8194, 0, 0, 0, 0, 0, 0, 0], bits: 16 },
42280
+ { groups: [16383, 0, 0, 0, 0, 0, 0, 0], bits: 20 },
42281
+ { groups: [64512, 0, 0, 0, 0, 0, 0, 0], bits: 7 },
42282
+ { groups: [65152, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
42283
+ { groups: [65216, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
42284
+ { groups: [65280, 0, 0, 0, 0, 0, 0, 0], bits: 8 }
42285
+ ];
42286
+ function isPrivateAddress(address) {
42287
+ const normalized = stripZoneId(address);
42288
+ const version = isIP(normalized);
42289
+ if (version === 4) {
42290
+ const integer = ipv4ToInt(normalized);
42291
+ if (integer === undefined)
42292
+ return true;
42293
+ return IPV4_PRIVATE_RANGES.some(([low, high]) => integer >= low && integer <= high);
42294
+ }
42295
+ if (version === 6) {
42296
+ const groups = ipv6Groups(normalized);
42297
+ if (!groups)
42298
+ return true;
42299
+ for (const prefix of IPV6_SPECIAL_PREFIXES) {
42300
+ if (!ipv6MatchesPrefix(groups, prefix.groups, prefix.bits))
42301
+ continue;
42302
+ if (prefix.bits === 96 && groups[5] === 65535) {
42303
+ return isPrivateAddress(ipv4IntToString(groups[6] << 16 | groups[7]));
42304
+ }
42305
+ if (prefix.bits === 16 && groups[0] === 8194) {
42306
+ return isPrivateAddress(ipv4IntToString(groups[1] << 16 | groups[2]));
42307
+ }
42308
+ return true;
42309
+ }
42310
+ return false;
42311
+ }
42312
+ return true;
42313
+ }
42314
+ async function resolveWebhookTarget(url, policy = {}) {
42315
+ const hostname = normalizeHostname(url.hostname);
42316
+ const allowlist = (policy.allowPrivateHosts ?? []).map((entry) => normalizeHostname(entry.toLowerCase()));
42317
+ if (allowlist.includes(hostname)) {
42318
+ const version2 = isIP(hostname);
42319
+ if (version2 === 4 || version2 === 6) {
42320
+ return { hostname, addresses: [hostname] };
42321
+ }
42322
+ const lookup2 = policy.lookup ?? defaultTargetLookup;
42323
+ let resolved2;
42324
+ try {
42325
+ resolved2 = await lookup2(hostname);
42326
+ } catch {
42327
+ throw new Error(`Webhook target ${hostname} could not be resolved`);
42328
+ }
42329
+ if (!Array.isArray(resolved2) || resolved2.length === 0) {
42330
+ throw new Error(`Webhook target ${hostname} resolved to no addresses`);
42331
+ }
42332
+ const addresses = resolved2.map((entry) => normalizeHostname(entry.address));
42333
+ return { hostname, addresses };
42334
+ }
42335
+ const version = isIP(hostname);
42336
+ if (version === 4 || version === 6) {
42337
+ if (isPrivateAddress(hostname)) {
42338
+ throw new Error(`Webhook target ${hostname} is a private or special-use address`);
42339
+ }
42340
+ return { hostname, addresses: [hostname] };
42341
+ }
42342
+ const lookup = policy.lookup ?? defaultTargetLookup;
42343
+ let resolved;
42344
+ try {
42345
+ resolved = await lookup(hostname);
42346
+ } catch {
42347
+ throw new Error(`Webhook target ${hostname} could not be resolved`);
42348
+ }
42349
+ if (!Array.isArray(resolved) || resolved.length === 0) {
42350
+ throw new Error(`Webhook target ${hostname} resolved to no addresses`);
42351
+ }
42352
+ const allowed = [];
42353
+ for (const entry of resolved) {
42354
+ const address = normalizeHostname(entry.address);
42355
+ if (isPrivateAddress(address)) {
42356
+ if (allowlist.includes(address)) {
42357
+ allowed.push(address);
42358
+ continue;
42359
+ }
42360
+ throw new Error(`Webhook target ${hostname} resolves to private or special-use address ${address}`);
42361
+ }
42362
+ allowed.push(address);
42363
+ }
42364
+ if (allowed.length === 0) {
42365
+ throw new Error(`Webhook target ${hostname} resolved to no public addresses`);
42366
+ }
42367
+ return { hostname, addresses: allowed };
42368
+ }
42369
+ function normalizeMaxRedirects(value) {
42370
+ if (value === undefined)
42371
+ return DEFAULT_MAX_REDIRECTS;
42372
+ if (!Number.isInteger(value) || value < 0)
42373
+ throw new Error("webhookTargetPolicy.maxRedirects must be a non-negative integer");
42374
+ return value;
42375
+ }
42376
+ var defaultTargetLookup = async (hostname) => {
42377
+ return dnsLookup(hostname, { all: true, verbatim: false });
42378
+ };
42379
+ function normalizeHostname(hostname) {
42380
+ const lower = hostname.toLowerCase();
42381
+ if (lower.startsWith("[") && lower.endsWith("]"))
42382
+ return lower.slice(1, -1);
42383
+ return lower;
42384
+ }
42385
+ function stripZoneId(address) {
42386
+ const percent = address.indexOf("%");
42387
+ return percent === -1 ? address : address.slice(0, percent);
42388
+ }
42389
+ function ipv4ToInt(address) {
42390
+ const parts = address.split(".");
42391
+ if (parts.length !== 4)
42392
+ return;
42393
+ let value = 0;
42394
+ for (const part of parts) {
42395
+ if (!/^\d{1,3}$/.test(part))
42396
+ return;
42397
+ const octet = Number(part);
42398
+ if (octet > 255)
42399
+ return;
42400
+ value = value << 8 | octet;
42401
+ }
42402
+ return value >>> 0;
42403
+ }
42404
+ function ipv4IntToString(integer) {
42405
+ return [
42406
+ integer >>> 24 & 255,
42407
+ integer >>> 16 & 255,
42408
+ integer >>> 8 & 255,
42409
+ integer & 255
42410
+ ].join(".");
42411
+ }
42412
+ function ipv6Groups(address) {
42413
+ const raw = stripZoneId(address);
42414
+ const doubleColon = raw.indexOf("::");
42415
+ const headText = doubleColon === -1 ? raw : raw.slice(0, doubleColon);
42416
+ const tailText = doubleColon === -1 ? "" : raw.slice(doubleColon + 2);
42417
+ const parseGroups = (text) => {
42418
+ if (text === "")
42419
+ return [];
42420
+ const out = [];
42421
+ for (const part of text.split(":")) {
42422
+ if (part.includes(".")) {
42423
+ const v4 = ipv4ToInt(part);
42424
+ if (v4 === undefined)
42425
+ return;
42426
+ out.push(v4 >>> 16 & 65535, v4 & 65535);
42427
+ } else {
42428
+ if (!/^[0-9a-fA-F]{1,4}$/.test(part))
42429
+ return;
42430
+ out.push(parseInt(part, 16));
42431
+ }
42432
+ }
42433
+ return out;
42434
+ };
42435
+ const head = parseGroups(headText);
42436
+ if (!head)
42437
+ return;
42438
+ const tail = parseGroups(tailText);
42439
+ if (!tail)
42440
+ return;
42441
+ const total = head.length + tail.length;
42442
+ if (doubleColon === -1) {
42443
+ return total === 8 ? head : undefined;
42444
+ }
42445
+ if (total >= 8)
42446
+ return;
42447
+ return [...head, ...new Array(8 - total).fill(0), ...tail];
42448
+ }
42449
+ function ipv6MatchesPrefix(groups, prefixGroups, prefixBits) {
42450
+ let remaining = prefixBits;
42451
+ for (let index = 0;index < prefixGroups.length && remaining > 0; index += 1) {
42452
+ const take = Math.min(16, remaining);
42453
+ const mask = 65535 << 16 - take & 65535;
42454
+ if ((groups[index] & mask) !== (prefixGroups[index] & mask))
42455
+ return false;
42456
+ remaining -= take;
42457
+ }
42458
+ return true;
42459
+ }
42153
42460
  function now() {
42154
42461
  return new Date().toISOString();
42155
42462
  }
@@ -42180,9 +42487,18 @@ function buildWebhookRequest(event, channel, options = {}) {
42180
42487
  }
42181
42488
  return { body, headers };
42182
42489
  }
42490
+ function normalizeWebhookUrl(raw) {
42491
+ const url = new URL(raw);
42492
+ if (url.username !== "" || url.password !== "") {
42493
+ url.username = "";
42494
+ url.password = "";
42495
+ }
42496
+ return url.toString();
42497
+ }
42183
42498
  async function dispatchWebhook(event, channel, options = {}) {
42184
42499
  if (!channel.webhook)
42185
42500
  throw new Error(`Channel ${channel.id} has no webhook config`);
42501
+ const webhookUrl = normalizeWebhookUrl(channel.webhook.url);
42186
42502
  const startedAt = now();
42187
42503
  let secret = channel.webhook.secret;
42188
42504
  if (channel.webhook.secretRef) {
@@ -42199,10 +42515,14 @@ async function dispatchWebhook(event, channel, options = {}) {
42199
42515
  }
42200
42516
  const timestamp = (options.now?.() ?? new Date).toISOString();
42201
42517
  const { body, headers } = buildWebhookRequest(event, channel, { secret, timestamp });
42518
+ const validateTargets = options.webhookTargetPolicy !== undefined || options.fetchImpl === undefined;
42519
+ if (validateTargets) {
42520
+ return dispatchValidatedWebhook(event, channel, { body, headers, startedAt, options });
42521
+ }
42202
42522
  const controller = new AbortController;
42203
42523
  const timeout = setTimeout(() => controller.abort(), channel.webhook.timeoutMs ?? 15000);
42204
42524
  try {
42205
- const response = await (options.fetchImpl ?? fetch)(channel.webhook.url, {
42525
+ const response = await (options.fetchImpl ?? fetch)(webhookUrl, {
42206
42526
  method: "POST",
42207
42527
  headers,
42208
42528
  body,
@@ -42230,6 +42550,130 @@ async function dispatchWebhook(event, channel, options = {}) {
42230
42550
  clearTimeout(timeout);
42231
42551
  }
42232
42552
  }
42553
+ function isRedirectStatus(status) {
42554
+ return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
42555
+ }
42556
+ function redirectKeepsBody(status) {
42557
+ return status === 307 || status === 308;
42558
+ }
42559
+ async function pinnedNativeRequest(target, addresses, method, headers, body, signal, tls) {
42560
+ const isHttps = target.protocol === "https:";
42561
+ if (!isHttps && target.protocol !== "http:") {
42562
+ throw new Error(`Webhook target uses unsupported protocol ${target.protocol}`);
42563
+ }
42564
+ const defaultPort = isHttps ? 443 : 80;
42565
+ const port = target.port ? Number(target.port) : defaultPort;
42566
+ const requestOptions = {
42567
+ hostname: target.hostname,
42568
+ port,
42569
+ path: `${target.pathname}${target.search}`,
42570
+ method,
42571
+ headers,
42572
+ ...tls?.ca ? { ca: tls.ca } : {},
42573
+ lookup: (hostname, _options, callback) => {
42574
+ const entries = addresses.map((address) => ({
42575
+ address,
42576
+ family: address.includes(":") ? 6 : 4
42577
+ }));
42578
+ callback(null, entries);
42579
+ }
42580
+ };
42581
+ return new Promise((resolve2, reject) => {
42582
+ const request = isHttps ? nodeHttpsRequest(requestOptions, onResponse) : nodeHttpRequest(requestOptions, onResponse);
42583
+ const onAbort = () => {
42584
+ const error = new Error("The operation was aborted.");
42585
+ error.name = "AbortError";
42586
+ request.destroy(error);
42587
+ };
42588
+ if (signal.aborted)
42589
+ onAbort();
42590
+ else
42591
+ signal.addEventListener("abort", onAbort, { once: true });
42592
+ request.on("error", reject);
42593
+ if (body !== undefined)
42594
+ request.write(body);
42595
+ request.end();
42596
+ function onResponse(response) {
42597
+ const chunks = [];
42598
+ response.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
42599
+ response.on("error", reject);
42600
+ response.on("end", () => {
42601
+ const headersRecord = {};
42602
+ for (const [name, value] of Object.entries(response.headers)) {
42603
+ if (typeof value === "string")
42604
+ headersRecord[name] = value;
42605
+ else if (Array.isArray(value))
42606
+ headersRecord[name] = value.join(", ");
42607
+ }
42608
+ resolve2(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
42609
+ });
42610
+ }
42611
+ });
42612
+ }
42613
+ async function dispatchValidatedWebhook(event, channel, input) {
42614
+ const { body, headers, startedAt, options } = input;
42615
+ const webhook = channel.webhook;
42616
+ if (!webhook)
42617
+ throw new Error(`Channel ${channel.id} has no webhook config`);
42618
+ const policy = options.webhookTargetPolicy ?? {};
42619
+ const maxRedirects = normalizeMaxRedirects(policy.maxRedirects);
42620
+ const controller = new AbortController;
42621
+ const timeout = setTimeout(() => controller.abort(), webhook.timeoutMs ?? 15000);
42622
+ try {
42623
+ let target = new URL(normalizeWebhookUrl(webhook.url));
42624
+ let requestHeaders = headers;
42625
+ let method = "POST";
42626
+ let requestBody = body;
42627
+ let redirectsFollowed = 0;
42628
+ for (;; ) {
42629
+ const resolved = await resolveWebhookTarget(target, policy).catch((error) => {
42630
+ throw new Error(`Webhook target rejected by SSRF guard: ${error.message}`);
42631
+ });
42632
+ const response = options.fetchImpl ? await options.fetchImpl(target, {
42633
+ method,
42634
+ headers: requestHeaders,
42635
+ body: requestBody,
42636
+ signal: controller.signal,
42637
+ redirect: "manual"
42638
+ }) : await pinnedNativeRequest(target, resolved.addresses, method, requestHeaders, requestBody, controller.signal, options.tls);
42639
+ const location = response.headers.get("location");
42640
+ if (isRedirectStatus(response.status) && location) {
42641
+ if (redirectsFollowed >= maxRedirects) {
42642
+ return failedAttempt(startedAt, `Webhook target exceeded ${maxRedirects} redirects`);
42643
+ }
42644
+ redirectsFollowed += 1;
42645
+ const next = new URL(location, target);
42646
+ target = next;
42647
+ if (!redirectKeepsBody(response.status)) {
42648
+ method = "GET";
42649
+ requestBody = undefined;
42650
+ requestHeaders = Object.fromEntries(Object.entries(requestHeaders).filter(([name]) => name.toLowerCase() !== "content-type" && name.toLowerCase() !== "content-length"));
42651
+ }
42652
+ continue;
42653
+ }
42654
+ const responseBody = truncate(await response.text());
42655
+ return {
42656
+ attempt: 1,
42657
+ status: response.ok ? "success" : "failed",
42658
+ startedAt,
42659
+ completedAt: now(),
42660
+ responseStatus: response.status,
42661
+ responseBody,
42662
+ error: response.ok ? undefined : `Webhook returned HTTP ${response.status}`
42663
+ };
42664
+ }
42665
+ } catch (error) {
42666
+ return {
42667
+ attempt: 1,
42668
+ status: "failed",
42669
+ startedAt,
42670
+ completedAt: now(),
42671
+ error: error instanceof Error ? error.message : String(error)
42672
+ };
42673
+ } finally {
42674
+ clearTimeout(timeout);
42675
+ }
42676
+ }
42233
42677
  function failedAttempt(startedAt, error) {
42234
42678
  return {
42235
42679
  attempt: 1,
@@ -42258,7 +42702,7 @@ async function dispatchCommand(event, channel) {
42258
42702
  HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
42259
42703
  HASNA_EVENT_JSON: eventJson
42260
42704
  };
42261
- return new Promise((resolve) => {
42705
+ return new Promise((resolve2) => {
42262
42706
  const child = spawn(channel.command.command, channel.command.args ?? [], {
42263
42707
  cwd: channel.command.cwd,
42264
42708
  env,
@@ -42276,7 +42720,7 @@ async function dispatchCommand(event, channel) {
42276
42720
  });
42277
42721
  child.on("error", (error) => {
42278
42722
  clearTimeout(timeout);
42279
- resolve({
42723
+ resolve2({
42280
42724
  attempt: 1,
42281
42725
  status: "failed",
42282
42726
  startedAt,
@@ -42289,7 +42733,7 @@ async function dispatchCommand(event, channel) {
42289
42733
  child.on("close", (code, signal) => {
42290
42734
  clearTimeout(timeout);
42291
42735
  const success = code === 0;
42292
- resolve({
42736
+ resolve2({
42293
42737
  attempt: 1,
42294
42738
  status: success ? "success" : "failed",
42295
42739
  startedAt,
@@ -42411,6 +42855,22 @@ function setPath(input, path, replacement) {
42411
42855
  if (last && last in cursor)
42412
42856
  cursor[last] = replacement;
42413
42857
  }
42858
+ var MAX_PACKAGE_BYTES = 1024 * 1024;
42859
+ var MAX_CREDENTIAL_FILE_BYTES = 64 * 1024;
42860
+ var INSPECT_CUSTOM = Symbol.for("nodejs.util.inspect.custom");
42861
+ var CREDENTIAL_SEAL = Symbol.for("hasna:contracts:sealedCredential");
42862
+ var AMBIENT_ENVIRONMENT = Symbol.for("hasna:contracts:ambientClientEnvironment");
42863
+ var requireSecretsSdk = createRequire(import.meta.url);
42864
+ var IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
42865
+ var AUTHORITY_OVERRIDE_HEADERS = new Set([
42866
+ "host",
42867
+ ":authority",
42868
+ "forwarded",
42869
+ "x-forwarded-host",
42870
+ "x-original-host"
42871
+ ]);
42872
+ var MAX_ENVELOPE_BYTES = 256 * 1024;
42873
+ var MAX_REQUEST_BYTES = MAX_ENVELOPE_BYTES * 2 + 8192;
42414
42874
  function createEvent(input) {
42415
42875
  return {
42416
42876
  id: input.id ?? randomUUID2(),
@@ -42439,7 +42899,9 @@ class EventsClient {
42439
42899
  this.transportOptions = {
42440
42900
  fetchImpl: options.fetchImpl,
42441
42901
  secretResolver: options.secretResolver,
42442
- now: options.now
42902
+ now: options.now,
42903
+ tls: options.tls,
42904
+ webhookTargetPolicy: options.webhookTargetPolicy
42443
42905
  };
42444
42906
  this.catalog = options.catalog ?? defaultEventTypeCatalog;
42445
42907
  this.validateCatalogTypes = options.validateCatalogTypes ?? false;
@@ -42726,6 +43188,13 @@ function parseMatcherExpression(value, label) {
42726
43188
  negated: false
42727
43189
  };
42728
43190
  }
43191
+ function webhookTargetPolicyFromEnv() {
43192
+ const value = process.env.HASNA_EVENTS_ALLOW_PRIVATE_WEBHOOK_TARGETS;
43193
+ if (!value)
43194
+ return;
43195
+ const hosts = value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
43196
+ return hosts.length > 0 ? { allowPrivateHosts: hosts } : undefined;
43197
+ }
42729
43198
  var DEFAULT_EVENT_LIST_LIMIT = 100;
42730
43199
  function parseJsonObject(value, fallback) {
42731
43200
  if (!value)
@@ -42751,7 +43220,7 @@ function parseHeaders(values) {
42751
43220
  function createClient(options) {
42752
43221
  if (options.createClient)
42753
43222
  return options.createClient();
42754
- return new EventsClient({ store: new JsonEventsStore(options.dataDir) });
43223
+ return new EventsClient({ store: new JsonEventsStore(options.dataDir), webhookTargetPolicy: webhookTargetPolicyFromEnv() });
42755
43224
  }
42756
43225
  function print(value, json, text) {
42757
43226
  if (json)
@@ -42832,6 +43301,8 @@ function registerChannelCommands(program, options) {
42832
43301
  metadata: parseJsonObject(actionOptions.metadata, {})
42833
43302
  }, { honorFilters: actionOptions.honorFilters });
42834
43303
  print(result, json, `${result.status}: ${result.channelId}`);
43304
+ if (result.status === "failed")
43305
+ process.exitCode = 1;
42835
43306
  } catch (error) {
42836
43307
  fail(error, json);
42837
43308
  }
@@ -42924,7 +43395,7 @@ function replaySummary(events, deliveries, nextCursor) {
42924
43395
  // src/cli/index.tsx
42925
43396
  import { render } from "ink";
42926
43397
 
42927
- // ../hooks0102-standalone-lock/node_modules/commander/esm.mjs
43398
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/esm.mjs
42928
43399
  var import__ = __toESM(require_commander(), 1);
42929
43400
  var {
42930
43401
  program,
@@ -42942,19 +43413,19 @@ var {
42942
43413
 
42943
43414
  // src/cli/index.tsx
42944
43415
  import chalk2 from "chalk";
42945
- import { existsSync as existsSync16, readFileSync as readFileSync20, rmSync as rmSync6 } from "fs";
42946
- import { join as join24, dirname as dirname22 } from "path";
43416
+ import { existsSync as existsSync18, readFileSync as readFileSync20, rmSync as rmSync6 } from "fs";
43417
+ import { join as join29, dirname as dirname22 } from "path";
42947
43418
  import { fileURLToPath as fileURLToPath6 } from "url";
42948
43419
 
42949
43420
  // src/cli/components/App.tsx
42950
43421
  import { useState as useState7 } from "react";
42951
43422
  import { Box as Box8, Text as Text10, useApp, useInput as useInput5 } from "ink";
42952
43423
 
42953
- // ../hooks0102-standalone-lock/node_modules/ink-select-input/build/Indicator.js
43424
+ // ../../node_modules/.bun/ink-select-input@6.2.0+fa875fef9f949ebd/node_modules/ink-select-input/build/Indicator.js
42954
43425
  import React from "react";
42955
43426
  import { Box, Text } from "ink";
42956
43427
 
42957
- // ../hooks0102-standalone-lock/node_modules/is-unicode-supported/index.js
43428
+ // ../../node_modules/.bun/is-unicode-supported@2.1.0/node_modules/is-unicode-supported/index.js
42958
43429
  import process2 from "process";
42959
43430
  function isUnicodeSupported() {
42960
43431
  const { env } = process2;
@@ -42965,7 +43436,7 @@ function isUnicodeSupported() {
42965
43436
  return Boolean(env.WT_SESSION) || Boolean(env.TERMINUS_SUBLIME) || env.ConEmuTask === "{cmd::Cmder}" || TERM_PROGRAM === "Terminus-Sublime" || TERM_PROGRAM === "vscode" || TERM === "xterm-256color" || TERM === "alacritty" || TERM === "rxvt-unicode" || TERM === "rxvt-unicode-256color" || env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
42966
43437
  }
42967
43438
 
42968
- // ../hooks0102-standalone-lock/node_modules/figures/index.js
43439
+ // ../../node_modules/.bun/figures@6.1.0/node_modules/figures/index.js
42969
43440
  var common = {
42970
43441
  circleQuestionMark: "(?)",
42971
43442
  questionMarkPrefix: "(?)",
@@ -43241,23 +43712,23 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
43241
43712
  var figures_default = figures;
43242
43713
  var replacements = Object.entries(specialMainSymbols);
43243
43714
 
43244
- // ../hooks0102-standalone-lock/node_modules/ink-select-input/build/Indicator.js
43715
+ // ../../node_modules/.bun/ink-select-input@6.2.0+fa875fef9f949ebd/node_modules/ink-select-input/build/Indicator.js
43245
43716
  function Indicator({ isSelected = false }) {
43246
43717
  return React.createElement(Box, { marginRight: 1 }, isSelected ? React.createElement(Text, { color: "blue" }, figures_default.pointer) : React.createElement(Text, null, " "));
43247
43718
  }
43248
43719
  var Indicator_default = Indicator;
43249
- // ../hooks0102-standalone-lock/node_modules/ink-select-input/build/Item.js
43720
+ // ../../node_modules/.bun/ink-select-input@6.2.0+fa875fef9f949ebd/node_modules/ink-select-input/build/Item.js
43250
43721
  import * as React2 from "react";
43251
43722
  import { Text as Text2 } from "ink";
43252
43723
  function Item({ isSelected = false, label }) {
43253
43724
  return React2.createElement(Text2, { color: isSelected ? "blue" : undefined }, label);
43254
43725
  }
43255
43726
  var Item_default = Item;
43256
- // ../hooks0102-standalone-lock/node_modules/ink-select-input/build/SelectInput.js
43727
+ // ../../node_modules/.bun/ink-select-input@6.2.0+fa875fef9f949ebd/node_modules/ink-select-input/build/SelectInput.js
43257
43728
  import { isDeepStrictEqual } from "util";
43258
43729
  import React3, { useState, useEffect, useRef, useCallback } from "react";
43259
43730
 
43260
- // ../hooks0102-standalone-lock/node_modules/to-rotated/index.js
43731
+ // ../../node_modules/.bun/to-rotated@1.0.0/node_modules/to-rotated/index.js
43261
43732
  function toRotated(array, steps) {
43262
43733
  if (!Array.isArray(array)) {
43263
43734
  throw new TypeError(`Expected an array, got \`${typeof array}\`.`);
@@ -43279,7 +43750,7 @@ function toRotated(array, steps) {
43279
43750
  ];
43280
43751
  }
43281
43752
 
43282
- // ../hooks0102-standalone-lock/node_modules/ink-select-input/build/SelectInput.js
43753
+ // ../../node_modules/.bun/ink-select-input@6.2.0+fa875fef9f949ebd/node_modules/ink-select-input/build/SelectInput.js
43283
43754
  import { Box as Box2, useInput } from "ink";
43284
43755
  function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicatorComponent = Indicator_default, itemComponent = Item_default, limit: customLimit, onSelect, onHighlight }) {
43285
43756
  const hasLimit = typeof customLimit === "number" && items.length > customLimit;
@@ -43575,7 +44046,7 @@ function HookSelect({
43575
44046
  import { useState as useState4, useEffect as useEffect3 } from "react";
43576
44047
  import { Box as Box6, Text as Text7, useInput as useInput4 } from "ink";
43577
44048
 
43578
- // ../hooks0102-standalone-lock/node_modules/ink-text-input/build/index.js
44049
+ // ../../node_modules/.bun/ink-text-input@6.0.0+fa875fef9f949ebd/node_modules/ink-text-input/build/index.js
43579
44050
  import React5, { useState as useState3, useEffect as useEffect2 } from "react";
43580
44051
  import { Text as Text6, useInput as useInput3 } from "ink";
43581
44052
  import chalk from "chalk";
@@ -43753,7 +44224,7 @@ function SearchView({
43753
44224
  import { useState as useState6, useEffect as useEffect5 } from "react";
43754
44225
  import { Box as Box7, Text as Text9 } from "ink";
43755
44226
 
43756
- // ../hooks0102-standalone-lock/node_modules/ink-spinner/build/index.js
44227
+ // ../../node_modules/.bun/ink-spinner@5.0.0+fa875fef9f949ebd/node_modules/ink-spinner/build/index.js
43757
44228
  var import_cli_spinners = __toESM(require_cli_spinners(), 1);
43758
44229
  import React7, { useState as useState5, useEffect as useEffect4 } from "react";
43759
44230
  import { Text as Text8 } from "ink";
@@ -44133,7 +44604,7 @@ init_transport2();
44133
44604
  init_db();
44134
44605
  import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
44135
44606
  var __dirname4 = dirname22(fileURLToPath6(import.meta.url));
44136
- var pkgPath = existsSync16(join24(__dirname4, "..", "package.json")) ? join24(__dirname4, "..", "package.json") : join24(__dirname4, "..", "..", "package.json");
44607
+ var pkgPath = existsSync18(join29(__dirname4, "..", "package.json")) ? join29(__dirname4, "..", "package.json") : join29(__dirname4, "..", "..", "package.json");
44137
44608
  var pkg2 = JSON.parse(readFileSync20(pkgPath, "utf-8"));
44138
44609
  var program3 = new Command;
44139
44610
  function resolveScope(options) {
@@ -44352,7 +44823,7 @@ program3.command("init").description("Register a new agent profile with a unique
44352
44823
  if (profile.name) {
44353
44824
  console.log(` ${chalk2.dim("Name:")} ${profile.name}`);
44354
44825
  }
44355
- console.log(` ${chalk2.dim("Profile:")} ${join24(getProfilesDir(), `${profile.agent_id}.json`)}`);
44826
+ console.log(` ${chalk2.dim("Profile:")} ${join29(getProfilesDir(), `${profile.agent_id}.json`)}`);
44356
44827
  console.log();
44357
44828
  console.log(chalk2.dim(" Install hooks with this profile:"));
44358
44829
  console.log(` hooks install gitguard --profile ${profile.agent_id}`);
@@ -44376,7 +44847,7 @@ program3.command("run").argument("<hook>", "Hook to run").option("--profile <id>
44376
44847
  process.exit(1);
44377
44848
  }
44378
44849
  const hookScript = resolveScriptPath2(hook);
44379
- if (!hookScript || !existsSync16(hookScript)) {
44850
+ if (!hookScript || !existsSync18(hookScript)) {
44380
44851
  console.error(JSON.stringify({ error: `Hook script not found: ${hookScript ?? hook}` }));
44381
44852
  process.exit(1);
44382
44853
  }
@@ -44974,7 +45445,7 @@ program3.command("doctor").option("-g, --global", "Check global settings", false
44974
45445
  });
44975
45446
  }
44976
45447
  const staleNames = new Set(stale.map((finding) => finding.hook));
44977
- const settingsExist = existsSync16(settingsPath);
45448
+ const settingsExist = existsSync18(settingsPath);
44978
45449
  if (!settingsExist) {
44979
45450
  issues.push({ hook: "(settings)", issue: `${settingsPath} not found`, severity: "warning" });
44980
45451
  }
@@ -44993,7 +45464,7 @@ program3.command("doctor").option("-g, --global", "Check global settings", false
44993
45464
  const meta3 = custom2 ? resolveHookMeta(name) : getHook(name);
44994
45465
  let hookHealthy = true;
44995
45466
  if (custom2) {
44996
- if (!existsSync16(custom2.scriptPath)) {
45467
+ if (!existsSync18(custom2.scriptPath)) {
44997
45468
  issues.push({ hook: name, issue: `Custom hook script missing: ${custom2.scriptPath}`, severity: "error" });
44998
45469
  hookHealthy = false;
44999
45470
  }
@@ -45004,8 +45475,8 @@ program3.command("doctor").option("-g, --global", "Check global settings", false
45004
45475
  continue;
45005
45476
  }
45006
45477
  const hookDir = getHookPath(name);
45007
- const hookScript = join24(hookDir, "src", "hook.ts");
45008
- if (!existsSync16(hookScript)) {
45478
+ const hookScript = join29(hookDir, "src", "hook.ts");
45479
+ if (!existsSync18(hookScript)) {
45009
45480
  issues.push({ hook: name, issue: "Missing src/hook.ts in package", severity: "error" });
45010
45481
  hookHealthy = false;
45011
45482
  }
@@ -45215,9 +45686,9 @@ program3.command("docs").argument("[hook]", "Hook name (shows general docs if om
45215
45686
  return;
45216
45687
  }
45217
45688
  const hookPath = getHookPath(hook);
45218
- const readmePath = join24(hookPath, "README.md");
45689
+ const readmePath = join29(hookPath, "README.md");
45219
45690
  let readme = "";
45220
- if (existsSync16(readmePath)) {
45691
+ if (existsSync18(readmePath)) {
45221
45692
  readme = readFileSync20(readmePath, "utf-8");
45222
45693
  }
45223
45694
  if (options.json) {