@cybedefend/vibedefend 1.2.4 → 1.3.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/README.md +8 -1
- package/dist/config.js +15 -5
- package/dist/config.js.map +1 -1
- package/dist/doctor.js +23 -6
- package/dist/doctor.js.map +1 -1
- package/dist/guards-evaluator/redact.js +25 -0
- package/dist/guards-evaluator/redact.js.map +1 -1
- package/dist/hook-runner.js +838 -96
- package/dist/hooks/install.js +42 -10
- package/dist/hooks/install.js.map +1 -1
- package/dist/hooks/runtime/emit.js +35 -0
- package/dist/hooks/runtime/emit.js.map +1 -1
- package/dist/hooks/runtime/guard-rules-cache.js +24 -9
- package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
- package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
- package/dist/hooks/runtime/judge-cache.js +64 -0
- package/dist/hooks/runtime/judge-cache.js.map +1 -0
- package/dist/hooks/runtime/judge.js +45 -0
- package/dist/hooks/runtime/judge.js.map +1 -0
- package/dist/hooks/runtime/near-miss.js +362 -0
- package/dist/hooks/runtime/near-miss.js.map +1 -0
- package/dist/hooks/runtime/resolve.js +28 -15
- package/dist/hooks/runtime/resolve.js.map +1 -1
- package/dist/hooks/runtime/session-review.js +261 -28
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/sniff.js +1 -1
- package/dist/hooks/runtime/sniff.js.map +1 -1
- package/dist/hooks/runtime/user-prompt-submit.js +1 -1
- package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
- package/dist/prompts.js +13 -3
- package/dist/prompts.js.map +1 -1
- package/package.json +1 -1
package/dist/hooks/install.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* natively on Linux, macOS, AND Windows (the previous design needed
|
|
15
15
|
* Git Bash on Windows).
|
|
16
16
|
*/
|
|
17
|
-
import { copyFileSync, existsSync, rmSync } from 'node:fs';
|
|
17
|
+
import { copyFileSync, existsSync, readFileSync, rmSync } from 'node:fs';
|
|
18
18
|
import { dirname, join } from 'node:path';
|
|
19
19
|
import { fileURLToPath } from 'node:url';
|
|
20
20
|
import { detectInstallMode, resolveScriptPath, GLOBAL_MODES, } from '../self-update.js';
|
|
@@ -37,7 +37,10 @@ const LEGACY_HOOKS_DIR = home('.cybedefend', 'hooks');
|
|
|
37
37
|
*/
|
|
38
38
|
function locateBundledRunner() {
|
|
39
39
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
40
|
-
//
|
|
40
|
+
// The runner needs no decoy-guard (unlike the shim below): tsc emits
|
|
41
|
+
// src/hooks/runtime/index.ts → dist/hooks/runtime/index.js, so there is NO
|
|
42
|
+
// `dist/hooks/hook-runner.js` sibling to shadow the esbuild bundle. The
|
|
43
|
+
// first existing candidate below is always the real bundle at dist/.
|
|
41
44
|
const candidates = [
|
|
42
45
|
join(here, 'hook-runner.js'),
|
|
43
46
|
join(here, '..', 'dist', 'hook-runner.js'),
|
|
@@ -50,18 +53,46 @@ function locateBundledRunner() {
|
|
|
50
53
|
return null;
|
|
51
54
|
}
|
|
52
55
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
56
|
+
* A *runnable* shim is the esbuild bundle (`dist/shim.js`, built from
|
|
57
|
+
* `src/hooks/shim-entry.ts`): it INVOKES `runShim()` at top level, so
|
|
58
|
+
* `node hook-runner.js <sub>` actually resolves + imports the real runner.
|
|
59
|
+
*
|
|
60
|
+
* The tsc compile of `src/hooks/shim.ts` lands at `dist/hooks/shim.js` and
|
|
61
|
+
* only *exports* `runShim` — it never calls it. Installing THAT file makes
|
|
62
|
+
* every hook a silent no-op (exit 0, no output) → all Action Guards off: the
|
|
63
|
+
* fail-open we must never ship. Reject any candidate lacking the top-level
|
|
64
|
+
* `runShim()` invocation so the decoy can never be selected.
|
|
55
65
|
*/
|
|
56
|
-
function
|
|
57
|
-
|
|
66
|
+
function isRunnableShimBundle(path) {
|
|
67
|
+
let src;
|
|
68
|
+
try {
|
|
69
|
+
src = readFileSync(path, 'utf8');
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return src.includes('runShim()');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the bundled `shim.js` (esbuild output) shipped in our package.
|
|
78
|
+
* `baseDir` is this module's directory (injectable for tests):
|
|
79
|
+
* - production: <pkg>/dist/hooks/install.js → bundle at <pkg>/dist/shim.js
|
|
80
|
+
* - dev (tsx): <pkg>/src/hooks/install.ts → bundle at <pkg>/dist/shim.js
|
|
81
|
+
*
|
|
82
|
+
* Candidates are ordered so the real esbuild bundle wins, and each is
|
|
83
|
+
* content-validated (`isRunnableShimBundle`) so the tsc decoy at
|
|
84
|
+
* `dist/hooks/shim.js` — a sibling of this module in production — can never be
|
|
85
|
+
* selected. Returns null when no runnable bundle is found; the caller then
|
|
86
|
+
* safely falls back to copying the full runner.
|
|
87
|
+
*/
|
|
88
|
+
export function locateBundledShim(baseDir = dirname(fileURLToPath(import.meta.url))) {
|
|
58
89
|
const candidates = [
|
|
59
|
-
join(
|
|
60
|
-
join(
|
|
61
|
-
join(
|
|
90
|
+
join(baseDir, '..', 'shim.js'), // prod: dist/hooks → dist/shim.js
|
|
91
|
+
join(baseDir, '..', '..', 'dist', 'shim.js'), // dev: src/hooks → dist/shim.js
|
|
92
|
+
join(baseDir, 'shim.js'), // flattened-dist fallback (also the tsc decoy — validated away)
|
|
62
93
|
];
|
|
63
94
|
for (const c of candidates) {
|
|
64
|
-
if (existsSync(c))
|
|
95
|
+
if (existsSync(c) && isRunnableShimBundle(c))
|
|
65
96
|
return c;
|
|
66
97
|
}
|
|
67
98
|
return null;
|
|
@@ -129,6 +160,7 @@ export function installHookRuntime(opts, deps = {}) {
|
|
|
129
160
|
reviewThreshold: opts.hooks.reviewThreshold,
|
|
130
161
|
autoProposeMode: opts.hooks.autoProposeMode,
|
|
131
162
|
autoUpdate: useShim ? opts.hooks.autoUpdate : false,
|
|
163
|
+
enableDiffScan: opts.hooks.enableDiffScan,
|
|
132
164
|
},
|
|
133
165
|
installedVersion: opts.installedVersion,
|
|
134
166
|
...(useShim ? { runnerSource } : {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/hooks/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/hooks/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,4 +42,39 @@ export function emitContext(body, client) {
|
|
|
42
42
|
}
|
|
43
43
|
emit(body, client);
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Stop-hook emission — the Stop event's output contract differs from the
|
|
47
|
+
* plain-context hooks.
|
|
48
|
+
*
|
|
49
|
+
* On Claude Code, a Stop hook's **plain stdout is NOT surfaced to the model**
|
|
50
|
+
* (it only reaches the debug log) — so the gap-analysis (and the pre-commit
|
|
51
|
+
* diff-scan directive) was computed but never reached Claude (BACK-73). To make
|
|
52
|
+
* Claude act on it, a Stop hook must return JSON with `decision: "block"` and a
|
|
53
|
+
* `reason` — `reason` is the field Claude reads on a Stop block.
|
|
54
|
+
*
|
|
55
|
+
* Claude Code surfaces a Stop block's `reason` to the USER (in its block
|
|
56
|
+
* render) — and `hookSpecificOutput.additionalContext` is surfaced too, so it
|
|
57
|
+
* does NOT hide anything; putting the verbose directive there just re-dumps it.
|
|
58
|
+
* So we send a SINGLE, concise `reason` and nothing else. It stays actionable
|
|
59
|
+
* because the detailed CybeDefend workflow is already in the model's context
|
|
60
|
+
* (MCP `Server.instructions` + the per-prompt doctrine hook); the Stop reason
|
|
61
|
+
* only needs to TRIGGER it. When no concise `reason` is supplied we fall back
|
|
62
|
+
* to `body`.
|
|
63
|
+
*
|
|
64
|
+
* Cursor keeps its working `{ permission, agent_message }` envelope; every
|
|
65
|
+
* other client keeps plain markdown. Codex / VS Code / Windsurf Stop envelopes
|
|
66
|
+
* are a separate follow-up — their plain-stdout path is not the BACK-73 bug.
|
|
67
|
+
*/
|
|
68
|
+
export function emitStop(body, client, reason) {
|
|
69
|
+
if (!body)
|
|
70
|
+
return;
|
|
71
|
+
if (client === 'claude-code') {
|
|
72
|
+
process.stdout.write(JSON.stringify({
|
|
73
|
+
decision: 'block',
|
|
74
|
+
reason: reason && reason.trim() ? reason : body,
|
|
75
|
+
}));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
emit(body, client);
|
|
79
|
+
}
|
|
45
80
|
//# sourceMappingURL=emit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.js","sourceRoot":"","sources":["../../../src/hooks/runtime/emit.ts"],"names":[],"mappings":"AAgCA,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,MAAgB;IACjD,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;YAC7B,UAAU,EAAE,OAAO;YACnB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,qCAAqC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAgB;IACxD,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;YAC7B,kBAAkB,EAAE;gBAClB,aAAa,EAAE,cAAc;gBAC7B,iBAAiB,EAAE,IAAI;aACxB;SACF,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACrB,CAAC"}
|
|
1
|
+
{"version":3,"file":"emit.js","sourceRoot":"","sources":["../../../src/hooks/runtime/emit.ts"],"names":[],"mappings":"AAgCA,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,MAAgB;IACjD,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;YAC7B,UAAU,EAAE,OAAO;YACnB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,qCAAqC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAgB;IACxD,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;YAC7B,kBAAkB,EAAE;gBAClB,aAAa,EAAE,cAAc;gBAC7B,iBAAiB,EAAE,IAAI;aACxB;SACF,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAY,EACZ,MAAgB,EAChB,MAAe;IAEf,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CAAC;YACb,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;SAChD,CAAC,CACH,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACrB,CAAC"}
|
|
@@ -87,6 +87,8 @@ export function snakeToCamelRule(raw) {
|
|
|
87
87
|
denyMessage: (raw['deny_message'] ?? raw['denyMessage']),
|
|
88
88
|
warnMessage: (raw['warn_message'] ?? raw['warnMessage']),
|
|
89
89
|
defaultAction: (raw['default_action'] ?? raw['defaultAction']),
|
|
90
|
+
llmJudgeEnabled: (raw['llm_judge_enabled'] ?? raw['llmJudgeEnabled']),
|
|
91
|
+
catchEligible: (raw['catch_eligible'] ?? raw['catchEligible']),
|
|
90
92
|
};
|
|
91
93
|
}
|
|
92
94
|
/**
|
|
@@ -98,12 +100,10 @@ export function makeGuardRulesCache(opts) {
|
|
|
98
100
|
const fetchFn = opts.fetchFn;
|
|
99
101
|
async function refreshIfStale(ctx) {
|
|
100
102
|
const entry = readCache(ctx.projectId);
|
|
101
|
-
const ageSec = entry
|
|
102
|
-
? (Date.now() - entry.fetchedAt) / 1000
|
|
103
|
-
: Infinity;
|
|
103
|
+
const ageSec = entry ? (Date.now() - entry.fetchedAt) / 1000 : Infinity;
|
|
104
104
|
if (entry && ageSec < staleSec) {
|
|
105
105
|
// Cache is fresh — return immediately
|
|
106
|
-
return { kind: 'rules', rules: entry.rules };
|
|
106
|
+
return { kind: 'rules', rules: entry.rules, llmJudge: entry.llmJudge };
|
|
107
107
|
}
|
|
108
108
|
// Fetch (with ETag for conditional request if we have one)
|
|
109
109
|
try {
|
|
@@ -112,12 +112,12 @@ export function makeGuardRulesCache(opts) {
|
|
|
112
112
|
etag: entry?.etag ?? null,
|
|
113
113
|
});
|
|
114
114
|
if (result.notModified && entry) {
|
|
115
|
-
// 304 — touch the TTL and return original rules
|
|
115
|
+
// 304 — touch the TTL and return original rules + cached hint
|
|
116
116
|
writeCache({
|
|
117
117
|
...entry,
|
|
118
118
|
fetchedAt: Date.now(),
|
|
119
119
|
});
|
|
120
|
-
return { kind: 'rules', rules: entry.rules };
|
|
120
|
+
return { kind: 'rules', rules: entry.rules, llmJudge: entry.llmJudge };
|
|
121
121
|
}
|
|
122
122
|
// 200 — persist fresh rules (transform snake_case → camelCase)
|
|
123
123
|
const transformedRules = result.rules.map((r) => snakeToCamelRule(r));
|
|
@@ -126,9 +126,10 @@ export function makeGuardRulesCache(opts) {
|
|
|
126
126
|
rules: transformedRules,
|
|
127
127
|
etag: result.etag,
|
|
128
128
|
fetchedAt: Date.now(),
|
|
129
|
+
llmJudge: result.llmJudge ?? null,
|
|
129
130
|
};
|
|
130
131
|
writeCache(fresh);
|
|
131
|
-
return { kind: 'rules', rules: fresh.rules };
|
|
132
|
+
return { kind: 'rules', rules: fresh.rules, llmJudge: fresh.llmJudge };
|
|
132
133
|
}
|
|
133
134
|
catch (e) {
|
|
134
135
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -138,7 +139,7 @@ export function makeGuardRulesCache(opts) {
|
|
|
138
139
|
const ageSec = Math.round((Date.now() - entry.fetchedAt) / 1000);
|
|
139
140
|
process.stderr.write(`[VibeDefend] Action Guards: rule refresh failed (${msg}). ` +
|
|
140
141
|
`Using cached rules (age=${ageSec}s).\n`);
|
|
141
|
-
return { kind: 'rules', rules: entry.rules };
|
|
142
|
+
return { kind: 'rules', rules: entry.rules, llmJudge: entry.llmJudge };
|
|
142
143
|
}
|
|
143
144
|
// Cold start with no cached rules — fail-closed.
|
|
144
145
|
return {
|
|
@@ -212,6 +213,20 @@ export async function fetchEffectiveRulesFromGateway(ctx, opts = {}) {
|
|
|
212
213
|
const data = body.data ?? body;
|
|
213
214
|
const rules = Array.isArray(data.rules) ? data.rules : [];
|
|
214
215
|
const etag = res.headers.get('ETag');
|
|
215
|
-
|
|
216
|
+
const llmJudge = parseLlmJudgeHint(data['llm_judge']);
|
|
217
|
+
return { rules, etag, notModified: false, llmJudge };
|
|
218
|
+
}
|
|
219
|
+
/** Map the gateway's snake_case `llm_judge` block to the camelCase hint. */
|
|
220
|
+
function parseLlmJudgeHint(raw) {
|
|
221
|
+
if (!raw || typeof raw !== 'object')
|
|
222
|
+
return null;
|
|
223
|
+
const o = raw;
|
|
224
|
+
return {
|
|
225
|
+
enabled: Boolean(o['enabled']),
|
|
226
|
+
quotaRemaining: typeof o['quota_remaining'] === 'number'
|
|
227
|
+
? o['quota_remaining']
|
|
228
|
+
: -1,
|
|
229
|
+
quotaExhausted: Boolean(o['quota_exhausted']),
|
|
230
|
+
};
|
|
216
231
|
}
|
|
217
232
|
//# sourceMappingURL=guard-rules-cache.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard-rules-cache.js","sourceRoot":"","sources":["../../../src/hooks/runtime/guard-rules-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CACpC,OAAO,EAAE,EACT,aAAa,EACb,mBAAmB,CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"guard-rules-cache.js","sourceRoot":"","sources":["../../../src/hooks/runtime/guard-rules-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard-violations-buffer.js","sourceRoot":"","sources":["../../../src/hooks/runtime/guard-violations-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EACL,cAAc,EACd,UAAU,EACV,YAAY,EACZ,aAAa,EACb,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CACrC,OAAO,EAAE,EACT,aAAa,EACb,gCAAgC,CACjC,CAAC;
|
|
1
|
+
{"version":3,"file":"guard-violations-buffer.js","sourceRoot":"","sources":["../../../src/hooks/runtime/guard-violations-buffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BACK-74 — short-TTL on-disk verdict cache for retry de-duplication.
|
|
3
|
+
*
|
|
4
|
+
* When an agent retries the same action (same target hash + rule set), the hook
|
|
5
|
+
* returns the cached verdict instead of re-calling the judge — avoiding a
|
|
6
|
+
* second LLM round-trip AND a second quota decrement. The gateway also dedups
|
|
7
|
+
* server-side (Redis); this client cache is the first, cheapest line.
|
|
8
|
+
*
|
|
9
|
+
* Best-effort: any FS/JSON error degrades to "no cache" (the judge is simply
|
|
10
|
+
* re-called). Keyed by `${actionHash}|${sortedRuleIds}|${phase}`.
|
|
11
|
+
*/
|
|
12
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
13
|
+
import { dirname, join } from 'node:path';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
export const DEFAULT_JUDGE_CACHE_FILE = join(homedir(), '.cybedefend', 'guards-judge-cache.json');
|
|
16
|
+
export const DEFAULT_JUDGE_TTL_MS = 120_000;
|
|
17
|
+
export function makeJudgeCache(opts = {}) {
|
|
18
|
+
const cacheFile = opts.cacheFile ?? DEFAULT_JUDGE_CACHE_FILE;
|
|
19
|
+
const ttlMs = opts.ttlMs ?? DEFAULT_JUDGE_TTL_MS;
|
|
20
|
+
const now = opts.now ?? (() => Date.now());
|
|
21
|
+
function readAll() {
|
|
22
|
+
if (!existsSync(cacheFile))
|
|
23
|
+
return {};
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(readFileSync(cacheFile, 'utf8'));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function get(key) {
|
|
32
|
+
const entry = readAll()[key];
|
|
33
|
+
if (!entry)
|
|
34
|
+
return null;
|
|
35
|
+
if (now() - entry.at > ttlMs)
|
|
36
|
+
return null;
|
|
37
|
+
return entry.res;
|
|
38
|
+
}
|
|
39
|
+
function set(key, res) {
|
|
40
|
+
try {
|
|
41
|
+
const all = readAll();
|
|
42
|
+
const t = now();
|
|
43
|
+
// Prune expired entries so the file can't grow unbounded.
|
|
44
|
+
for (const k of Object.keys(all)) {
|
|
45
|
+
if (t - all[k].at > ttlMs)
|
|
46
|
+
delete all[k];
|
|
47
|
+
}
|
|
48
|
+
all[key] = { res, at: t };
|
|
49
|
+
ensureDirFor(cacheFile);
|
|
50
|
+
writeFileSync(cacheFile, JSON.stringify(all), 'utf8');
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Best-effort — never block the hook on an I/O error.
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { get, set };
|
|
57
|
+
}
|
|
58
|
+
function ensureDirFor(filePath) {
|
|
59
|
+
const dir = dirname(filePath);
|
|
60
|
+
if (!existsSync(dir)) {
|
|
61
|
+
mkdirSync(dir, { recursive: true });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=judge-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"judge-cache.js","sourceRoot":"","sources":["../../../src/hooks/runtime/judge-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAC1C,OAAO,EAAE,EACT,aAAa,EACb,yBAAyB,CAC1B,CAAC;AACF,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAiB5C,MAAM,UAAU,cAAc,CAAC,OAA0B,EAAE;IACzD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,wBAAwB,CAAC;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,oBAAoB,CAAC;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAE3C,SAAS,OAAO;QACd,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,EAAE,CAAC;QACtC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAe,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,SAAS,GAAG,CAAC,GAAW;QACtB,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,GAAG,KAAK;YAAE,OAAO,IAAI,CAAC;QAC1C,OAAO,KAAK,CAAC,GAAG,CAAC;IACnB,CAAC;IAED,SAAS,GAAG,CAAC,GAAW,EAAE,GAAgB;QACxC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC;YAChB,0DAA0D;YAC1D,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK;oBAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3C,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;YAC1B,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,sDAAsD;QACxD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const DEFAULT_TIMEOUT_MS = 1_500;
|
|
2
|
+
export async function callJudge(input, opts = {}) {
|
|
3
|
+
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
4
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
5
|
+
const url = `${input.apiBaseResolved}/project/${encodeURIComponent(input.projectId)}/action-guards/judge`;
|
|
6
|
+
try {
|
|
7
|
+
const res = await f(url, {
|
|
8
|
+
method: 'POST',
|
|
9
|
+
headers: {
|
|
10
|
+
Authorization: `Bearer ${input.token}`,
|
|
11
|
+
'Content-Type': 'application/json',
|
|
12
|
+
},
|
|
13
|
+
body: JSON.stringify({
|
|
14
|
+
tool: input.tool,
|
|
15
|
+
agent: input.agent,
|
|
16
|
+
session_id: input.sessionId,
|
|
17
|
+
phase: input.phase ?? 'confirm',
|
|
18
|
+
action_summary: input.actionSummary,
|
|
19
|
+
action_hash: input.actionHash,
|
|
20
|
+
rules: input.rules,
|
|
21
|
+
}),
|
|
22
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
23
|
+
});
|
|
24
|
+
if (!res.ok)
|
|
25
|
+
return null;
|
|
26
|
+
const body = (await res.json());
|
|
27
|
+
const data = body.data ?? body;
|
|
28
|
+
const decision = data['decision'];
|
|
29
|
+
if (decision !== 'block' && decision !== 'allow')
|
|
30
|
+
return null;
|
|
31
|
+
return {
|
|
32
|
+
decision,
|
|
33
|
+
reason: typeof data['reason'] === 'string' ? data['reason'] : '',
|
|
34
|
+
model: typeof data['model'] === 'string' ? data['model'] : '',
|
|
35
|
+
quotaRemaining: typeof data['quota_remaining'] === 'number'
|
|
36
|
+
? data['quota_remaining']
|
|
37
|
+
: -1,
|
|
38
|
+
quotaExceeded: Boolean(data['quota_exceeded']),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=judge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"judge.js","sourceRoot":"","sources":["../../../src/hooks/runtime/judge.ts"],"names":[],"mappings":"AA6CA,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,KAAiB,EACjB,OAAoE,EAAE;IAEtE,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC;IACvD,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,eAAe,YAAY,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,sBAAsB,CAAC;IAE1G,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE;YACvB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;gBACtC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,UAAU,EAAE,KAAK,CAAC,SAAS;gBAC3B,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,SAAS;gBAC/B,cAAc,EAAE,KAAK,CAAC,aAAa;gBACnC,WAAW,EAAE,KAAK,CAAC,UAAU;gBAC7B,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB,CAAC;YACF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;SACvC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAEzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA4B,CAAC;QAC3D,MAAM,IAAI,GAAI,IAAI,CAAC,IAAgC,IAAI,IAAI,CAAC;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QAE9D,OAAO;YACL,QAAQ;YACR,MAAM,EACJ,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAI,CAAC,QAAQ,CAAY,CAAC,CAAC,CAAC,EAAE;YACtE,KAAK,EAAE,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAI,CAAC,OAAO,CAAY,CAAC,CAAC,CAAC,EAAE;YACzE,cAAc,EACZ,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,QAAQ;gBACzC,CAAC,CAAE,IAAI,CAAC,iBAAiB,CAAY;gBACrC,CAAC,CAAC,CAAC,CAAC;YACR,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;SAC/C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|