@hasna/hooks 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/hooks-mcp.js +2 -2
- package/bin/index.js +120 -586
- package/bin/native-safety-entry.js +7 -2
- package/bin/serve.js +9 -9
- package/dist/index.js +12 -12
- package/dist/sdk/index.js +1 -1
- package/hooks/hook-trash-guard/src/binary.ts +6 -2
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -2516,7 +2516,7 @@ var init_codex_settings = __esm(() => {
|
|
|
2516
2516
|
snapshots = new WeakMap;
|
|
2517
2517
|
});
|
|
2518
2518
|
|
|
2519
|
-
//
|
|
2519
|
+
// node_modules/@hasna/skills/dist/index.js
|
|
2520
2520
|
import { existsSync as existsSync10 } from "fs";
|
|
2521
2521
|
import { homedir as homedir6 } from "os";
|
|
2522
2522
|
import { join as join10, resolve as resolve4 } from "path";
|
|
@@ -35489,7 +35489,7 @@ var init_codex_safety_trust = __esm(() => {
|
|
|
35489
35489
|
};
|
|
35490
35490
|
});
|
|
35491
35491
|
|
|
35492
|
-
//
|
|
35492
|
+
// node_modules/commander/lib/error.js
|
|
35493
35493
|
var require_error = __commonJS((exports) => {
|
|
35494
35494
|
class CommanderError extends Error {
|
|
35495
35495
|
constructor(exitCode, code2, message) {
|
|
@@ -35513,7 +35513,7 @@ var require_error = __commonJS((exports) => {
|
|
|
35513
35513
|
exports.InvalidArgumentError = InvalidArgumentError;
|
|
35514
35514
|
});
|
|
35515
35515
|
|
|
35516
|
-
//
|
|
35516
|
+
// node_modules/commander/lib/argument.js
|
|
35517
35517
|
var require_argument = __commonJS((exports) => {
|
|
35518
35518
|
var { InvalidArgumentError } = require_error();
|
|
35519
35519
|
|
|
@@ -35592,7 +35592,7 @@ var require_argument = __commonJS((exports) => {
|
|
|
35592
35592
|
exports.humanReadableArgName = humanReadableArgName;
|
|
35593
35593
|
});
|
|
35594
35594
|
|
|
35595
|
-
//
|
|
35595
|
+
// node_modules/commander/lib/help.js
|
|
35596
35596
|
var require_help = __commonJS((exports) => {
|
|
35597
35597
|
var { humanReadableArgName } = require_argument();
|
|
35598
35598
|
|
|
@@ -35841,7 +35841,7 @@ var require_help = __commonJS((exports) => {
|
|
|
35841
35841
|
exports.Help = Help;
|
|
35842
35842
|
});
|
|
35843
35843
|
|
|
35844
|
-
//
|
|
35844
|
+
// node_modules/commander/lib/option.js
|
|
35845
35845
|
var require_option = __commonJS((exports) => {
|
|
35846
35846
|
var { InvalidArgumentError } = require_error();
|
|
35847
35847
|
|
|
@@ -35992,7 +35992,7 @@ var require_option = __commonJS((exports) => {
|
|
|
35992
35992
|
exports.DualOptions = DualOptions;
|
|
35993
35993
|
});
|
|
35994
35994
|
|
|
35995
|
-
//
|
|
35995
|
+
// node_modules/commander/lib/suggestSimilar.js
|
|
35996
35996
|
var require_suggestSimilar = __commonJS((exports) => {
|
|
35997
35997
|
var maxDistance = 3;
|
|
35998
35998
|
function editDistance(a, b) {
|
|
@@ -36065,7 +36065,7 @@ var require_suggestSimilar = __commonJS((exports) => {
|
|
|
36065
36065
|
exports.suggestSimilar = suggestSimilar;
|
|
36066
36066
|
});
|
|
36067
36067
|
|
|
36068
|
-
//
|
|
36068
|
+
// node_modules/commander/lib/command.js
|
|
36069
36069
|
var require_command = __commonJS((exports) => {
|
|
36070
36070
|
var EventEmitter = __require("events").EventEmitter;
|
|
36071
36071
|
var childProcess = __require("child_process");
|
|
@@ -37308,7 +37308,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
37308
37308
|
exports.Command = Command;
|
|
37309
37309
|
});
|
|
37310
37310
|
|
|
37311
|
-
//
|
|
37311
|
+
// node_modules/commander/index.js
|
|
37312
37312
|
var require_commander = __commonJS((exports) => {
|
|
37313
37313
|
var { Argument } = require_argument();
|
|
37314
37314
|
var { Command } = require_command();
|
|
@@ -37328,7 +37328,7 @@ var require_commander = __commonJS((exports) => {
|
|
|
37328
37328
|
exports.InvalidOptionArgumentError = InvalidArgumentError;
|
|
37329
37329
|
});
|
|
37330
37330
|
|
|
37331
|
-
//
|
|
37331
|
+
// node_modules/cli-spinners/spinners.json
|
|
37332
37332
|
var require_spinners = __commonJS((exports, module) => {
|
|
37333
37333
|
module.exports = {
|
|
37334
37334
|
dots: {
|
|
@@ -38954,7 +38954,7 @@ var require_spinners = __commonJS((exports, module) => {
|
|
|
38954
38954
|
};
|
|
38955
38955
|
});
|
|
38956
38956
|
|
|
38957
|
-
//
|
|
38957
|
+
// node_modules/cli-spinners/index.js
|
|
38958
38958
|
var require_cli_spinners = __commonJS((exports, module) => {
|
|
38959
38959
|
var spinners = Object.assign({}, require_spinners());
|
|
38960
38960
|
var spinnersList = Object.keys(spinners);
|
|
@@ -39035,10 +39035,10 @@ var init_redact = __esm(() => {
|
|
|
39035
39035
|
|
|
39036
39036
|
// src/lib/profiles.ts
|
|
39037
39037
|
import { existsSync as existsSync14, mkdirSync as mkdirSync13, readFileSync as readFileSync19, writeFileSync as writeFileSync12, readdirSync as readdirSync8, rmSync, cpSync as cpSync2 } from "fs";
|
|
39038
|
-
import { join as
|
|
39038
|
+
import { join as join27 } from "path";
|
|
39039
39039
|
function getProfilesDir() {
|
|
39040
|
-
const newDir =
|
|
39041
|
-
const oldDir =
|
|
39040
|
+
const newDir = join27(getEffectiveDataRoot(), "profiles");
|
|
39041
|
+
const oldDir = join27(getHomeDir(), ".hooks", "profiles");
|
|
39042
39042
|
if (!existsSync14(newDir) && existsSync14(oldDir)) {
|
|
39043
39043
|
mkdirSync13(newDir, { recursive: true });
|
|
39044
39044
|
cpSync2(oldDir, newDir, { recursive: true });
|
|
@@ -39052,7 +39052,7 @@ function ensureProfilesDir() {
|
|
|
39052
39052
|
}
|
|
39053
39053
|
}
|
|
39054
39054
|
function profilePath(id) {
|
|
39055
|
-
return
|
|
39055
|
+
return join27(getProfilesDir(), `${id}.json`);
|
|
39056
39056
|
}
|
|
39057
39057
|
function shortUuid() {
|
|
39058
39058
|
return crypto.randomUUID().slice(0, 8);
|
|
@@ -39094,7 +39094,7 @@ function listProfiles() {
|
|
|
39094
39094
|
const profiles = [];
|
|
39095
39095
|
for (const file2 of files) {
|
|
39096
39096
|
try {
|
|
39097
|
-
const content = readFileSync19(
|
|
39097
|
+
const content = readFileSync19(join27(dir, file2), "utf-8");
|
|
39098
39098
|
profiles.push(JSON.parse(content));
|
|
39099
39099
|
} catch {}
|
|
39100
39100
|
}
|
|
@@ -39138,18 +39138,18 @@ var init_profiles = __esm(() => {
|
|
|
39138
39138
|
init_app_home();
|
|
39139
39139
|
});
|
|
39140
39140
|
|
|
39141
|
-
//
|
|
39142
|
-
import { isIP
|
|
39141
|
+
// node_modules/@hasna/contracts/dist/client/transport.js
|
|
39142
|
+
import { isIP } from "net";
|
|
39143
39143
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
39144
39144
|
import { closeSync as closeSync22, fstatSync as fstatSync22, openSync as openSync22, readFileSync as readFileSync22 } from "fs";
|
|
39145
39145
|
import { O_NOFOLLOW as O_NOFOLLOW2, O_NONBLOCK as O_NONBLOCK2, O_RDONLY as O_RDONLY2 } from "constants";
|
|
39146
39146
|
import { hostname as osHostname } from "os";
|
|
39147
39147
|
import { isAbsolute as isAbsolute21, join as join28 } from "path";
|
|
39148
|
-
import { createRequire as
|
|
39148
|
+
import { createRequire as createRequire2 } from "module";
|
|
39149
39149
|
import { fileURLToPath as fileURLToPath22 } from "url";
|
|
39150
39150
|
import { closeSync as closeSync20, fstatSync as fstatSync19, lstatSync as lstatSync24, openSync as openSync20, readFileSync as readFileSync20, realpathSync as realpathSync12, statSync as statSync2 } from "fs";
|
|
39151
39151
|
import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
|
|
39152
|
-
import { basename as basename9, dirname as dirname22, join as
|
|
39152
|
+
import { basename as basename9, dirname as dirname22, join as join29, relative as relative5, sep as sep6 } from "path";
|
|
39153
39153
|
import { fileURLToPath as fileURLToPath3, pathToFileURL } from "url";
|
|
39154
39154
|
function envToken2(name) {
|
|
39155
39155
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -39224,11 +39224,11 @@ function o(e2, r2, t2) {
|
|
|
39224
39224
|
}
|
|
39225
39225
|
function entryPoint(directory2) {
|
|
39226
39226
|
const root = realpathSync12(directory2);
|
|
39227
|
-
const fd = openSync20(
|
|
39227
|
+
const fd = openSync20(join29(root, "package.json"), O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
|
|
39228
39228
|
let pkg;
|
|
39229
39229
|
try {
|
|
39230
39230
|
const stat2 = fstatSync19(fd);
|
|
39231
|
-
if (!stat2.isFile() || stat2.size >
|
|
39231
|
+
if (!stat2.isFile() || stat2.size > MAX_PACKAGE_BYTES2)
|
|
39232
39232
|
throw new Error("Invalid Secrets package metadata");
|
|
39233
39233
|
pkg = JSON.parse(readFileSync20(fd, "utf8"));
|
|
39234
39234
|
} finally {
|
|
@@ -39244,7 +39244,7 @@ function entryPoint(directory2) {
|
|
|
39244
39244
|
if (/[\\%?#\0]/.test(target) || parts.some((part) => !part || part === "." || part === ".." || part === "node_modules")) {
|
|
39245
39245
|
throw new Error("Invalid Secrets import export");
|
|
39246
39246
|
}
|
|
39247
|
-
const file2 = realpathSync12(
|
|
39247
|
+
const file2 = realpathSync12(join29(root, ...parts));
|
|
39248
39248
|
const within = relative5(root, file2);
|
|
39249
39249
|
if (!within || within === ".." || within.startsWith(`..${sep6}`) || !statSync2(file2).isFile()) {
|
|
39250
39250
|
throw new Error("Secrets import export escapes its package or is not a file");
|
|
@@ -39255,7 +39255,7 @@ function resolveInstalledSecrets(parentUrl) {
|
|
|
39255
39255
|
let directory2 = dirname22(fileURLToPath3(parentUrl));
|
|
39256
39256
|
for (;; ) {
|
|
39257
39257
|
if (basename9(directory2) !== "node_modules") {
|
|
39258
|
-
const candidate =
|
|
39258
|
+
const candidate = join29(directory2, "node_modules", PACKAGE);
|
|
39259
39259
|
let absent = false;
|
|
39260
39260
|
try {
|
|
39261
39261
|
lstatSync24(candidate);
|
|
@@ -39375,7 +39375,7 @@ function readAppConfigFile(path) {
|
|
|
39375
39375
|
const uid2 = process.getuid?.() ?? process.geteuid?.();
|
|
39376
39376
|
if (uid2 !== undefined && before.uid !== uid2)
|
|
39377
39377
|
unsafe("the file is not owned by the current user");
|
|
39378
|
-
if (before.size >
|
|
39378
|
+
if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
|
|
39379
39379
|
unsafe("the file exceeds the size limit");
|
|
39380
39380
|
const bytes = readFileSync22(fd);
|
|
39381
39381
|
const after = fstatSync22(fd);
|
|
@@ -39467,13 +39467,13 @@ function sealCredential(fields) {
|
|
|
39467
39467
|
configurable: false
|
|
39468
39468
|
});
|
|
39469
39469
|
}
|
|
39470
|
-
Object.defineProperty(sealed,
|
|
39470
|
+
Object.defineProperty(sealed, INSPECT_CUSTOM2, {
|
|
39471
39471
|
value: () => ({ ...visible, apiKey: "[redacted]" }),
|
|
39472
39472
|
enumerable: false,
|
|
39473
39473
|
writable: false,
|
|
39474
39474
|
configurable: false
|
|
39475
39475
|
});
|
|
39476
|
-
Object.defineProperty(sealed,
|
|
39476
|
+
Object.defineProperty(sealed, CREDENTIAL_SEAL2, {
|
|
39477
39477
|
value: true,
|
|
39478
39478
|
enumerable: false,
|
|
39479
39479
|
writable: false,
|
|
@@ -39504,7 +39504,7 @@ function firstEnvValue(env, keys2) {
|
|
|
39504
39504
|
return null;
|
|
39505
39505
|
}
|
|
39506
39506
|
function isAmbientEnvironment(env) {
|
|
39507
|
-
return env === process.env || env[
|
|
39507
|
+
return env === process.env || env[AMBIENT_ENVIRONMENT2] === true;
|
|
39508
39508
|
}
|
|
39509
39509
|
function defaultKeychainRunner(argv) {
|
|
39510
39510
|
const result = spawnSync2(KEYCHAIN_SECURITY_BIN, [...argv], {
|
|
@@ -39598,7 +39598,7 @@ function snapshotClientEnvironment(name, env) {
|
|
|
39598
39598
|
snapshot2[key] = descriptor.value;
|
|
39599
39599
|
}
|
|
39600
39600
|
if (ambient) {
|
|
39601
|
-
Object.defineProperty(snapshot2,
|
|
39601
|
+
Object.defineProperty(snapshot2, AMBIENT_ENVIRONMENT2, {
|
|
39602
39602
|
value: true,
|
|
39603
39603
|
enumerable: false,
|
|
39604
39604
|
writable: false,
|
|
@@ -39771,7 +39771,7 @@ async function completePointerCredential(name, pointerResolution, env = process.
|
|
|
39771
39771
|
let secretsSdk;
|
|
39772
39772
|
try {
|
|
39773
39773
|
const sdkUrl = resolveInstalledSecrets(import.meta.url);
|
|
39774
|
-
secretsSdk =
|
|
39774
|
+
secretsSdk = requireSecretsSdk2(fileURLToPath22(sdkUrl));
|
|
39775
39775
|
} catch {
|
|
39776
39776
|
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]);
|
|
39777
39777
|
}
|
|
@@ -39855,7 +39855,7 @@ function canonicalAuthorityHostname(authority) {
|
|
|
39855
39855
|
}
|
|
39856
39856
|
assertCanonicalPort(portSuffix.slice(1));
|
|
39857
39857
|
}
|
|
39858
|
-
if (
|
|
39858
|
+
if (isIP(rawHostname.slice(1, -1)) !== 6) {
|
|
39859
39859
|
throw new Error("API URL authority must contain a canonical IPv6 literal.");
|
|
39860
39860
|
}
|
|
39861
39861
|
} else {
|
|
@@ -39871,7 +39871,7 @@ function canonicalAuthorityHostname(authority) {
|
|
|
39871
39871
|
} else {
|
|
39872
39872
|
rawHostname = authority;
|
|
39873
39873
|
}
|
|
39874
|
-
const ipVersion =
|
|
39874
|
+
const ipVersion = isIP(rawHostname);
|
|
39875
39875
|
const numericAddressParts = rawHostname.split(".");
|
|
39876
39876
|
const looksLikeNonCanonicalIpv4 = numericAddressParts.every((part) => /^(?:0x[0-9a-f]+|[0-9]+)$/i.test(part));
|
|
39877
39877
|
if (ipVersion !== 4 && looksLikeNonCanonicalIpv4 || ipVersion !== 4 && !isValidDnsDomain(rawHostname.toLowerCase())) {
|
|
@@ -40007,9 +40007,9 @@ function credentialDiskSourcesForMessage(name, env) {
|
|
|
40007
40007
|
const paths = credentialDiskSources(name, env);
|
|
40008
40008
|
return paths.length > 0 ? paths.join(" or ") : "<no HOME or HASNA_HOME set in this environment, so no credential file was consulted>";
|
|
40009
40009
|
}
|
|
40010
|
-
var CREDENTIAL_PROFILE_ENV_KEY = "HASNA_PROFILE", PACKAGE = "@hasna/secrets",
|
|
40010
|
+
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;
|
|
40011
40011
|
var init_transport = __esm(() => {
|
|
40012
|
-
|
|
40012
|
+
MAX_PACKAGE_BYTES2 = 1024 * 1024;
|
|
40013
40013
|
CredentialResolutionError = class CredentialResolutionError extends Error {
|
|
40014
40014
|
appName;
|
|
40015
40015
|
attempted;
|
|
@@ -40028,16 +40028,16 @@ var init_transport = __esm(() => {
|
|
|
40028
40028
|
this.path = path;
|
|
40029
40029
|
}
|
|
40030
40030
|
};
|
|
40031
|
-
|
|
40031
|
+
MAX_CREDENTIAL_FILE_BYTES2 = 64 * 1024;
|
|
40032
40032
|
SAFE_APP_SLUG = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
40033
40033
|
SAFE_PROFILE = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
40034
40034
|
ILLEGAL_IN_HEADER_VALUE = /[^\t\x20-\x7e]/;
|
|
40035
40035
|
VAULT_POINTER_SHAPE = /^[a-z0-9][a-z0-9-]*(?:\/[a-z0-9][a-z0-9-_.]*){2,}$/;
|
|
40036
40036
|
CREDENTIAL_SHAPED_KEY = /(?:^|_)(?:API_KEY|KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)(?:_|$)/;
|
|
40037
|
-
|
|
40038
|
-
|
|
40039
|
-
|
|
40040
|
-
|
|
40037
|
+
INSPECT_CUSTOM2 = Symbol.for("nodejs.util.inspect.custom");
|
|
40038
|
+
CREDENTIAL_SEAL2 = Symbol.for("hasna:contracts:sealedCredential");
|
|
40039
|
+
AMBIENT_ENVIRONMENT2 = Symbol.for("hasna:contracts:ambientClientEnvironment");
|
|
40040
|
+
requireSecretsSdk2 = createRequire2(import.meta.url);
|
|
40041
40041
|
ASCII_CONTROL_PATTERN = /[\u0000-\u001f\u007f]/;
|
|
40042
40042
|
DNS_LABEL_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
40043
40043
|
ClientTransportConfigurationError = class ClientTransportConfigurationError extends Error {
|
|
@@ -40050,8 +40050,8 @@ var init_transport = __esm(() => {
|
|
|
40050
40050
|
this.sources = Object.freeze([...sources]);
|
|
40051
40051
|
}
|
|
40052
40052
|
};
|
|
40053
|
-
|
|
40054
|
-
|
|
40053
|
+
IDEMPOTENT_METHODS2 = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
40054
|
+
AUTHORITY_OVERRIDE_HEADERS2 = new Set([
|
|
40055
40055
|
"host",
|
|
40056
40056
|
":authority",
|
|
40057
40057
|
"forwarded",
|
|
@@ -40562,7 +40562,7 @@ __export(exports_run, {
|
|
|
40562
40562
|
});
|
|
40563
40563
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
40564
40564
|
import { rmSync as rmSync2, writeFileSync as writeFileSync13 } from "fs";
|
|
40565
|
-
import { basename as basename11, dirname as dirname24, isAbsolute as isAbsolute25, join as
|
|
40565
|
+
import { basename as basename11, dirname as dirname24, isAbsolute as isAbsolute25, join as join30 } from "path";
|
|
40566
40566
|
function extensionOf(scriptPath) {
|
|
40567
40567
|
const base = basename11(scriptPath);
|
|
40568
40568
|
const dot = base.lastIndexOf(".");
|
|
@@ -40633,7 +40633,7 @@ async function readPipeWithDeadline(stream, deadlineMs) {
|
|
|
40633
40633
|
async function executeVerifiedScript(options) {
|
|
40634
40634
|
const scriptDir = dirname24(options.scriptPath);
|
|
40635
40635
|
const interpreter = interpreterFor(options.name, options.scriptPath, options.content);
|
|
40636
|
-
const tempPath =
|
|
40636
|
+
const tempPath = join30(scriptDir, `.hooks-verified-${randomBytes2(12).toString("hex")}.${interpreter.tempExt}`);
|
|
40637
40637
|
let proc = null;
|
|
40638
40638
|
let timedOut = false;
|
|
40639
40639
|
const timeoutTimer = options.timeout ? setTimeout(() => {
|
|
@@ -40725,10 +40725,10 @@ __export(exports_custom_install, {
|
|
|
40725
40725
|
ensureCustomDir: () => ensureCustomDir
|
|
40726
40726
|
});
|
|
40727
40727
|
import { existsSync as existsSync16, mkdirSync as mkdirSync14, mkdtempSync, readFileSync as readFileSync21, rmSync as rmSync4 } from "fs";
|
|
40728
|
-
import { join as
|
|
40728
|
+
import { join as join31 } from "path";
|
|
40729
40729
|
import { tmpdir as tmpdir2 } from "os";
|
|
40730
40730
|
function manifestAt(dir) {
|
|
40731
|
-
const path =
|
|
40731
|
+
const path = join31(dir, "manifest.json");
|
|
40732
40732
|
if (!existsSync16(path))
|
|
40733
40733
|
return;
|
|
40734
40734
|
try {
|
|
@@ -40751,8 +40751,8 @@ function writeFromManifest(manifest, srcDir, source, kind) {
|
|
|
40751
40751
|
return { name, version: manifest.version, kind, source, dir, scriptPath };
|
|
40752
40752
|
}
|
|
40753
40753
|
async function cloneToTemp(gitUrl) {
|
|
40754
|
-
const tmp = mkdtempSync(
|
|
40755
|
-
const proc = Bun.spawn(["git", "clone", "--depth", "1", "--quiet", gitUrl,
|
|
40754
|
+
const tmp = mkdtempSync(join31(tmpdir2(), "hooks-install-"));
|
|
40755
|
+
const proc = Bun.spawn(["git", "clone", "--depth", "1", "--quiet", gitUrl, join31(tmp, "repo")], {
|
|
40756
40756
|
stdout: "pipe",
|
|
40757
40757
|
stderr: "pipe"
|
|
40758
40758
|
});
|
|
@@ -40765,7 +40765,7 @@ async function cloneToTemp(gitUrl) {
|
|
|
40765
40765
|
rmSync4(tmp, { recursive: true, force: true });
|
|
40766
40766
|
throw new Error(`git clone failed (${exitCode}): ${stderr.trim()}`);
|
|
40767
40767
|
}
|
|
40768
|
-
return
|
|
40768
|
+
return join31(tmp, "repo");
|
|
40769
40769
|
}
|
|
40770
40770
|
function isGitUrl(value) {
|
|
40771
40771
|
return value.startsWith("git@") || value.startsWith("ssh://") || value.startsWith("file://") || value.endsWith(".git");
|
|
@@ -42004,11 +42004,11 @@ __export(exports_serve, {
|
|
|
42004
42004
|
DEFAULT_SERVE_PORT: () => DEFAULT_SERVE_PORT
|
|
42005
42005
|
});
|
|
42006
42006
|
import { readFileSync as readFileSync25 } from "fs";
|
|
42007
|
-
import { dirname as dirname25, join as
|
|
42007
|
+
import { dirname as dirname25, join as join32 } from "path";
|
|
42008
42008
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
42009
42009
|
function packageVersion() {
|
|
42010
42010
|
try {
|
|
42011
|
-
const pkgPath =
|
|
42011
|
+
const pkgPath = join32(dirname25(fileURLToPath4(import.meta.url)), "..", "package.json");
|
|
42012
42012
|
return JSON.parse(readFileSync25(pkgPath, "utf-8")).version || "0.0.0";
|
|
42013
42013
|
} catch {
|
|
42014
42014
|
return "0.0.0";
|
|
@@ -42310,7 +42310,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
42310
42310
|
import { z as z3 } from "zod";
|
|
42311
42311
|
import { createServer } from "http";
|
|
42312
42312
|
import { existsSync as existsSync17, readFileSync as readFileSync26 } from "fs";
|
|
42313
|
-
import { join as
|
|
42313
|
+
import { join as join33, dirname as dirname26 } from "path";
|
|
42314
42314
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
42315
42315
|
async function runVerifiedHook(name, stdin, timeoutMs) {
|
|
42316
42316
|
const { resolveHook: resolveHook2, resolveScriptPath: resolveScriptPath2 } = await Promise.resolve().then(() => (init_resolve(), exports_resolve));
|
|
@@ -42544,7 +42544,7 @@ function createHooksServer() {
|
|
|
42544
42544
|
continue;
|
|
42545
42545
|
}
|
|
42546
42546
|
const hookDir = getHookPath(name);
|
|
42547
|
-
if (!existsSync17(
|
|
42547
|
+
if (!existsSync17(join33(hookDir, "src", "hook.ts"))) {
|
|
42548
42548
|
issues.push({ hook: name, issue: "Missing src/hook.ts in package", severity: "error" });
|
|
42549
42549
|
hookHealthy = false;
|
|
42550
42550
|
}
|
|
@@ -42588,7 +42588,7 @@ function createHooksServer() {
|
|
|
42588
42588
|
return { content: [{ type: "text", text: JSON.stringify({ error: `Hook '${name}' not found` }) }] };
|
|
42589
42589
|
}
|
|
42590
42590
|
const hookPath = getHookPath(name);
|
|
42591
|
-
const readmePath =
|
|
42591
|
+
const readmePath = join33(hookPath, "README.md");
|
|
42592
42592
|
let readme = "";
|
|
42593
42593
|
if (existsSync17(readmePath)) {
|
|
42594
42594
|
readme = readFileSync26(readmePath, "utf-8");
|
|
@@ -43318,7 +43318,7 @@ var init_server = __esm(() => {
|
|
|
43318
43318
|
pkg = { name: "@hasna/hooks", version: "0.0.0" };
|
|
43319
43319
|
try {
|
|
43320
43320
|
for (const rel of ["../../package.json", "../package.json", "../../../package.json"]) {
|
|
43321
|
-
const p =
|
|
43321
|
+
const p = join33(__dirname3, rel);
|
|
43322
43322
|
if (existsSync17(p)) {
|
|
43323
43323
|
pkg = JSON.parse(readFileSync26(p, "utf-8"));
|
|
43324
43324
|
break;
|
|
@@ -43397,7 +43397,7 @@ __export(exports_native_readiness_binding, {
|
|
|
43397
43397
|
import { createHash as createHash25, randomUUID as randomUUID8 } from "crypto";
|
|
43398
43398
|
import { closeSync as closeSync21, constants as constants19, fsyncSync as fsyncSync8, lstatSync as lstatSync25, mkdirSync as mkdirSync15, openSync as openSync21, realpathSync as realpathSync14, writeFileSync as writeFileSync14 } from "fs";
|
|
43399
43399
|
import { homedir as homedir15 } from "os";
|
|
43400
|
-
import { dirname as dirname27, join as
|
|
43400
|
+
import { dirname as dirname27, join as join34 } from "path";
|
|
43401
43401
|
function need10(value, code2) {
|
|
43402
43402
|
if (!value)
|
|
43403
43403
|
throw new ReadinessBindingError(code2);
|
|
@@ -43455,7 +43455,7 @@ async function registerTrashReadinessBinding(input2, expectedSHA256) {
|
|
|
43455
43455
|
const operationId = randomUUID8();
|
|
43456
43456
|
let directory2 = home;
|
|
43457
43457
|
for (const part of [".hasna", "hooks", "native", "trash-readiness"]) {
|
|
43458
|
-
directory2 =
|
|
43458
|
+
directory2 = join34(directory2, part);
|
|
43459
43459
|
try {
|
|
43460
43460
|
mkdirSync15(directory2, { mode: 448 });
|
|
43461
43461
|
syncDirectory4(dirname27(directory2));
|
|
@@ -43465,12 +43465,12 @@ async function registerTrashReadinessBinding(input2, expectedSHA256) {
|
|
|
43465
43465
|
}
|
|
43466
43466
|
safeDirectory4(directory2);
|
|
43467
43467
|
}
|
|
43468
|
-
const operation =
|
|
43468
|
+
const operation = join34(directory2, operationId);
|
|
43469
43469
|
mkdirSync15(operation, { mode: 448 });
|
|
43470
43470
|
syncDirectory4(directory2);
|
|
43471
43471
|
if (before)
|
|
43472
|
-
exclusive3(
|
|
43473
|
-
exclusive3(
|
|
43472
|
+
exclusive3(join34(operation, "binding.before"), before.raw);
|
|
43473
|
+
exclusive3(join34(operation, "intent.json"), JSON.stringify({ operationId, target, expectedSHA256, desiredSHA256: digest4 }) + `
|
|
43474
43474
|
`);
|
|
43475
43475
|
try {
|
|
43476
43476
|
need10((read4()?.sha256 ?? "absent") === expectedSHA256, "binding_changed");
|
|
@@ -43484,7 +43484,7 @@ async function registerTrashReadinessBinding(input2, expectedSHA256) {
|
|
|
43484
43484
|
syncDirectory4(directory2);
|
|
43485
43485
|
need10(read4()?.sha256 === digest4, "binding_changed");
|
|
43486
43486
|
const receipt = { ok: true, changed: true, operationId, path: target, sha256: digest4, configurationReady: true, nativeAdoptionVerified: false };
|
|
43487
|
-
exclusive3(
|
|
43487
|
+
exclusive3(join34(operation, "receipt.json"), JSON.stringify(receipt) + `
|
|
43488
43488
|
`);
|
|
43489
43489
|
return receipt;
|
|
43490
43490
|
} catch {
|
|
@@ -43508,7 +43508,7 @@ var init_native_readiness_binding = __esm(() => {
|
|
|
43508
43508
|
|
|
43509
43509
|
// src/cli/index.tsx
|
|
43510
43510
|
init_native_safety_registration();
|
|
43511
|
-
import { resolve as
|
|
43511
|
+
import { resolve as resolve21 } from "path";
|
|
43512
43512
|
|
|
43513
43513
|
// src/lib/claude-safety-check.ts
|
|
43514
43514
|
init_native_safety();
|
|
@@ -43627,25 +43627,16 @@ async function verifyClaudeSafetyConfiguration(options = {}, dependencies = {})
|
|
|
43627
43627
|
// src/cli/index.tsx
|
|
43628
43628
|
init_codex_safety_trust();
|
|
43629
43629
|
|
|
43630
|
-
//
|
|
43630
|
+
// node_modules/@hasna/events/dist/commander.js
|
|
43631
43631
|
import { chmod, mkdir, readFile as readFile2, rename, writeFile } from "fs/promises";
|
|
43632
43632
|
import { Buffer as Buffer2 } from "buffer";
|
|
43633
|
-
import { existsSync as existsSync22 } from "fs";
|
|
43634
|
-
import { join as join22 } from "path";
|
|
43635
43633
|
import { existsSync as existsSync13 } from "fs";
|
|
43636
43634
|
import { homedir as homedir13 } from "os";
|
|
43637
|
-
import { join as join20
|
|
43638
|
-
import { homedir as pathsResolverHomedir3 } from "os";
|
|
43639
|
-
import { join as pathsResolverJoin3 } from "path";
|
|
43635
|
+
import { join as join20 } from "path";
|
|
43640
43636
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
43641
|
-
import { lookup as dnsLookup } from "dns/promises";
|
|
43642
|
-
import { isIP } from "net";
|
|
43643
43637
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
43644
43638
|
import { spawn as spawn3 } from "child_process";
|
|
43645
|
-
import { request as nodeHttpRequest } from "http";
|
|
43646
|
-
import { request as nodeHttpsRequest } from "https";
|
|
43647
43639
|
import { randomUUID as randomUUID22 } from "crypto";
|
|
43648
|
-
import { createRequire as createRequire2 } from "module";
|
|
43649
43640
|
function getPathValue(input2, path) {
|
|
43650
43641
|
return path.split(".").reduce((value, part) => {
|
|
43651
43642
|
if (value && typeof value === "object" && part in value) {
|
|
@@ -43741,103 +43732,13 @@ function channelMatchesEvent(channel, event) {
|
|
|
43741
43732
|
return true;
|
|
43742
43733
|
return channel.filters.some((filter) => eventMatchesFilter(event, filter));
|
|
43743
43734
|
}
|
|
43744
|
-
var PATHS_RESOLVER_KIND_ENV2 = {
|
|
43745
|
-
config: "HASNA_CONFIG_HOME",
|
|
43746
|
-
data: "HASNA_DATA_HOME",
|
|
43747
|
-
state: "HASNA_STATE_HOME",
|
|
43748
|
-
cache: "HASNA_CACHE_HOME"
|
|
43749
|
-
};
|
|
43750
|
-
var PATHS_RESOLVER_APP_SLUG_RE3 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
43751
|
-
function pathsResolverAssertApp3(app) {
|
|
43752
|
-
if (typeof app !== "string" || app.length === 0) {
|
|
43753
|
-
throw new TypeError("paths: app must be a non-empty string");
|
|
43754
|
-
}
|
|
43755
|
-
if (!PATHS_RESOLVER_APP_SLUG_RE3.test(app)) {
|
|
43756
|
-
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
43757
|
-
}
|
|
43758
|
-
}
|
|
43759
|
-
function pathsResolverAssertKind2(kind) {
|
|
43760
|
-
if (!Object.keys(PATHS_RESOLVER_KIND_ENV2).includes(kind)) {
|
|
43761
|
-
throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${Object.keys(PATHS_RESOLVER_KIND_ENV2).join(", ")}`);
|
|
43762
|
-
}
|
|
43763
|
-
}
|
|
43764
|
-
function pathsResolverBaseDir2(kind, options) {
|
|
43765
|
-
pathsResolverAssertKind2(kind);
|
|
43766
|
-
const env = options.env ?? process.env;
|
|
43767
|
-
const override = env[PATHS_RESOLVER_KIND_ENV2[kind]];
|
|
43768
|
-
if (typeof override === "string" && override.length > 0)
|
|
43769
|
-
return override;
|
|
43770
|
-
const home = options.home ?? pathsResolverHomedir3();
|
|
43771
|
-
const platform = options.platform ?? process.platform;
|
|
43772
|
-
if (platform === "darwin") {
|
|
43773
|
-
switch (kind) {
|
|
43774
|
-
case "config":
|
|
43775
|
-
case "data":
|
|
43776
|
-
return pathsResolverJoin3(home, "Library", "Application Support", "Hasna");
|
|
43777
|
-
case "cache":
|
|
43778
|
-
return pathsResolverJoin3(home, "Library", "Caches", "Hasna");
|
|
43779
|
-
case "state":
|
|
43780
|
-
return pathsResolverJoin3(home, "Library", "Logs", "Hasna");
|
|
43781
|
-
}
|
|
43782
|
-
}
|
|
43783
|
-
switch (kind) {
|
|
43784
|
-
case "config":
|
|
43785
|
-
return pathsResolverJoin3(home, ".config", "hasna");
|
|
43786
|
-
case "data":
|
|
43787
|
-
return pathsResolverJoin3(home, ".local", "share", "hasna");
|
|
43788
|
-
case "state":
|
|
43789
|
-
return pathsResolverJoin3(home, ".local", "state", "hasna");
|
|
43790
|
-
case "cache":
|
|
43791
|
-
return pathsResolverJoin3(home, ".cache", "hasna");
|
|
43792
|
-
}
|
|
43793
|
-
}
|
|
43794
|
-
function pathsResolverResolve2(kind, options) {
|
|
43795
|
-
pathsResolverAssertApp3(options.app);
|
|
43796
|
-
const appSegment = options.internal === true ? pathsResolverJoin3("internal", options.app) : options.app;
|
|
43797
|
-
return pathsResolverJoin3(pathsResolverBaseDir2(kind, options), appSegment);
|
|
43798
|
-
}
|
|
43799
|
-
function dataDir3(options) {
|
|
43800
|
-
return pathsResolverResolve2("data", options);
|
|
43801
|
-
}
|
|
43802
43735
|
var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR";
|
|
43803
43736
|
var HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME";
|
|
43804
|
-
var EVENTS_STORE_SENTINEL_FILE = "events.json";
|
|
43805
|
-
function effectiveHome2() {
|
|
43806
|
-
return process.env["HOME"] || process.env["USERPROFILE"] || homedir13();
|
|
43807
|
-
}
|
|
43808
|
-
function legacyHomeDir() {
|
|
43809
|
-
return join20(effectiveHome2(), ".hasna", "events");
|
|
43810
|
-
}
|
|
43811
|
-
function resolverHome() {
|
|
43812
|
-
return dataDir3({ app: "events", home: effectiveHome2() || undefined });
|
|
43813
|
-
}
|
|
43814
|
-
function adoptResolverHome(resolved, env = process.env) {
|
|
43815
|
-
const dataOverride = env.HASNA_DATA_HOME;
|
|
43816
|
-
if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
|
|
43817
|
-
return true;
|
|
43818
|
-
return existsSync13(join20(resolved, EVENTS_STORE_SENTINEL_FILE));
|
|
43819
|
-
}
|
|
43820
|
-
function exactEventsHome() {
|
|
43821
|
-
const dir = process.env[HASNA_EVENTS_DIR_ENV];
|
|
43822
|
-
if (dir && dir.trim())
|
|
43823
|
-
return dir.trim();
|
|
43824
|
-
const home = process.env[HASNA_EVENTS_HOME_ENV];
|
|
43825
|
-
if (home && home.trim())
|
|
43826
|
-
return home.trim();
|
|
43827
|
-
return;
|
|
43828
|
-
}
|
|
43829
|
-
function getEventsHome() {
|
|
43830
|
-
const exact2 = exactEventsHome();
|
|
43831
|
-
if (exact2)
|
|
43832
|
-
return resolve20(exact2);
|
|
43833
|
-
const resolved = resolverHome();
|
|
43834
|
-
return adoptResolverHome(resolved) ? resolve20(resolved) : resolve20(legacyHomeDir());
|
|
43835
|
-
}
|
|
43836
43737
|
var LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:";
|
|
43837
43738
|
var DEFAULT_EVENT_PAGE_LIMIT = 100;
|
|
43838
43739
|
var MAX_EVENT_PAGE_LIMIT = 1000;
|
|
43839
43740
|
function getEventsDataDir(override) {
|
|
43840
|
-
return override ||
|
|
43741
|
+
return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join20(homedir13(), ".hasna", "events");
|
|
43841
43742
|
}
|
|
43842
43743
|
function getActiveEventsDirEnv() {
|
|
43843
43744
|
if (process.env[HASNA_EVENTS_DIR_ENV])
|
|
@@ -43853,12 +43754,12 @@ class JsonEventsStore {
|
|
|
43853
43754
|
channelsPath;
|
|
43854
43755
|
eventsPath;
|
|
43855
43756
|
deliveriesPath;
|
|
43856
|
-
constructor(
|
|
43857
|
-
this.dataDir =
|
|
43858
|
-
this.runtime = localJsonRuntime(
|
|
43859
|
-
this.channelsPath =
|
|
43860
|
-
this.eventsPath =
|
|
43861
|
-
this.deliveriesPath =
|
|
43757
|
+
constructor(dataDir3 = getEventsDataDir()) {
|
|
43758
|
+
this.dataDir = dataDir3;
|
|
43759
|
+
this.runtime = localJsonRuntime(dataDir3);
|
|
43760
|
+
this.channelsPath = join20(dataDir3, "channels.json");
|
|
43761
|
+
this.eventsPath = join20(dataDir3, "events.json");
|
|
43762
|
+
this.deliveriesPath = join20(dataDir3, "deliveries.json");
|
|
43862
43763
|
}
|
|
43863
43764
|
async init() {
|
|
43864
43765
|
await mkdir(this.dataDir, { recursive: true, mode: 448 });
|
|
@@ -43975,7 +43876,7 @@ class JsonEventsStore {
|
|
|
43975
43876
|
};
|
|
43976
43877
|
}
|
|
43977
43878
|
async ensureArrayFile(path) {
|
|
43978
|
-
if (!
|
|
43879
|
+
if (!existsSync13(path)) {
|
|
43979
43880
|
await writeFile(path, `[]
|
|
43980
43881
|
`, { encoding: "utf-8", mode: 384 });
|
|
43981
43882
|
}
|
|
@@ -44005,7 +43906,7 @@ class JsonEventsStore {
|
|
|
44005
43906
|
});
|
|
44006
43907
|
}
|
|
44007
43908
|
}
|
|
44008
|
-
function localJsonRuntime(
|
|
43909
|
+
function localJsonRuntime(dataDir3 = getEventsDataDir()) {
|
|
44009
43910
|
return {
|
|
44010
43911
|
mode: "local-files",
|
|
44011
43912
|
name: "json-events-store",
|
|
@@ -44018,7 +43919,7 @@ function localJsonRuntime(dataDir22 = getEventsDataDir()) {
|
|
|
44018
43919
|
durable: true,
|
|
44019
43920
|
idempotency: "best-effort-local",
|
|
44020
43921
|
replayCursors: true,
|
|
44021
|
-
description: `Local JSON files in ${
|
|
43922
|
+
description: `Local JSON files in ${dataDir3}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
|
|
44022
43923
|
};
|
|
44023
43924
|
}
|
|
44024
43925
|
function encodeLocalJsonEventCursor(offset, options = {}) {
|
|
@@ -44082,8 +43983,8 @@ function assertCursorFilter(name, cursorValue, optionValue) {
|
|
|
44082
43983
|
function findEventByIdentity(events2, identity3) {
|
|
44083
43984
|
return events2.find((event) => identity3.id !== undefined && event.id === identity3.id || identity3.dedupeKey !== undefined && event.dedupeKey === identity3.dedupeKey);
|
|
44084
43985
|
}
|
|
44085
|
-
async function getEventsStatus(
|
|
44086
|
-
const store = new JsonEventsStore(
|
|
43986
|
+
async function getEventsStatus(dataDir3) {
|
|
43987
|
+
const store = new JsonEventsStore(dataDir3);
|
|
44087
43988
|
await store.init();
|
|
44088
43989
|
const [channels, events2, deliveries] = await Promise.all([
|
|
44089
43990
|
store.listChannels(),
|
|
@@ -44125,9 +44026,9 @@ async function getEventsStatus(dataDir22) {
|
|
|
44125
44026
|
}
|
|
44126
44027
|
};
|
|
44127
44028
|
}
|
|
44128
|
-
function statusFile(
|
|
44129
|
-
const path =
|
|
44130
|
-
return { path, exists:
|
|
44029
|
+
function statusFile(dataDir3, fileName, records) {
|
|
44030
|
+
const path = join20(dataDir3, fileName);
|
|
44031
|
+
return { path, exists: existsSync13(path), records };
|
|
44131
44032
|
}
|
|
44132
44033
|
var DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
|
|
44133
44034
|
function buildSignatureBase(timestamp, body) {
|
|
@@ -44137,214 +44038,6 @@ function signPayload(secret, timestamp, body) {
|
|
|
44137
44038
|
const digest4 = createHmac("sha256", secret).update(buildSignatureBase(timestamp, body)).digest("hex");
|
|
44138
44039
|
return `sha256=${digest4}`;
|
|
44139
44040
|
}
|
|
44140
|
-
var DEFAULT_MAX_REDIRECTS = 5;
|
|
44141
|
-
var IPV4_PRIVATE_RANGES = [
|
|
44142
|
-
[0, 16777215],
|
|
44143
|
-
[167772160, 184549375],
|
|
44144
|
-
[1681915904, 1686110207],
|
|
44145
|
-
[2130706432, 2147483647],
|
|
44146
|
-
[2851995648, 2852061183],
|
|
44147
|
-
[2886729728, 2887778303],
|
|
44148
|
-
[3221225472, 3221225727],
|
|
44149
|
-
[3221225984, 3221226239],
|
|
44150
|
-
[3227017984, 3227018239],
|
|
44151
|
-
[3232235520, 3232301055],
|
|
44152
|
-
[3323068416, 3323199487],
|
|
44153
|
-
[3325256704, 3325256959],
|
|
44154
|
-
[3405803776, 3405804031],
|
|
44155
|
-
[3758096384, 4294967295]
|
|
44156
|
-
];
|
|
44157
|
-
var IPV6_SPECIAL_PREFIXES = [
|
|
44158
|
-
{ groups: [0, 0, 0, 0, 0, 0, 0, 0], bits: 128 },
|
|
44159
|
-
{ groups: [0, 0, 0, 0, 0, 0, 0, 1], bits: 128 },
|
|
44160
|
-
{ groups: [0, 0, 0, 0, 0, 65535, 0, 0], bits: 96 },
|
|
44161
|
-
{ groups: [100, 65435, 0, 0, 0, 0, 0, 0], bits: 96 },
|
|
44162
|
-
{ groups: [256, 0, 0, 0, 0, 0, 0, 0], bits: 64 },
|
|
44163
|
-
{ groups: [8193, 0, 0, 0, 0, 0, 0, 0], bits: 32 },
|
|
44164
|
-
{ groups: [8193, 2, 0, 0, 0, 0, 0, 0], bits: 48 },
|
|
44165
|
-
{ groups: [8193, 16, 0, 0, 0, 0, 0, 0], bits: 28 },
|
|
44166
|
-
{ groups: [8193, 3512, 0, 0, 0, 0, 0, 0], bits: 32 },
|
|
44167
|
-
{ groups: [8194, 0, 0, 0, 0, 0, 0, 0], bits: 16 },
|
|
44168
|
-
{ groups: [16383, 0, 0, 0, 0, 0, 0, 0], bits: 20 },
|
|
44169
|
-
{ groups: [64512, 0, 0, 0, 0, 0, 0, 0], bits: 7 },
|
|
44170
|
-
{ groups: [65152, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
|
|
44171
|
-
{ groups: [65216, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
|
|
44172
|
-
{ groups: [65280, 0, 0, 0, 0, 0, 0, 0], bits: 8 }
|
|
44173
|
-
];
|
|
44174
|
-
function isPrivateAddress(address) {
|
|
44175
|
-
const normalized = stripZoneId(address);
|
|
44176
|
-
const version2 = isIP(normalized);
|
|
44177
|
-
if (version2 === 4) {
|
|
44178
|
-
const integer3 = ipv4ToInt(normalized);
|
|
44179
|
-
if (integer3 === undefined)
|
|
44180
|
-
return true;
|
|
44181
|
-
return IPV4_PRIVATE_RANGES.some(([low, high]) => integer3 >= low && integer3 <= high);
|
|
44182
|
-
}
|
|
44183
|
-
if (version2 === 6) {
|
|
44184
|
-
const groups = ipv6Groups(normalized);
|
|
44185
|
-
if (!groups)
|
|
44186
|
-
return true;
|
|
44187
|
-
for (const prefix3 of IPV6_SPECIAL_PREFIXES) {
|
|
44188
|
-
if (!ipv6MatchesPrefix(groups, prefix3.groups, prefix3.bits))
|
|
44189
|
-
continue;
|
|
44190
|
-
if (prefix3.bits === 96 && groups[5] === 65535) {
|
|
44191
|
-
return isPrivateAddress(ipv4IntToString(groups[6] << 16 | groups[7]));
|
|
44192
|
-
}
|
|
44193
|
-
if (prefix3.bits === 16 && groups[0] === 8194) {
|
|
44194
|
-
return isPrivateAddress(ipv4IntToString(groups[1] << 16 | groups[2]));
|
|
44195
|
-
}
|
|
44196
|
-
return true;
|
|
44197
|
-
}
|
|
44198
|
-
return false;
|
|
44199
|
-
}
|
|
44200
|
-
return true;
|
|
44201
|
-
}
|
|
44202
|
-
async function resolveWebhookTarget(url2, policy = {}) {
|
|
44203
|
-
const hostname3 = normalizeHostname(url2.hostname);
|
|
44204
|
-
const allowlist = (policy.allowPrivateHosts ?? []).map((entry) => normalizeHostname(entry.toLowerCase()));
|
|
44205
|
-
if (allowlist.includes(hostname3)) {
|
|
44206
|
-
const version22 = isIP(hostname3);
|
|
44207
|
-
if (version22 === 4 || version22 === 6) {
|
|
44208
|
-
return { hostname: hostname3, addresses: [hostname3] };
|
|
44209
|
-
}
|
|
44210
|
-
const lookup2 = policy.lookup ?? defaultTargetLookup;
|
|
44211
|
-
let resolved2;
|
|
44212
|
-
try {
|
|
44213
|
-
resolved2 = await lookup2(hostname3);
|
|
44214
|
-
} catch {
|
|
44215
|
-
throw new Error(`Webhook target ${hostname3} could not be resolved`);
|
|
44216
|
-
}
|
|
44217
|
-
if (!Array.isArray(resolved2) || resolved2.length === 0) {
|
|
44218
|
-
throw new Error(`Webhook target ${hostname3} resolved to no addresses`);
|
|
44219
|
-
}
|
|
44220
|
-
const addresses = resolved2.map((entry) => normalizeHostname(entry.address));
|
|
44221
|
-
return { hostname: hostname3, addresses };
|
|
44222
|
-
}
|
|
44223
|
-
const version2 = isIP(hostname3);
|
|
44224
|
-
if (version2 === 4 || version2 === 6) {
|
|
44225
|
-
if (isPrivateAddress(hostname3)) {
|
|
44226
|
-
throw new Error(`Webhook target ${hostname3} is a private or special-use address`);
|
|
44227
|
-
}
|
|
44228
|
-
return { hostname: hostname3, addresses: [hostname3] };
|
|
44229
|
-
}
|
|
44230
|
-
const lookup = policy.lookup ?? defaultTargetLookup;
|
|
44231
|
-
let resolved;
|
|
44232
|
-
try {
|
|
44233
|
-
resolved = await lookup(hostname3);
|
|
44234
|
-
} catch {
|
|
44235
|
-
throw new Error(`Webhook target ${hostname3} could not be resolved`);
|
|
44236
|
-
}
|
|
44237
|
-
if (!Array.isArray(resolved) || resolved.length === 0) {
|
|
44238
|
-
throw new Error(`Webhook target ${hostname3} resolved to no addresses`);
|
|
44239
|
-
}
|
|
44240
|
-
const allowed = [];
|
|
44241
|
-
for (const entry of resolved) {
|
|
44242
|
-
const address = normalizeHostname(entry.address);
|
|
44243
|
-
if (isPrivateAddress(address)) {
|
|
44244
|
-
if (allowlist.includes(address)) {
|
|
44245
|
-
allowed.push(address);
|
|
44246
|
-
continue;
|
|
44247
|
-
}
|
|
44248
|
-
throw new Error(`Webhook target ${hostname3} resolves to private or special-use address ${address}`);
|
|
44249
|
-
}
|
|
44250
|
-
allowed.push(address);
|
|
44251
|
-
}
|
|
44252
|
-
if (allowed.length === 0) {
|
|
44253
|
-
throw new Error(`Webhook target ${hostname3} resolved to no public addresses`);
|
|
44254
|
-
}
|
|
44255
|
-
return { hostname: hostname3, addresses: allowed };
|
|
44256
|
-
}
|
|
44257
|
-
function normalizeMaxRedirects(value) {
|
|
44258
|
-
if (value === undefined)
|
|
44259
|
-
return DEFAULT_MAX_REDIRECTS;
|
|
44260
|
-
if (!Number.isInteger(value) || value < 0)
|
|
44261
|
-
throw new Error("webhookTargetPolicy.maxRedirects must be a non-negative integer");
|
|
44262
|
-
return value;
|
|
44263
|
-
}
|
|
44264
|
-
var defaultTargetLookup = async (hostname3) => {
|
|
44265
|
-
return dnsLookup(hostname3, { all: true, verbatim: false });
|
|
44266
|
-
};
|
|
44267
|
-
function normalizeHostname(hostname3) {
|
|
44268
|
-
const lower = hostname3.toLowerCase();
|
|
44269
|
-
if (lower.startsWith("[") && lower.endsWith("]"))
|
|
44270
|
-
return lower.slice(1, -1);
|
|
44271
|
-
return lower;
|
|
44272
|
-
}
|
|
44273
|
-
function stripZoneId(address) {
|
|
44274
|
-
const percent = address.indexOf("%");
|
|
44275
|
-
return percent === -1 ? address : address.slice(0, percent);
|
|
44276
|
-
}
|
|
44277
|
-
function ipv4ToInt(address) {
|
|
44278
|
-
const parts = address.split(".");
|
|
44279
|
-
if (parts.length !== 4)
|
|
44280
|
-
return;
|
|
44281
|
-
let value = 0;
|
|
44282
|
-
for (const part of parts) {
|
|
44283
|
-
if (!/^\d{1,3}$/.test(part))
|
|
44284
|
-
return;
|
|
44285
|
-
const octet = Number(part);
|
|
44286
|
-
if (octet > 255)
|
|
44287
|
-
return;
|
|
44288
|
-
value = value << 8 | octet;
|
|
44289
|
-
}
|
|
44290
|
-
return value >>> 0;
|
|
44291
|
-
}
|
|
44292
|
-
function ipv4IntToString(integer3) {
|
|
44293
|
-
return [
|
|
44294
|
-
integer3 >>> 24 & 255,
|
|
44295
|
-
integer3 >>> 16 & 255,
|
|
44296
|
-
integer3 >>> 8 & 255,
|
|
44297
|
-
integer3 & 255
|
|
44298
|
-
].join(".");
|
|
44299
|
-
}
|
|
44300
|
-
function ipv6Groups(address) {
|
|
44301
|
-
const raw = stripZoneId(address);
|
|
44302
|
-
const doubleColon = raw.indexOf("::");
|
|
44303
|
-
const headText = doubleColon === -1 ? raw : raw.slice(0, doubleColon);
|
|
44304
|
-
const tailText = doubleColon === -1 ? "" : raw.slice(doubleColon + 2);
|
|
44305
|
-
const parseGroups = (text3) => {
|
|
44306
|
-
if (text3 === "")
|
|
44307
|
-
return [];
|
|
44308
|
-
const out = [];
|
|
44309
|
-
for (const part of text3.split(":")) {
|
|
44310
|
-
if (part.includes(".")) {
|
|
44311
|
-
const v4 = ipv4ToInt(part);
|
|
44312
|
-
if (v4 === undefined)
|
|
44313
|
-
return;
|
|
44314
|
-
out.push(v4 >>> 16 & 65535, v4 & 65535);
|
|
44315
|
-
} else {
|
|
44316
|
-
if (!/^[0-9a-fA-F]{1,4}$/.test(part))
|
|
44317
|
-
return;
|
|
44318
|
-
out.push(parseInt(part, 16));
|
|
44319
|
-
}
|
|
44320
|
-
}
|
|
44321
|
-
return out;
|
|
44322
|
-
};
|
|
44323
|
-
const head = parseGroups(headText);
|
|
44324
|
-
if (!head)
|
|
44325
|
-
return;
|
|
44326
|
-
const tail = parseGroups(tailText);
|
|
44327
|
-
if (!tail)
|
|
44328
|
-
return;
|
|
44329
|
-
const total = head.length + tail.length;
|
|
44330
|
-
if (doubleColon === -1) {
|
|
44331
|
-
return total === 8 ? head : undefined;
|
|
44332
|
-
}
|
|
44333
|
-
if (total >= 8)
|
|
44334
|
-
return;
|
|
44335
|
-
return [...head, ...new Array(8 - total).fill(0), ...tail];
|
|
44336
|
-
}
|
|
44337
|
-
function ipv6MatchesPrefix(groups, prefixGroups, prefixBits) {
|
|
44338
|
-
let remaining = prefixBits;
|
|
44339
|
-
for (let index = 0;index < prefixGroups.length && remaining > 0; index += 1) {
|
|
44340
|
-
const take = Math.min(16, remaining);
|
|
44341
|
-
const mask = 65535 << 16 - take & 65535;
|
|
44342
|
-
if ((groups[index] & mask) !== (prefixGroups[index] & mask))
|
|
44343
|
-
return false;
|
|
44344
|
-
remaining -= take;
|
|
44345
|
-
}
|
|
44346
|
-
return true;
|
|
44347
|
-
}
|
|
44348
44041
|
function now() {
|
|
44349
44042
|
return new Date().toISOString();
|
|
44350
44043
|
}
|
|
@@ -44375,18 +44068,9 @@ function buildWebhookRequest(event, channel, options = {}) {
|
|
|
44375
44068
|
}
|
|
44376
44069
|
return { body, headers };
|
|
44377
44070
|
}
|
|
44378
|
-
function normalizeWebhookUrl(raw) {
|
|
44379
|
-
const url2 = new URL(raw);
|
|
44380
|
-
if (url2.username !== "" || url2.password !== "") {
|
|
44381
|
-
url2.username = "";
|
|
44382
|
-
url2.password = "";
|
|
44383
|
-
}
|
|
44384
|
-
return url2.toString();
|
|
44385
|
-
}
|
|
44386
44071
|
async function dispatchWebhook(event, channel, options = {}) {
|
|
44387
44072
|
if (!channel.webhook)
|
|
44388
44073
|
throw new Error(`Channel ${channel.id} has no webhook config`);
|
|
44389
|
-
const webhookUrl = normalizeWebhookUrl(channel.webhook.url);
|
|
44390
44074
|
const startedAt = now();
|
|
44391
44075
|
let secret = channel.webhook.secret;
|
|
44392
44076
|
if (channel.webhook.secretRef) {
|
|
@@ -44403,14 +44087,10 @@ async function dispatchWebhook(event, channel, options = {}) {
|
|
|
44403
44087
|
}
|
|
44404
44088
|
const timestamp = (options.now?.() ?? new Date).toISOString();
|
|
44405
44089
|
const { body, headers } = buildWebhookRequest(event, channel, { secret, timestamp });
|
|
44406
|
-
const validateTargets = options.webhookTargetPolicy !== undefined || options.fetchImpl === undefined;
|
|
44407
|
-
if (validateTargets) {
|
|
44408
|
-
return dispatchValidatedWebhook(event, channel, { body, headers, startedAt, options });
|
|
44409
|
-
}
|
|
44410
44090
|
const controller = new AbortController;
|
|
44411
44091
|
const timeout = setTimeout(() => controller.abort(), channel.webhook.timeoutMs ?? 15000);
|
|
44412
44092
|
try {
|
|
44413
|
-
const response = await (options.fetchImpl ?? fetch)(
|
|
44093
|
+
const response = await (options.fetchImpl ?? fetch)(channel.webhook.url, {
|
|
44414
44094
|
method: "POST",
|
|
44415
44095
|
headers,
|
|
44416
44096
|
body,
|
|
@@ -44438,130 +44118,6 @@ async function dispatchWebhook(event, channel, options = {}) {
|
|
|
44438
44118
|
clearTimeout(timeout);
|
|
44439
44119
|
}
|
|
44440
44120
|
}
|
|
44441
|
-
function isRedirectStatus(status) {
|
|
44442
|
-
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
44443
|
-
}
|
|
44444
|
-
function redirectKeepsBody(status) {
|
|
44445
|
-
return status === 307 || status === 308;
|
|
44446
|
-
}
|
|
44447
|
-
async function pinnedNativeRequest(target, addresses, method, headers, body, signal, tls) {
|
|
44448
|
-
const isHttps = target.protocol === "https:";
|
|
44449
|
-
if (!isHttps && target.protocol !== "http:") {
|
|
44450
|
-
throw new Error(`Webhook target uses unsupported protocol ${target.protocol}`);
|
|
44451
|
-
}
|
|
44452
|
-
const defaultPort = isHttps ? 443 : 80;
|
|
44453
|
-
const port = target.port ? Number(target.port) : defaultPort;
|
|
44454
|
-
const requestOptions = {
|
|
44455
|
-
hostname: target.hostname,
|
|
44456
|
-
port,
|
|
44457
|
-
path: `${target.pathname}${target.search}`,
|
|
44458
|
-
method,
|
|
44459
|
-
headers,
|
|
44460
|
-
...tls?.ca ? { ca: tls.ca } : {},
|
|
44461
|
-
lookup: (hostname3, _options, callback) => {
|
|
44462
|
-
const entries = addresses.map((address) => ({
|
|
44463
|
-
address,
|
|
44464
|
-
family: address.includes(":") ? 6 : 4
|
|
44465
|
-
}));
|
|
44466
|
-
callback(null, entries);
|
|
44467
|
-
}
|
|
44468
|
-
};
|
|
44469
|
-
return new Promise((resolve23, reject) => {
|
|
44470
|
-
const request = isHttps ? nodeHttpsRequest(requestOptions, onResponse) : nodeHttpRequest(requestOptions, onResponse);
|
|
44471
|
-
const onAbort = () => {
|
|
44472
|
-
const error61 = new Error("The operation was aborted.");
|
|
44473
|
-
error61.name = "AbortError";
|
|
44474
|
-
request.destroy(error61);
|
|
44475
|
-
};
|
|
44476
|
-
if (signal.aborted)
|
|
44477
|
-
onAbort();
|
|
44478
|
-
else
|
|
44479
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
44480
|
-
request.on("error", reject);
|
|
44481
|
-
if (body !== undefined)
|
|
44482
|
-
request.write(body);
|
|
44483
|
-
request.end();
|
|
44484
|
-
function onResponse(response) {
|
|
44485
|
-
const chunks = [];
|
|
44486
|
-
response.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
44487
|
-
response.on("error", reject);
|
|
44488
|
-
response.on("end", () => {
|
|
44489
|
-
const headersRecord = {};
|
|
44490
|
-
for (const [name, value] of Object.entries(response.headers)) {
|
|
44491
|
-
if (typeof value === "string")
|
|
44492
|
-
headersRecord[name] = value;
|
|
44493
|
-
else if (Array.isArray(value))
|
|
44494
|
-
headersRecord[name] = value.join(", ");
|
|
44495
|
-
}
|
|
44496
|
-
resolve23(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
|
|
44497
|
-
});
|
|
44498
|
-
}
|
|
44499
|
-
});
|
|
44500
|
-
}
|
|
44501
|
-
async function dispatchValidatedWebhook(event, channel, input2) {
|
|
44502
|
-
const { body, headers, startedAt, options } = input2;
|
|
44503
|
-
const webhook = channel.webhook;
|
|
44504
|
-
if (!webhook)
|
|
44505
|
-
throw new Error(`Channel ${channel.id} has no webhook config`);
|
|
44506
|
-
const policy = options.webhookTargetPolicy ?? {};
|
|
44507
|
-
const maxRedirects = normalizeMaxRedirects(policy.maxRedirects);
|
|
44508
|
-
const controller = new AbortController;
|
|
44509
|
-
const timeout = setTimeout(() => controller.abort(), webhook.timeoutMs ?? 15000);
|
|
44510
|
-
try {
|
|
44511
|
-
let target = new URL(normalizeWebhookUrl(webhook.url));
|
|
44512
|
-
let requestHeaders = headers;
|
|
44513
|
-
let method = "POST";
|
|
44514
|
-
let requestBody = body;
|
|
44515
|
-
let redirectsFollowed = 0;
|
|
44516
|
-
for (;; ) {
|
|
44517
|
-
const resolved = await resolveWebhookTarget(target, policy).catch((error61) => {
|
|
44518
|
-
throw new Error(`Webhook target rejected by SSRF guard: ${error61.message}`);
|
|
44519
|
-
});
|
|
44520
|
-
const response = options.fetchImpl ? await options.fetchImpl(target, {
|
|
44521
|
-
method,
|
|
44522
|
-
headers: requestHeaders,
|
|
44523
|
-
body: requestBody,
|
|
44524
|
-
signal: controller.signal,
|
|
44525
|
-
redirect: "manual"
|
|
44526
|
-
}) : await pinnedNativeRequest(target, resolved.addresses, method, requestHeaders, requestBody, controller.signal, options.tls);
|
|
44527
|
-
const location = response.headers.get("location");
|
|
44528
|
-
if (isRedirectStatus(response.status) && location) {
|
|
44529
|
-
if (redirectsFollowed >= maxRedirects) {
|
|
44530
|
-
return failedAttempt(startedAt, `Webhook target exceeded ${maxRedirects} redirects`);
|
|
44531
|
-
}
|
|
44532
|
-
redirectsFollowed += 1;
|
|
44533
|
-
const next = new URL(location, target);
|
|
44534
|
-
target = next;
|
|
44535
|
-
if (!redirectKeepsBody(response.status)) {
|
|
44536
|
-
method = "GET";
|
|
44537
|
-
requestBody = undefined;
|
|
44538
|
-
requestHeaders = Object.fromEntries(Object.entries(requestHeaders).filter(([name]) => name.toLowerCase() !== "content-type" && name.toLowerCase() !== "content-length"));
|
|
44539
|
-
}
|
|
44540
|
-
continue;
|
|
44541
|
-
}
|
|
44542
|
-
const responseBody = truncate(await response.text());
|
|
44543
|
-
return {
|
|
44544
|
-
attempt: 1,
|
|
44545
|
-
status: response.ok ? "success" : "failed",
|
|
44546
|
-
startedAt,
|
|
44547
|
-
completedAt: now(),
|
|
44548
|
-
responseStatus: response.status,
|
|
44549
|
-
responseBody,
|
|
44550
|
-
error: response.ok ? undefined : `Webhook returned HTTP ${response.status}`
|
|
44551
|
-
};
|
|
44552
|
-
}
|
|
44553
|
-
} catch (error61) {
|
|
44554
|
-
return {
|
|
44555
|
-
attempt: 1,
|
|
44556
|
-
status: "failed",
|
|
44557
|
-
startedAt,
|
|
44558
|
-
completedAt: now(),
|
|
44559
|
-
error: error61 instanceof Error ? error61.message : String(error61)
|
|
44560
|
-
};
|
|
44561
|
-
} finally {
|
|
44562
|
-
clearTimeout(timeout);
|
|
44563
|
-
}
|
|
44564
|
-
}
|
|
44565
44121
|
function failedAttempt(startedAt, error61) {
|
|
44566
44122
|
return {
|
|
44567
44123
|
attempt: 1,
|
|
@@ -44590,7 +44146,7 @@ async function dispatchCommand(event, channel) {
|
|
|
44590
44146
|
HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
|
|
44591
44147
|
HASNA_EVENT_JSON: eventJson
|
|
44592
44148
|
};
|
|
44593
|
-
return new Promise((
|
|
44149
|
+
return new Promise((resolve16) => {
|
|
44594
44150
|
const child = spawn3(channel.command.command, channel.command.args ?? [], {
|
|
44595
44151
|
cwd: channel.command.cwd,
|
|
44596
44152
|
env,
|
|
@@ -44608,7 +44164,7 @@ async function dispatchCommand(event, channel) {
|
|
|
44608
44164
|
});
|
|
44609
44165
|
child.on("error", (error61) => {
|
|
44610
44166
|
clearTimeout(timeout);
|
|
44611
|
-
|
|
44167
|
+
resolve16({
|
|
44612
44168
|
attempt: 1,
|
|
44613
44169
|
status: "failed",
|
|
44614
44170
|
startedAt,
|
|
@@ -44621,7 +44177,7 @@ async function dispatchCommand(event, channel) {
|
|
|
44621
44177
|
child.on("close", (code2, signal) => {
|
|
44622
44178
|
clearTimeout(timeout);
|
|
44623
44179
|
const success2 = code2 === 0;
|
|
44624
|
-
|
|
44180
|
+
resolve16({
|
|
44625
44181
|
attempt: 1,
|
|
44626
44182
|
status: success2 ? "success" : "failed",
|
|
44627
44183
|
startedAt,
|
|
@@ -44743,22 +44299,6 @@ function setPath(input2, path, replacement) {
|
|
|
44743
44299
|
if (last && last in cursor)
|
|
44744
44300
|
cursor[last] = replacement;
|
|
44745
44301
|
}
|
|
44746
|
-
var MAX_PACKAGE_BYTES2 = 1024 * 1024;
|
|
44747
|
-
var MAX_CREDENTIAL_FILE_BYTES2 = 64 * 1024;
|
|
44748
|
-
var INSPECT_CUSTOM2 = Symbol.for("nodejs.util.inspect.custom");
|
|
44749
|
-
var CREDENTIAL_SEAL2 = Symbol.for("hasna:contracts:sealedCredential");
|
|
44750
|
-
var AMBIENT_ENVIRONMENT2 = Symbol.for("hasna:contracts:ambientClientEnvironment");
|
|
44751
|
-
var requireSecretsSdk2 = createRequire2(import.meta.url);
|
|
44752
|
-
var IDEMPOTENT_METHODS2 = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
44753
|
-
var AUTHORITY_OVERRIDE_HEADERS2 = new Set([
|
|
44754
|
-
"host",
|
|
44755
|
-
":authority",
|
|
44756
|
-
"forwarded",
|
|
44757
|
-
"x-forwarded-host",
|
|
44758
|
-
"x-original-host"
|
|
44759
|
-
]);
|
|
44760
|
-
var MAX_ENVELOPE_BYTES = 256 * 1024;
|
|
44761
|
-
var MAX_REQUEST_BYTES = MAX_ENVELOPE_BYTES * 2 + 8192;
|
|
44762
44302
|
function createEvent(input2) {
|
|
44763
44303
|
return {
|
|
44764
44304
|
id: input2.id ?? randomUUID22(),
|
|
@@ -44787,9 +44327,7 @@ class EventsClient {
|
|
|
44787
44327
|
this.transportOptions = {
|
|
44788
44328
|
fetchImpl: options.fetchImpl,
|
|
44789
44329
|
secretResolver: options.secretResolver,
|
|
44790
|
-
now: options.now
|
|
44791
|
-
tls: options.tls,
|
|
44792
|
-
webhookTargetPolicy: options.webhookTargetPolicy
|
|
44330
|
+
now: options.now
|
|
44793
44331
|
};
|
|
44794
44332
|
this.catalog = options.catalog ?? defaultEventTypeCatalog;
|
|
44795
44333
|
this.validateCatalogTypes = options.validateCatalogTypes ?? false;
|
|
@@ -45076,13 +44614,6 @@ function parseMatcherExpression(value, label) {
|
|
|
45076
44614
|
negated: false
|
|
45077
44615
|
};
|
|
45078
44616
|
}
|
|
45079
|
-
function webhookTargetPolicyFromEnv() {
|
|
45080
|
-
const value = process.env.HASNA_EVENTS_ALLOW_PRIVATE_WEBHOOK_TARGETS;
|
|
45081
|
-
if (!value)
|
|
45082
|
-
return;
|
|
45083
|
-
const hosts = value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
45084
|
-
return hosts.length > 0 ? { allowPrivateHosts: hosts } : undefined;
|
|
45085
|
-
}
|
|
45086
44617
|
var DEFAULT_EVENT_LIST_LIMIT = 100;
|
|
45087
44618
|
function parseJsonObject(value, fallback) {
|
|
45088
44619
|
if (!value)
|
|
@@ -45108,7 +44639,7 @@ function parseHeaders(values) {
|
|
|
45108
44639
|
function createClient(options) {
|
|
45109
44640
|
if (options.createClient)
|
|
45110
44641
|
return options.createClient();
|
|
45111
|
-
return new EventsClient({ store: new JsonEventsStore(options.dataDir)
|
|
44642
|
+
return new EventsClient({ store: new JsonEventsStore(options.dataDir) });
|
|
45112
44643
|
}
|
|
45113
44644
|
function print(value, json2, text3) {
|
|
45114
44645
|
if (json2)
|
|
@@ -45189,8 +44720,6 @@ function registerChannelCommands(program2, options) {
|
|
|
45189
44720
|
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
45190
44721
|
}, { honorFilters: actionOptions.honorFilters });
|
|
45191
44722
|
print(result, json2, `${result.status}: ${result.channelId}`);
|
|
45192
|
-
if (result.status === "failed")
|
|
45193
|
-
process.exitCode = 1;
|
|
45194
44723
|
} catch (error61) {
|
|
45195
44724
|
fail(error61, json2);
|
|
45196
44725
|
}
|
|
@@ -45283,7 +44812,7 @@ function replaySummary(events2, deliveries, nextCursor) {
|
|
|
45283
44812
|
// src/cli/index.tsx
|
|
45284
44813
|
import { render } from "ink";
|
|
45285
44814
|
|
|
45286
|
-
//
|
|
44815
|
+
// node_modules/commander/esm.mjs
|
|
45287
44816
|
var import__ = __toESM(require_commander(), 1);
|
|
45288
44817
|
var {
|
|
45289
44818
|
program: program2,
|
|
@@ -45302,18 +44831,18 @@ var {
|
|
|
45302
44831
|
// src/cli/index.tsx
|
|
45303
44832
|
import chalk2 from "chalk";
|
|
45304
44833
|
import { existsSync as existsSync18, readFileSync as readFileSync27, rmSync as rmSync6 } from "fs";
|
|
45305
|
-
import { join as
|
|
44834
|
+
import { join as join35, dirname as dirname28 } from "path";
|
|
45306
44835
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
45307
44836
|
|
|
45308
44837
|
// src/cli/components/App.tsx
|
|
45309
44838
|
import { useState as useState7 } from "react";
|
|
45310
44839
|
import { Box as Box8, Text as Text10, useApp, useInput as useInput5 } from "ink";
|
|
45311
44840
|
|
|
45312
|
-
//
|
|
44841
|
+
// node_modules/ink-select-input/build/Indicator.js
|
|
45313
44842
|
import React from "react";
|
|
45314
44843
|
import { Box, Text } from "ink";
|
|
45315
44844
|
|
|
45316
|
-
//
|
|
44845
|
+
// node_modules/is-unicode-supported/index.js
|
|
45317
44846
|
import process3 from "process";
|
|
45318
44847
|
function isUnicodeSupported() {
|
|
45319
44848
|
const { env } = process3;
|
|
@@ -45324,7 +44853,7 @@ function isUnicodeSupported() {
|
|
|
45324
44853
|
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";
|
|
45325
44854
|
}
|
|
45326
44855
|
|
|
45327
|
-
//
|
|
44856
|
+
// node_modules/figures/index.js
|
|
45328
44857
|
var common2 = {
|
|
45329
44858
|
circleQuestionMark: "(?)",
|
|
45330
44859
|
questionMarkPrefix: "(?)",
|
|
@@ -45600,23 +45129,23 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|
|
|
45600
45129
|
var figures_default = figures;
|
|
45601
45130
|
var replacements = Object.entries(specialMainSymbols);
|
|
45602
45131
|
|
|
45603
|
-
//
|
|
45132
|
+
// node_modules/ink-select-input/build/Indicator.js
|
|
45604
45133
|
function Indicator({ isSelected = false }) {
|
|
45605
45134
|
return React.createElement(Box, { marginRight: 1 }, isSelected ? React.createElement(Text, { color: "blue" }, figures_default.pointer) : React.createElement(Text, null, " "));
|
|
45606
45135
|
}
|
|
45607
45136
|
var Indicator_default = Indicator;
|
|
45608
|
-
//
|
|
45137
|
+
// node_modules/ink-select-input/build/Item.js
|
|
45609
45138
|
import * as React2 from "react";
|
|
45610
45139
|
import { Text as Text2 } from "ink";
|
|
45611
45140
|
function Item({ isSelected = false, label }) {
|
|
45612
45141
|
return React2.createElement(Text2, { color: isSelected ? "blue" : undefined }, label);
|
|
45613
45142
|
}
|
|
45614
45143
|
var Item_default = Item;
|
|
45615
|
-
//
|
|
45144
|
+
// node_modules/ink-select-input/build/SelectInput.js
|
|
45616
45145
|
import { isDeepStrictEqual } from "util";
|
|
45617
45146
|
import React3, { useState, useEffect, useRef, useCallback } from "react";
|
|
45618
45147
|
|
|
45619
|
-
//
|
|
45148
|
+
// node_modules/to-rotated/index.js
|
|
45620
45149
|
function toRotated(array3, steps) {
|
|
45621
45150
|
if (!Array.isArray(array3)) {
|
|
45622
45151
|
throw new TypeError(`Expected an array, got \`${typeof array3}\`.`);
|
|
@@ -45638,7 +45167,7 @@ function toRotated(array3, steps) {
|
|
|
45638
45167
|
];
|
|
45639
45168
|
}
|
|
45640
45169
|
|
|
45641
|
-
//
|
|
45170
|
+
// node_modules/ink-select-input/build/SelectInput.js
|
|
45642
45171
|
import { Box as Box2, useInput } from "ink";
|
|
45643
45172
|
function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicatorComponent = Indicator_default, itemComponent = Item_default, limit: customLimit, onSelect, onHighlight }) {
|
|
45644
45173
|
const hasLimit = typeof customLimit === "number" && items.length > customLimit;
|
|
@@ -45934,7 +45463,7 @@ function HookSelect({
|
|
|
45934
45463
|
import { useState as useState4, useEffect as useEffect3 } from "react";
|
|
45935
45464
|
import { Box as Box6, Text as Text7, useInput as useInput4 } from "ink";
|
|
45936
45465
|
|
|
45937
|
-
//
|
|
45466
|
+
// node_modules/ink-text-input/build/index.js
|
|
45938
45467
|
import React5, { useState as useState3, useEffect as useEffect2 } from "react";
|
|
45939
45468
|
import { Text as Text6, useInput as useInput3 } from "ink";
|
|
45940
45469
|
import chalk from "chalk";
|
|
@@ -46112,7 +45641,7 @@ function SearchView({
|
|
|
46112
45641
|
import { useState as useState6, useEffect as useEffect5 } from "react";
|
|
46113
45642
|
import { Box as Box7, Text as Text9 } from "ink";
|
|
46114
45643
|
|
|
46115
|
-
//
|
|
45644
|
+
// node_modules/ink-spinner/build/index.js
|
|
46116
45645
|
var import_cli_spinners = __toESM(require_cli_spinners(), 1);
|
|
46117
45646
|
import React7, { useState as useState5, useEffect as useEffect4 } from "react";
|
|
46118
45647
|
import { Text as Text8 } from "ink";
|
|
@@ -46479,10 +46008,10 @@ init_native_safety();
|
|
|
46479
46008
|
|
|
46480
46009
|
// src/lib/sumi-binding.ts
|
|
46481
46010
|
import { homedir as homedir14 } from "os";
|
|
46482
|
-
import { join as
|
|
46011
|
+
import { join as join24, sep as sep3 } from "path";
|
|
46483
46012
|
|
|
46484
46013
|
// hooks/hook-trash-guard/src/binary.ts
|
|
46485
|
-
import { dirname as dirname21, isAbsolute as isAbsolute20, join as
|
|
46014
|
+
import { dirname as dirname21, isAbsolute as isAbsolute20, join as join22, resolve as resolve20 } from "path";
|
|
46486
46015
|
import { accessSync, closeSync as closeSync19, constants as constants18, fstatSync as fstatSync18, lstatSync as lstatSync23, openSync as openSync19, readFileSync as readFileSync17, readlinkSync as readlinkSync3, readSync as readSync3, realpathSync as realpathSync11, statSync } from "fs";
|
|
46487
46016
|
import { spawnSync } from "child_process";
|
|
46488
46017
|
function trustedOwner(uid2) {
|
|
@@ -46504,7 +46033,7 @@ function safeExecutableFile(path, systemBinAlias = false) {
|
|
|
46504
46033
|
parent = dirname21(parent);
|
|
46505
46034
|
continue;
|
|
46506
46035
|
}
|
|
46507
|
-
const next =
|
|
46036
|
+
const next = join22(parent, part), info2 = lstatSync23(next);
|
|
46508
46037
|
if (systemBinAlias && next === "/bin" && info2.isSymbolicLink() && info2.uid === 0) {
|
|
46509
46038
|
const target = realpathSync11(next);
|
|
46510
46039
|
if (!safeBinaryDirectory(target))
|
|
@@ -46516,7 +46045,7 @@ function safeExecutableFile(path, systemBinAlias = false) {
|
|
|
46516
46045
|
return false;
|
|
46517
46046
|
parent = next;
|
|
46518
46047
|
}
|
|
46519
|
-
const candidate =
|
|
46048
|
+
const candidate = join22(parent, name), info = lstatSync23(candidate);
|
|
46520
46049
|
if (!trustedOwner(info.uid))
|
|
46521
46050
|
return false;
|
|
46522
46051
|
if (info.isSymbolicLink()) {
|
|
@@ -46529,9 +46058,9 @@ function safeExecutableFile(path, systemBinAlias = false) {
|
|
|
46529
46058
|
return false;
|
|
46530
46059
|
}
|
|
46531
46060
|
function safeInterpreterSearchDirectory(path) {
|
|
46532
|
-
if (!isAbsolute20(path) ||
|
|
46061
|
+
if (!isAbsolute20(path) || resolve20(path) !== (path.replace(/\/+$/, "") || "/"))
|
|
46533
46062
|
return false;
|
|
46534
|
-
for (let cursor =
|
|
46063
|
+
for (let cursor = resolve20(path);; cursor = dirname21(cursor)) {
|
|
46535
46064
|
try {
|
|
46536
46065
|
lstatSync23(cursor);
|
|
46537
46066
|
return safeBinaryDirectory(cursor);
|
|
@@ -46563,7 +46092,7 @@ function safeScriptInterpreter(executable2, pathValue) {
|
|
|
46563
46092
|
for (const dir of pathValue.split(":").slice(0, 64)) {
|
|
46564
46093
|
if (!safeInterpreterSearchDirectory(dir))
|
|
46565
46094
|
return false;
|
|
46566
|
-
const interpreter =
|
|
46095
|
+
const interpreter = resolve20(dir, "bun");
|
|
46567
46096
|
try {
|
|
46568
46097
|
if (!statSync(interpreter).isFile())
|
|
46569
46098
|
continue;
|
|
@@ -46598,7 +46127,7 @@ function inspectTrashBinary(env = process.env) {
|
|
|
46598
46127
|
for (const dir of pathValue.split(":").slice(0, 64)) {
|
|
46599
46128
|
if (!isAbsolute20(dir) || Date.now() >= deadline)
|
|
46600
46129
|
continue;
|
|
46601
|
-
const candidate =
|
|
46130
|
+
const candidate = resolve20(dir, "trash");
|
|
46602
46131
|
try {
|
|
46603
46132
|
const stat2 = statSync(candidate);
|
|
46604
46133
|
if (!stat2.isFile() || !trustedOwner(stat2.uid) || (stat2.mode & 73) === 0 || (stat2.mode & 18) !== 0) {
|
|
@@ -46606,7 +46135,7 @@ function inspectTrashBinary(env = process.env) {
|
|
|
46606
46135
|
continue;
|
|
46607
46136
|
}
|
|
46608
46137
|
const executable2 = realpathSync11(candidate);
|
|
46609
|
-
if (!safeBinaryDirectory(
|
|
46138
|
+
if (!safeBinaryDirectory(resolve20(dir)) || !safeBinaryDirectory(dirname21(executable2))) {
|
|
46610
46139
|
reject("unsafe_directory");
|
|
46611
46140
|
continue;
|
|
46612
46141
|
}
|
|
@@ -46614,15 +46143,15 @@ function inspectTrashBinary(env = process.env) {
|
|
|
46614
46143
|
reject("unsafe_directory");
|
|
46615
46144
|
continue;
|
|
46616
46145
|
}
|
|
46617
|
-
const packageRoot =
|
|
46618
|
-
const manifestPath =
|
|
46146
|
+
const packageRoot = resolve20(dirname21(executable2), "../..");
|
|
46147
|
+
const manifestPath = join22(packageRoot, "package.json");
|
|
46619
46148
|
const manifestStat = statSync(manifestPath);
|
|
46620
46149
|
if (!manifestStat.isFile() || !trustedOwner(manifestStat.uid) || manifestStat.size > 16384 || (manifestStat.mode & 18) !== 0 || lstatSync23(manifestPath).isSymbolicLink()) {
|
|
46621
46150
|
reject("unsafe_manifest");
|
|
46622
46151
|
continue;
|
|
46623
46152
|
}
|
|
46624
46153
|
const manifest = JSON.parse(readFileSync17(manifestPath, "utf8"));
|
|
46625
|
-
if (manifest.name !== "@hasna/trash" || typeof manifest.version !== "string" || typeof manifest.bin?.trash !== "string" || realpathSync11(
|
|
46154
|
+
if (manifest.name !== "@hasna/trash" || typeof manifest.version !== "string" || typeof manifest.bin?.trash !== "string" || realpathSync11(resolve20(packageRoot, manifest.bin.trash)) !== executable2) {
|
|
46626
46155
|
reject("unrecognized_package");
|
|
46627
46156
|
continue;
|
|
46628
46157
|
}
|
|
@@ -46635,14 +46164,19 @@ function inspectTrashBinary(env = process.env) {
|
|
|
46635
46164
|
reject("unsafe_interpreter");
|
|
46636
46165
|
continue;
|
|
46637
46166
|
}
|
|
46167
|
+
const remaining = deadline - Date.now();
|
|
46168
|
+
if (remaining <= 0) {
|
|
46169
|
+
reject("identity_failed");
|
|
46170
|
+
break;
|
|
46171
|
+
}
|
|
46638
46172
|
const probe = spawnSync(candidate, ["--identity"], {
|
|
46639
46173
|
encoding: "utf8",
|
|
46640
|
-
timeout:
|
|
46174
|
+
timeout: remaining,
|
|
46641
46175
|
maxBuffer: 2048,
|
|
46642
46176
|
env: { PATH: pathValue },
|
|
46643
46177
|
stdio: ["ignore", "pipe", "pipe"]
|
|
46644
46178
|
});
|
|
46645
|
-
if (probe.error || probe.status !== 0) {
|
|
46179
|
+
if (probe.error || probe.status !== 0 || Date.now() >= deadline) {
|
|
46646
46180
|
reject("identity_failed");
|
|
46647
46181
|
continue;
|
|
46648
46182
|
}
|
|
@@ -46662,7 +46196,7 @@ function failure(code2, reason) {
|
|
|
46662
46196
|
return { ok: false, target: "sumi", code: code2, ...reason ? { reason: reason.slice(0, 300) } : {} };
|
|
46663
46197
|
}
|
|
46664
46198
|
function nativeSafetyBindingDurable(worker, home) {
|
|
46665
|
-
return !(worker.startsWith(
|
|
46199
|
+
return !(worker.startsWith(join24(home, ".bun") + sep3) || worker.includes(`${sep3}node_modules${sep3}.bun${sep3}`));
|
|
46666
46200
|
}
|
|
46667
46201
|
async function provisionSumiSafetyBinding(options = {}) {
|
|
46668
46202
|
const home = options.home ?? homedir14();
|
|
@@ -46737,7 +46271,7 @@ init_transport2();
|
|
|
46737
46271
|
init_db();
|
|
46738
46272
|
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
46739
46273
|
var __dirname4 = dirname28(fileURLToPath6(import.meta.url));
|
|
46740
|
-
var pkgPath = existsSync18(
|
|
46274
|
+
var pkgPath = existsSync18(join35(__dirname4, "..", "package.json")) ? join35(__dirname4, "..", "package.json") : join35(__dirname4, "..", "..", "package.json");
|
|
46741
46275
|
var pkg2 = JSON.parse(readFileSync27(pkgPath, "utf-8"));
|
|
46742
46276
|
var program3 = new Command;
|
|
46743
46277
|
function resolveScope(options) {
|
|
@@ -46970,7 +46504,7 @@ program3.command("init").description("Register a new agent profile with a unique
|
|
|
46970
46504
|
if (profile.name) {
|
|
46971
46505
|
console.log(` ${chalk2.dim("Name:")} ${profile.name}`);
|
|
46972
46506
|
}
|
|
46973
|
-
console.log(` ${chalk2.dim("Profile:")} ${
|
|
46507
|
+
console.log(` ${chalk2.dim("Profile:")} ${join35(getProfilesDir(), `${profile.agent_id}.json`)}`);
|
|
46974
46508
|
console.log();
|
|
46975
46509
|
console.log(chalk2.dim(" Install hooks with this profile:"));
|
|
46976
46510
|
console.log(` hooks install gitguard --profile ${profile.agent_id}`);
|
|
@@ -47625,7 +47159,7 @@ program3.command("doctor").option("-g, --global", "Check global settings", false
|
|
|
47625
47159
|
continue;
|
|
47626
47160
|
}
|
|
47627
47161
|
const hookDir = getHookPath(name);
|
|
47628
|
-
const hookScript =
|
|
47162
|
+
const hookScript = join35(hookDir, "src", "hook.ts");
|
|
47629
47163
|
if (!existsSync18(hookScript)) {
|
|
47630
47164
|
issues.push({ hook: name, issue: "Missing src/hook.ts in package", severity: "error" });
|
|
47631
47165
|
hookHealthy = false;
|
|
@@ -47836,7 +47370,7 @@ program3.command("docs").argument("[hook]", "Hook name (shows general docs if om
|
|
|
47836
47370
|
return;
|
|
47837
47371
|
}
|
|
47838
47372
|
const hookPath = getHookPath(hook);
|
|
47839
|
-
const readmePath =
|
|
47373
|
+
const readmePath = join35(hookPath, "README.md");
|
|
47840
47374
|
let readme = "";
|
|
47841
47375
|
if (existsSync18(readmePath)) {
|
|
47842
47376
|
readme = readFileSync27(readmePath, "utf-8");
|
|
@@ -48634,7 +48168,7 @@ safety.command("verify").requiredOption("--target <target>", "sumi, codex or cla
|
|
|
48634
48168
|
throw new ClaudeSafetyError("settings_invalid");
|
|
48635
48169
|
console.log(JSON.stringify(await verifyClaudeSafetyConfiguration({
|
|
48636
48170
|
cwd: options.cwd,
|
|
48637
|
-
...process.env.CLAUDE_CONFIG_DIR ? { userSettingsPath:
|
|
48171
|
+
...process.env.CLAUDE_CONFIG_DIR ? { userSettingsPath: resolve21(process.env.CLAUDE_CONFIG_DIR, "settings.json") } : {}
|
|
48638
48172
|
})));
|
|
48639
48173
|
} catch (error61) {
|
|
48640
48174
|
console.log(JSON.stringify({ ok: false, target: "claude", code: error61 instanceof ClaudeSafetyError ? error61.code : "settings_invalid", nativeAdoptionVerified: false }));
|