@darkhunt-security/endpoint-codex 0.9.16 → 0.9.18
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/.codex-plugin/plugin.json +1 -1
- package/commands/backfill.md +55 -1
- package/commands/status.md +5 -0
- package/dist/bin/backfill.mjs +269 -28
- package/dist/bin/enroll.mjs +12 -1
- package/dist/bin/forwarder.mjs +227 -22
- package/dist/bin/guard.mjs +11 -1
- package/dist/bin/init.mjs +12 -1
- package/dist/bin/spool.mjs +11 -1
- package/dist/bin/status.mjs +79 -26
- package/package.json +2 -2
package/dist/bin/enroll.mjs
CHANGED
|
@@ -60,12 +60,16 @@ async function readStdin(stream) {
|
|
|
60
60
|
return Buffer.concat(chunks).toString("utf8");
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
// packages/core/dist/emit/emitter.js
|
|
64
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
65
|
+
|
|
63
66
|
// packages/core/dist/forwarder/tail.js
|
|
64
67
|
var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
65
68
|
var LINE_CEILING = 64 * 1024 * 1024;
|
|
66
69
|
|
|
67
70
|
// packages/core/dist/forwarder/lock.js
|
|
68
71
|
var STALE_MS = 5 * 60 * 1e3;
|
|
72
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
69
73
|
var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
|
|
70
74
|
|
|
71
75
|
// node_modules/@darkhunt-security/telemetry/package.json
|
|
@@ -994,6 +998,9 @@ var VALIDATORS = Object.freeze({
|
|
|
994
998
|
// node_modules/@darkhunt-security/telemetry/dist/client.js
|
|
995
999
|
var LIB_VERSION = package_default.version;
|
|
996
1000
|
|
|
1001
|
+
// packages/core/dist/forwarder/retry.js
|
|
1002
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
1003
|
+
|
|
997
1004
|
// packages/core/dist/cli/init.js
|
|
998
1005
|
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
999
1006
|
function init(argv) {
|
|
@@ -1033,7 +1040,11 @@ function init(argv) {
|
|
|
1033
1040
|
// a named profile resolve without the flag on every later run.
|
|
1034
1041
|
...separateFile ? { profile, credentials: credsPath, ...stripCredentials(existingConfig) } : credentials,
|
|
1035
1042
|
enabled: existingConfig["enabled"] ?? true,
|
|
1036
|
-
|
|
1043
|
+
// Written explicitly rather than left to the default: `backfill: false` is the one
|
|
1044
|
+
// setting someone is likely to go looking for, and a key that is not in the file is
|
|
1045
|
+
// not findable. An existing block is preserved untouched, so this never flips a
|
|
1046
|
+
// machine that had already opted in.
|
|
1047
|
+
capture: existingConfig["capture"] ?? { enabled: true, backfill: false },
|
|
1037
1048
|
// Enforcement stays off until the mapper is validated — capture only for now.
|
|
1038
1049
|
enforce: existingConfig["enforce"] ?? { mode: "off", failClosed: true },
|
|
1039
1050
|
// Whatever another endpoint wrote is preserved: one file, several endpoints, and
|
package/dist/bin/forwarder.mjs
CHANGED
|
@@ -18160,6 +18160,9 @@ function settingsFor(file, vendor) {
|
|
|
18160
18160
|
...file.enforce ?? override.enforce ? { enforce: { ...file.enforce, ...override.enforce } } : {}
|
|
18161
18161
|
};
|
|
18162
18162
|
}
|
|
18163
|
+
function resolveCapture(capture) {
|
|
18164
|
+
return { enabled: capture?.enabled ?? true, backfill: capture?.backfill ?? false };
|
|
18165
|
+
}
|
|
18163
18166
|
function readConfigFile(vendor) {
|
|
18164
18167
|
if (!existsSync(configPath())) {
|
|
18165
18168
|
throw new ConfigMissingError(`${configPath()} does not exist \u2014 run init.mjs to create it`);
|
|
@@ -18212,7 +18215,7 @@ function loadLocalConfig(vendor, options = {}) {
|
|
|
18212
18215
|
applicationId,
|
|
18213
18216
|
...(creds.userId ?? vendorFile.userId) !== void 0 ? { userId: creds.userId ?? vendorFile.userId } : {},
|
|
18214
18217
|
enabled: vendorFile.enabled ?? true,
|
|
18215
|
-
capture:
|
|
18218
|
+
capture: resolveCapture(vendorFile.capture),
|
|
18216
18219
|
enforce: {
|
|
18217
18220
|
mode: vendorFile.enforce?.mode ?? "off",
|
|
18218
18221
|
failClosed: vendorFile.enforce?.failClosed ?? true
|
|
@@ -18257,6 +18260,9 @@ function liveTranscripts(beat, now = Date.now()) {
|
|
|
18257
18260
|
return [...paths];
|
|
18258
18261
|
}
|
|
18259
18262
|
|
|
18263
|
+
// packages/core/dist/emit/emitter.js
|
|
18264
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
18265
|
+
|
|
18260
18266
|
// packages/core/dist/emit/ids.js
|
|
18261
18267
|
import { createHash, randomBytes } from "node:crypto";
|
|
18262
18268
|
var SPAN_ID_HEX = 16;
|
|
@@ -18296,6 +18302,20 @@ var SeededIdGenerator = class {
|
|
|
18296
18302
|
};
|
|
18297
18303
|
|
|
18298
18304
|
// packages/core/dist/emit/emitter.js
|
|
18305
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
18306
|
+
function capPayload(value, limit = PAYLOAD_LIMIT) {
|
|
18307
|
+
if (value === void 0 || value === null)
|
|
18308
|
+
return value;
|
|
18309
|
+
const text = typeof value === "string" ? value : JSON.stringify(value);
|
|
18310
|
+
if (text === void 0 || text.length <= limit)
|
|
18311
|
+
return value;
|
|
18312
|
+
const digest = createHash2("sha256").update(text).digest("hex").slice(0, 16);
|
|
18313
|
+
const marker = `\u2026 [truncated by darkhunt: ${text.length} chars total, sha256:${digest}]`;
|
|
18314
|
+
return `${text.slice(0, Math.max(0, limit - marker.length))}${marker}`;
|
|
18315
|
+
}
|
|
18316
|
+
function capText(text, limit = PAYLOAD_LIMIT) {
|
|
18317
|
+
return capPayload(text, limit);
|
|
18318
|
+
}
|
|
18299
18319
|
var TOOL_SUMMARY_LIMIT = 2e3;
|
|
18300
18320
|
function summarize(output) {
|
|
18301
18321
|
const text = typeof output === "string" ? output : JSON.stringify(output ?? null);
|
|
@@ -18422,7 +18442,7 @@ var SessionEmitter = class {
|
|
|
18422
18442
|
// A subagent's first record is the task it was given, and it has already been
|
|
18423
18443
|
// absorbed by the time this fires — so the child trace opens with its brief
|
|
18424
18444
|
// rather than empty.
|
|
18425
|
-
...this.lastUserText ? { input: this.lastUserText } : {},
|
|
18445
|
+
...this.lastUserText ? { input: capText(this.lastUserText) } : {},
|
|
18426
18446
|
...this.options.userId !== void 0 ? { userId: this.options.userId } : {}
|
|
18427
18447
|
}));
|
|
18428
18448
|
this.sidechains.push(owner);
|
|
@@ -18463,7 +18483,7 @@ var SessionEmitter = class {
|
|
|
18463
18483
|
case "thinking": {
|
|
18464
18484
|
this.openGeneration(record, owner);
|
|
18465
18485
|
const host = this.generation ?? owner;
|
|
18466
|
-
this.seeded(["thinking", record.uuid], () => host.span("thinking", { startTime: record.ts, output: record.text })).end({ endTime: record.ts });
|
|
18486
|
+
this.seeded(["thinking", record.uuid], () => host.span("thinking", { startTime: record.ts, output: capPayload(record.text) })).end({ endTime: record.ts });
|
|
18467
18487
|
break;
|
|
18468
18488
|
}
|
|
18469
18489
|
case "tool_call": {
|
|
@@ -18474,8 +18494,8 @@ var SessionEmitter = class {
|
|
|
18474
18494
|
startTime: record.ts,
|
|
18475
18495
|
...record.toolName !== void 0 ? { toolName: record.toolName } : {},
|
|
18476
18496
|
...record.toolCallId !== void 0 ? { toolCallId: record.toolCallId } : {},
|
|
18477
|
-
toolArguments: record.input,
|
|
18478
|
-
input: record.input
|
|
18497
|
+
toolArguments: capPayload(record.input),
|
|
18498
|
+
input: capPayload(record.input)
|
|
18479
18499
|
}));
|
|
18480
18500
|
if (record.toolCallId)
|
|
18481
18501
|
this.toolSpans.set(record.toolCallId, span);
|
|
@@ -18487,7 +18507,7 @@ var SessionEmitter = class {
|
|
|
18487
18507
|
const span = record.toolCallId ? this.toolSpans.get(record.toolCallId) : void 0;
|
|
18488
18508
|
if (span) {
|
|
18489
18509
|
span.end({
|
|
18490
|
-
output: record.output,
|
|
18510
|
+
output: capPayload(record.output),
|
|
18491
18511
|
endTime: record.ts,
|
|
18492
18512
|
...record.isError ? { level: "ERROR" } : {},
|
|
18493
18513
|
...record.errorKind !== void 0 ? { statusMessage: record.errorKind } : {}
|
|
@@ -18501,7 +18521,7 @@ var SessionEmitter = class {
|
|
|
18501
18521
|
this.endGeneration();
|
|
18502
18522
|
this.seeded(["compaction", record.uuid], () => owner.span("compaction", {
|
|
18503
18523
|
startTime: record.ts,
|
|
18504
|
-
...record.text ? { output: record.text } : {}
|
|
18524
|
+
...record.text ? { output: capPayload(record.text) } : {}
|
|
18505
18525
|
})).end({ endTime: record.ts });
|
|
18506
18526
|
break;
|
|
18507
18527
|
case "permission_grant": {
|
|
@@ -18563,7 +18583,7 @@ var SessionEmitter = class {
|
|
|
18563
18583
|
...this.title !== void 0 ? { name: this.title } : {},
|
|
18564
18584
|
// The pass's result. Paired with the `input` set when the trace opened, this is
|
|
18565
18585
|
// what stops the consumer inferring the trace's I/O from a descendant.
|
|
18566
|
-
...this.lastAssistantText !== void 0 ? { output: this.lastAssistantText } : {}
|
|
18586
|
+
...this.lastAssistantText !== void 0 ? { output: capText(this.lastAssistantText) } : {}
|
|
18567
18587
|
});
|
|
18568
18588
|
this.trace.end();
|
|
18569
18589
|
this.trace = void 0;
|
|
@@ -18646,7 +18666,7 @@ var SessionEmitter = class {
|
|
|
18646
18666
|
// What the agent was asked. `TraceArgs.input` is construction-only — the SDK's
|
|
18647
18667
|
// `update()` carries output alone — which is why `ingest` absorbs the user turn
|
|
18648
18668
|
// before it calls this.
|
|
18649
|
-
...this.lastUserText ? { input: this.lastUserText } : {},
|
|
18669
|
+
...this.lastUserText ? { input: capText(this.lastUserText) } : {},
|
|
18650
18670
|
tags: [this.options.vendor, ...this.options.agentId ? ["subagent"] : []],
|
|
18651
18671
|
metadata: {
|
|
18652
18672
|
...this.meta,
|
|
@@ -18715,7 +18735,7 @@ var SessionEmitter = class {
|
|
|
18715
18735
|
buildInputMessages() {
|
|
18716
18736
|
const messages = [];
|
|
18717
18737
|
if (this.lastUserText !== void 0) {
|
|
18718
|
-
messages.push({ role: "user", content: this.lastUserText });
|
|
18738
|
+
messages.push({ role: "user", content: capText(this.lastUserText) });
|
|
18719
18739
|
}
|
|
18720
18740
|
for (const result of this.pendingToolResults) {
|
|
18721
18741
|
messages.push({ role: "tool", content: result });
|
|
@@ -18725,7 +18745,7 @@ var SessionEmitter = class {
|
|
|
18725
18745
|
endGeneration() {
|
|
18726
18746
|
if (!this.generation)
|
|
18727
18747
|
return;
|
|
18728
|
-
const output = this.outputText.join("\n");
|
|
18748
|
+
const output = capText(this.outputText.join("\n"));
|
|
18729
18749
|
if (output)
|
|
18730
18750
|
this.lastAssistantText = output;
|
|
18731
18751
|
this.generation.end({
|
|
@@ -18754,8 +18774,9 @@ function installSeededIdGenerator(client) {
|
|
|
18754
18774
|
}
|
|
18755
18775
|
|
|
18756
18776
|
// packages/core/dist/forwarder/checkpoint.js
|
|
18757
|
-
import { mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3, renameSync as renameSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
18777
|
+
import { copyFileSync, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3, renameSync as renameSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
18758
18778
|
import { join as join6 } from "node:path";
|
|
18779
|
+
var SPOOL_KEY = "::spool::";
|
|
18759
18780
|
function checkpointPath(scope) {
|
|
18760
18781
|
return join6(CONFIG_DIR, `${scope}.checkpoints.json`);
|
|
18761
18782
|
}
|
|
@@ -18766,6 +18787,25 @@ function loadCheckpoints(scope) {
|
|
|
18766
18787
|
return {};
|
|
18767
18788
|
}
|
|
18768
18789
|
}
|
|
18790
|
+
function laggingTranscripts(checkpoints, now = statSize) {
|
|
18791
|
+
const paths = [];
|
|
18792
|
+
for (const [path, checkpoint] of Object.entries(checkpoints)) {
|
|
18793
|
+
if (path === SPOOL_KEY)
|
|
18794
|
+
continue;
|
|
18795
|
+
const size = now(path);
|
|
18796
|
+
if (size === void 0 || size === checkpoint.offset)
|
|
18797
|
+
continue;
|
|
18798
|
+
paths.push(path);
|
|
18799
|
+
}
|
|
18800
|
+
return paths;
|
|
18801
|
+
}
|
|
18802
|
+
function statSize(path) {
|
|
18803
|
+
try {
|
|
18804
|
+
return statSync2(path).size;
|
|
18805
|
+
} catch {
|
|
18806
|
+
return void 0;
|
|
18807
|
+
}
|
|
18808
|
+
}
|
|
18769
18809
|
function orphanedScopes(vendor, scope) {
|
|
18770
18810
|
const suffix = ".checkpoints.json";
|
|
18771
18811
|
try {
|
|
@@ -18849,6 +18889,7 @@ function readNewLines(path, offset, maxBytes = DEFAULT_MAX_BYTES) {
|
|
|
18849
18889
|
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
18850
18890
|
import { join as join7 } from "node:path";
|
|
18851
18891
|
var STALE_MS = 5 * 60 * 1e3;
|
|
18892
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
18852
18893
|
function acquireLock(scope) {
|
|
18853
18894
|
mkdirSync3(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
18854
18895
|
const path = join7(CONFIG_DIR, `${scope}.forwarder.lock`);
|
|
@@ -18870,7 +18911,17 @@ function acquireLock(scope) {
|
|
|
18870
18911
|
} catch {
|
|
18871
18912
|
return null;
|
|
18872
18913
|
}
|
|
18873
|
-
|
|
18914
|
+
const beat = setInterval(() => {
|
|
18915
|
+
try {
|
|
18916
|
+
writeFileSync3(path, JSON.stringify({ pid: process.pid, ts: Date.now() }), { mode: 384 });
|
|
18917
|
+
} catch {
|
|
18918
|
+
}
|
|
18919
|
+
}, HEARTBEAT_MS);
|
|
18920
|
+
beat.unref();
|
|
18921
|
+
return () => {
|
|
18922
|
+
clearInterval(beat);
|
|
18923
|
+
rmSync(path, { force: true });
|
|
18924
|
+
};
|
|
18874
18925
|
}
|
|
18875
18926
|
function isAlive(pid, kill = (p, s) => {
|
|
18876
18927
|
process.kill(p, s);
|
|
@@ -18971,6 +19022,65 @@ function saveHealth(scope, health) {
|
|
|
18971
19022
|
}
|
|
18972
19023
|
}
|
|
18973
19024
|
|
|
19025
|
+
// packages/core/dist/forwarder/pending.js
|
|
19026
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync4, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
19027
|
+
import { join as join9 } from "node:path";
|
|
19028
|
+
var MAX_PENDING_PATHS = 256;
|
|
19029
|
+
function pendingPath(scope) {
|
|
19030
|
+
return join9(CONFIG_DIR, `${scope}.pending.json`);
|
|
19031
|
+
}
|
|
19032
|
+
function loadPending(scope) {
|
|
19033
|
+
try {
|
|
19034
|
+
const backlog = JSON.parse(readFileSync6(pendingPath(scope), "utf8"));
|
|
19035
|
+
if (!Array.isArray(backlog.paths))
|
|
19036
|
+
return void 0;
|
|
19037
|
+
return backlog;
|
|
19038
|
+
} catch {
|
|
19039
|
+
return void 0;
|
|
19040
|
+
}
|
|
19041
|
+
}
|
|
19042
|
+
function pendingTranscripts(scope) {
|
|
19043
|
+
const backlog = loadPending(scope);
|
|
19044
|
+
if (!backlog)
|
|
19045
|
+
return [];
|
|
19046
|
+
return backlog.paths.filter((path) => {
|
|
19047
|
+
try {
|
|
19048
|
+
return existsSync3(path);
|
|
19049
|
+
} catch {
|
|
19050
|
+
return false;
|
|
19051
|
+
}
|
|
19052
|
+
});
|
|
19053
|
+
}
|
|
19054
|
+
function savePending(scope, paths, now = /* @__PURE__ */ new Date()) {
|
|
19055
|
+
try {
|
|
19056
|
+
const at = now.toISOString();
|
|
19057
|
+
const previous = loadPending(scope);
|
|
19058
|
+
const merged = [.../* @__PURE__ */ new Set([...previous?.paths ?? [], ...paths])];
|
|
19059
|
+
const kept = merged.slice(Math.max(0, merged.length - MAX_PENDING_PATHS));
|
|
19060
|
+
if (kept.length === 0)
|
|
19061
|
+
return;
|
|
19062
|
+
write(scope, { since: previous?.since ?? at, at, paths: kept });
|
|
19063
|
+
} catch {
|
|
19064
|
+
}
|
|
19065
|
+
}
|
|
19066
|
+
function clearPending(scope) {
|
|
19067
|
+
try {
|
|
19068
|
+
rmSync2(pendingPath(scope), { force: true });
|
|
19069
|
+
} catch {
|
|
19070
|
+
}
|
|
19071
|
+
}
|
|
19072
|
+
function write(scope, backlog) {
|
|
19073
|
+
mkdirSync5(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
19074
|
+
const target = pendingPath(scope);
|
|
19075
|
+
const tmp = `${target}.tmp`;
|
|
19076
|
+
writeFileSync5(tmp, JSON.stringify(backlog), { mode: 384 });
|
|
19077
|
+
renameSync4(tmp, target);
|
|
19078
|
+
}
|
|
19079
|
+
|
|
19080
|
+
// packages/core/dist/forwarder/retry.js
|
|
19081
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
19082
|
+
import { join as join10 } from "node:path";
|
|
19083
|
+
|
|
18974
19084
|
// packages/core/dist/forwarder/run.js
|
|
18975
19085
|
import { readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
|
|
18976
19086
|
|
|
@@ -21694,7 +21804,6 @@ function toFloat(value, fallback) {
|
|
|
21694
21804
|
}
|
|
21695
21805
|
|
|
21696
21806
|
// packages/core/dist/forwarder/run.js
|
|
21697
|
-
var SPOOL_KEY = "::spool::";
|
|
21698
21807
|
var DARKHUNT_SOURCE_HINT = "darkhunt-telemetry";
|
|
21699
21808
|
function drainSpool(mapper, checkpoints) {
|
|
21700
21809
|
const path = spoolPath(mapper.vendor);
|
|
@@ -21807,7 +21916,14 @@ async function runForwarder(mapper, options = {}) {
|
|
|
21807
21916
|
}
|
|
21808
21917
|
}
|
|
21809
21918
|
const drain = options.paths ? { paths: options.paths } : drainSpool(mapper, checkpoints);
|
|
21810
|
-
const named = options.paths ? drain.paths : [
|
|
21919
|
+
const named = options.paths ? drain.paths : [
|
|
21920
|
+
.../* @__PURE__ */ new Set([
|
|
21921
|
+
...drain.paths,
|
|
21922
|
+
...liveTranscripts(loadBeat(config.scope)),
|
|
21923
|
+
...pendingTranscripts(config.scope),
|
|
21924
|
+
...laggingTranscripts(checkpoints)
|
|
21925
|
+
])
|
|
21926
|
+
];
|
|
21811
21927
|
const paths = [...new Set(named.flatMap((path) => [path, ...related(mapper, path)]))];
|
|
21812
21928
|
if (paths.length === 0) {
|
|
21813
21929
|
if (drain.checkpoint)
|
|
@@ -21904,13 +22020,16 @@ async function runForwarder(mapper, options = {}) {
|
|
|
21904
22020
|
result.emitted = { transcripts: result.transcripts, records: result.records };
|
|
21905
22021
|
if (watch.failures() > 0) {
|
|
21906
22022
|
result.ok = false;
|
|
22023
|
+
result.retryable = true;
|
|
21907
22024
|
result.error = watch.reason() ?? "span export failed";
|
|
21908
22025
|
result.transcripts = 0;
|
|
21909
22026
|
result.records = 0;
|
|
22027
|
+
savePending(config.scope, paths);
|
|
21910
22028
|
} else {
|
|
21911
22029
|
if (drain.checkpoint)
|
|
21912
22030
|
staged[SPOOL_KEY] = drain.checkpoint;
|
|
21913
22031
|
saveCheckpoints(config.scope, staged);
|
|
22032
|
+
clearPending(config.scope);
|
|
21914
22033
|
}
|
|
21915
22034
|
const previous = loadHealth(config.scope);
|
|
21916
22035
|
saveHealth(config.scope, {
|
|
@@ -21962,17 +22081,103 @@ function discoverTranscripts(mapper) {
|
|
|
21962
22081
|
return found;
|
|
21963
22082
|
}
|
|
21964
22083
|
|
|
22084
|
+
// packages/core/dist/forwarder/retry.js
|
|
22085
|
+
var RETRY_DELAYS_MS = [
|
|
22086
|
+
3e4,
|
|
22087
|
+
6e4,
|
|
22088
|
+
12e4,
|
|
22089
|
+
3e5,
|
|
22090
|
+
6e5,
|
|
22091
|
+
9e5,
|
|
22092
|
+
18e5
|
|
22093
|
+
];
|
|
22094
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
22095
|
+
function retryClaimPath(scope) {
|
|
22096
|
+
return join10(CONFIG_DIR, `${scope}.forwarder-retry.lock`);
|
|
22097
|
+
}
|
|
22098
|
+
function claimRetry(scope, now = Date.now()) {
|
|
22099
|
+
const path = retryClaimPath(scope);
|
|
22100
|
+
try {
|
|
22101
|
+
mkdirSync6(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
22102
|
+
if (existsSync4(path)) {
|
|
22103
|
+
try {
|
|
22104
|
+
const held = JSON.parse(readFileSync7(path, "utf8"));
|
|
22105
|
+
if (isAlive(held.pid) && now - held.ts < CLAIM_STALE_MS)
|
|
22106
|
+
return null;
|
|
22107
|
+
} catch {
|
|
22108
|
+
}
|
|
22109
|
+
rmSync3(path, { force: true });
|
|
22110
|
+
}
|
|
22111
|
+
const stamp = () => {
|
|
22112
|
+
writeFileSync6(path, JSON.stringify({ pid: process.pid, ts: Date.now() }), { mode: 384 });
|
|
22113
|
+
};
|
|
22114
|
+
stamp();
|
|
22115
|
+
return {
|
|
22116
|
+
renew: () => {
|
|
22117
|
+
try {
|
|
22118
|
+
stamp();
|
|
22119
|
+
} catch {
|
|
22120
|
+
}
|
|
22121
|
+
},
|
|
22122
|
+
release: () => rmSync3(path, { force: true })
|
|
22123
|
+
};
|
|
22124
|
+
} catch {
|
|
22125
|
+
return null;
|
|
22126
|
+
}
|
|
22127
|
+
}
|
|
22128
|
+
function retriesEnabled() {
|
|
22129
|
+
const flag = process.env["DARKHUNT_FORWARDER_RETRY"];
|
|
22130
|
+
return flag !== "0" && flag !== "off" && flag !== "false";
|
|
22131
|
+
}
|
|
22132
|
+
function scopeOf(mapper, options) {
|
|
22133
|
+
try {
|
|
22134
|
+
return loadLocalConfig(mapper.vendor, options.profile !== void 0 ? { profile: options.profile } : {}).scope;
|
|
22135
|
+
} catch {
|
|
22136
|
+
return mapper.vendor;
|
|
22137
|
+
}
|
|
22138
|
+
}
|
|
22139
|
+
async function runForwarderWithRetry(mapper, options = {}) {
|
|
22140
|
+
const pass = options.pass ?? ((m, o) => runForwarder(m, o));
|
|
22141
|
+
const sleep2 = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
22142
|
+
const forwarding = {
|
|
22143
|
+
...options.paths !== void 0 ? { paths: options.paths } : {},
|
|
22144
|
+
...options.profile !== void 0 ? { profile: options.profile } : {}
|
|
22145
|
+
};
|
|
22146
|
+
let last = await pass(mapper, forwarding);
|
|
22147
|
+
if (!last.retryable || !retriesEnabled())
|
|
22148
|
+
return last;
|
|
22149
|
+
const claim = claimRetry(scopeOf(mapper, options));
|
|
22150
|
+
if (!claim)
|
|
22151
|
+
return last;
|
|
22152
|
+
try {
|
|
22153
|
+
const delays = options.delaysMs ?? RETRY_DELAYS_MS;
|
|
22154
|
+
for (const [index, delay] of delays.entries()) {
|
|
22155
|
+
options.onRetry?.(last, index + 1, delay);
|
|
22156
|
+
await sleep2(delay);
|
|
22157
|
+
claim.renew();
|
|
22158
|
+
last = await pass(mapper, forwarding);
|
|
22159
|
+
if (last.lockBusy)
|
|
22160
|
+
continue;
|
|
22161
|
+
if (!last.retryable)
|
|
22162
|
+
return last;
|
|
22163
|
+
}
|
|
22164
|
+
return last;
|
|
22165
|
+
} finally {
|
|
22166
|
+
claim.release();
|
|
22167
|
+
}
|
|
22168
|
+
}
|
|
22169
|
+
|
|
21965
22170
|
// packages/core/dist/cli/status.js
|
|
21966
22171
|
var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
|
|
21967
22172
|
|
|
21968
22173
|
// packages/core/dist/cli/enroll.js
|
|
21969
22174
|
import { homedir as homedir3 } from "node:os";
|
|
21970
|
-
import { join as
|
|
21971
|
-
var CLI_CREDENTIALS_PATH =
|
|
22175
|
+
import { join as join11 } from "node:path";
|
|
22176
|
+
var CLI_CREDENTIALS_PATH = join11(homedir3(), ".darkhunt", "credentials.json");
|
|
21972
22177
|
|
|
21973
22178
|
// adapters/codex/dist/transcript.js
|
|
21974
|
-
import { readFileSync as
|
|
21975
|
-
import { basename, join as
|
|
22179
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
22180
|
+
import { basename, join as join12 } from "node:path";
|
|
21976
22181
|
import { homedir as homedir4 } from "node:os";
|
|
21977
22182
|
function str(value) {
|
|
21978
22183
|
return typeof value === "string" ? value : void 0;
|
|
@@ -22116,7 +22321,7 @@ function stripSuffix(path) {
|
|
|
22116
22321
|
var codexTranscript = {
|
|
22117
22322
|
vendor: "codex",
|
|
22118
22323
|
sessionRoots() {
|
|
22119
|
-
return [
|
|
22324
|
+
return [join12(homedir4(), ".codex", "sessions")];
|
|
22120
22325
|
},
|
|
22121
22326
|
/**
|
|
22122
22327
|
* `~/.codex/auth.json` -> the `email` claim of `tokens.id_token`.
|
|
@@ -22138,7 +22343,7 @@ var codexTranscript = {
|
|
|
22138
22343
|
*/
|
|
22139
22344
|
resolveUserId() {
|
|
22140
22345
|
try {
|
|
22141
|
-
return emailFromAuth(
|
|
22346
|
+
return emailFromAuth(readFileSync8(join12(homedir4(), ".codex", "auth.json"), "utf8"));
|
|
22142
22347
|
} catch {
|
|
22143
22348
|
return void 0;
|
|
22144
22349
|
}
|
|
@@ -22350,7 +22555,7 @@ var codexTranscript = {
|
|
|
22350
22555
|
|
|
22351
22556
|
// adapters/codex/bin/forwarder.mjs
|
|
22352
22557
|
try {
|
|
22353
|
-
await
|
|
22558
|
+
await runForwarderWithRetry(codexTranscript);
|
|
22354
22559
|
} catch {
|
|
22355
22560
|
process.exit(1);
|
|
22356
22561
|
}
|
package/dist/bin/guard.mjs
CHANGED
|
@@ -228,13 +228,16 @@ function loadRuntimeSettings(vendor, options = {}) {
|
|
|
228
228
|
profile,
|
|
229
229
|
scope: scopeKey(vendor, profile),
|
|
230
230
|
enabled: vendorFile.enabled ?? true,
|
|
231
|
-
capture:
|
|
231
|
+
capture: resolveCapture(vendorFile.capture),
|
|
232
232
|
enforce: {
|
|
233
233
|
mode: vendorFile.enforce?.mode ?? "off",
|
|
234
234
|
failClosed: vendorFile.enforce?.failClosed ?? true
|
|
235
235
|
}
|
|
236
236
|
};
|
|
237
237
|
}
|
|
238
|
+
function resolveCapture(capture) {
|
|
239
|
+
return { enabled: capture?.enabled ?? true, backfill: capture?.backfill ?? false };
|
|
240
|
+
}
|
|
238
241
|
function readConfigFile(vendor) {
|
|
239
242
|
if (!existsSync(configPath())) {
|
|
240
243
|
throw new ConfigMissingError(`${configPath()} does not exist \u2014 run init.mjs to create it`);
|
|
@@ -393,12 +396,16 @@ async function readStdin(stream) {
|
|
|
393
396
|
return Buffer.concat(chunks).toString("utf8");
|
|
394
397
|
}
|
|
395
398
|
|
|
399
|
+
// packages/core/dist/emit/emitter.js
|
|
400
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
401
|
+
|
|
396
402
|
// packages/core/dist/forwarder/tail.js
|
|
397
403
|
var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
398
404
|
var LINE_CEILING = 64 * 1024 * 1024;
|
|
399
405
|
|
|
400
406
|
// packages/core/dist/forwarder/lock.js
|
|
401
407
|
var STALE_MS = 5 * 60 * 1e3;
|
|
408
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
402
409
|
var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
|
|
403
410
|
|
|
404
411
|
// node_modules/@darkhunt-security/telemetry/package.json
|
|
@@ -1327,6 +1334,9 @@ var VALIDATORS = Object.freeze({
|
|
|
1327
1334
|
// node_modules/@darkhunt-security/telemetry/dist/client.js
|
|
1328
1335
|
var LIB_VERSION = package_default.version;
|
|
1329
1336
|
|
|
1337
|
+
// packages/core/dist/forwarder/retry.js
|
|
1338
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
1339
|
+
|
|
1330
1340
|
// packages/core/dist/cli/status.js
|
|
1331
1341
|
var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
|
|
1332
1342
|
|
package/dist/bin/init.mjs
CHANGED
|
@@ -52,12 +52,16 @@ var SPOOL_DIR = join4(CONFIG_DIR, "spool");
|
|
|
52
52
|
// packages/core/dist/runtime/beat.js
|
|
53
53
|
var BEAT_LIVE_MS = 30 * 60 * 1e3;
|
|
54
54
|
|
|
55
|
+
// packages/core/dist/emit/emitter.js
|
|
56
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
57
|
+
|
|
55
58
|
// packages/core/dist/forwarder/tail.js
|
|
56
59
|
var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
57
60
|
var LINE_CEILING = 64 * 1024 * 1024;
|
|
58
61
|
|
|
59
62
|
// packages/core/dist/forwarder/lock.js
|
|
60
63
|
var STALE_MS = 5 * 60 * 1e3;
|
|
64
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
61
65
|
var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
|
|
62
66
|
|
|
63
67
|
// node_modules/@darkhunt-security/telemetry/package.json
|
|
@@ -986,6 +990,9 @@ var VALIDATORS = Object.freeze({
|
|
|
986
990
|
// node_modules/@darkhunt-security/telemetry/dist/client.js
|
|
987
991
|
var LIB_VERSION = package_default.version;
|
|
988
992
|
|
|
993
|
+
// packages/core/dist/forwarder/retry.js
|
|
994
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
995
|
+
|
|
989
996
|
// packages/core/dist/cli/init.js
|
|
990
997
|
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
991
998
|
function init(argv) {
|
|
@@ -1025,7 +1032,11 @@ function init(argv) {
|
|
|
1025
1032
|
// a named profile resolve without the flag on every later run.
|
|
1026
1033
|
...separateFile ? { profile, credentials: credsPath, ...stripCredentials(existingConfig) } : credentials,
|
|
1027
1034
|
enabled: existingConfig["enabled"] ?? true,
|
|
1028
|
-
|
|
1035
|
+
// Written explicitly rather than left to the default: `backfill: false` is the one
|
|
1036
|
+
// setting someone is likely to go looking for, and a key that is not in the file is
|
|
1037
|
+
// not findable. An existing block is preserved untouched, so this never flips a
|
|
1038
|
+
// machine that had already opted in.
|
|
1039
|
+
capture: existingConfig["capture"] ?? { enabled: true, backfill: false },
|
|
1029
1040
|
// Enforcement stays off until the mapper is validated — capture only for now.
|
|
1030
1041
|
enforce: existingConfig["enforce"] ?? { mode: "off", failClosed: true },
|
|
1031
1042
|
// Whatever another endpoint wrote is preserved: one file, several endpoints, and
|
package/dist/bin/spool.mjs
CHANGED
|
@@ -74,13 +74,16 @@ function loadRuntimeSettings(vendor, options = {}) {
|
|
|
74
74
|
profile,
|
|
75
75
|
scope: scopeKey(vendor, profile),
|
|
76
76
|
enabled: vendorFile.enabled ?? true,
|
|
77
|
-
capture:
|
|
77
|
+
capture: resolveCapture(vendorFile.capture),
|
|
78
78
|
enforce: {
|
|
79
79
|
mode: vendorFile.enforce?.mode ?? "off",
|
|
80
80
|
failClosed: vendorFile.enforce?.failClosed ?? true
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
+
function resolveCapture(capture) {
|
|
85
|
+
return { enabled: capture?.enabled ?? true, backfill: capture?.backfill ?? false };
|
|
86
|
+
}
|
|
84
87
|
function readConfigFile(vendor) {
|
|
85
88
|
if (!existsSync(configPath())) {
|
|
86
89
|
throw new ConfigMissingError(`${configPath()} does not exist \u2014 run init.mjs to create it`);
|
|
@@ -195,12 +198,16 @@ async function readStdin(stream) {
|
|
|
195
198
|
return Buffer.concat(chunks).toString("utf8");
|
|
196
199
|
}
|
|
197
200
|
|
|
201
|
+
// packages/core/dist/emit/emitter.js
|
|
202
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
203
|
+
|
|
198
204
|
// packages/core/dist/forwarder/tail.js
|
|
199
205
|
var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
200
206
|
var LINE_CEILING = 64 * 1024 * 1024;
|
|
201
207
|
|
|
202
208
|
// packages/core/dist/forwarder/lock.js
|
|
203
209
|
var STALE_MS = 5 * 60 * 1e3;
|
|
210
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
204
211
|
var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
|
|
205
212
|
|
|
206
213
|
// node_modules/@darkhunt-security/telemetry/package.json
|
|
@@ -1129,6 +1136,9 @@ var VALIDATORS = Object.freeze({
|
|
|
1129
1136
|
// node_modules/@darkhunt-security/telemetry/dist/client.js
|
|
1130
1137
|
var LIB_VERSION = package_default.version;
|
|
1131
1138
|
|
|
1139
|
+
// packages/core/dist/forwarder/retry.js
|
|
1140
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
1141
|
+
|
|
1132
1142
|
// packages/core/dist/cli/status.js
|
|
1133
1143
|
var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
|
|
1134
1144
|
|