@cybedefend/vibedefend 1.4.6 → 1.4.7
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/dist/hook-runner.js +386 -142
- package/dist/hooks/runtime/api.js +29 -2
- package/dist/hooks/runtime/api.js.map +1 -1
- package/dist/hooks/runtime/fetch-rules.js +27 -1
- package/dist/hooks/runtime/fetch-rules.js.map +1 -1
- package/dist/hooks/runtime/guard-rules-cache.js +25 -3
- package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
- package/dist/hooks/runtime/judge.js +10 -2
- package/dist/hooks/runtime/judge.js.map +1 -1
- package/dist/hooks/runtime/usage-block.js +199 -0
- package/dist/hooks/runtime/usage-block.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
import { readUsageWarning, readVibedefendBlock, } from './usage-block.js';
|
|
2
|
+
/**
|
|
3
|
+
* Report the usage signal of `res` to `listener`. Returns true when the
|
|
4
|
+
* answer is a success the caller may read. A block still returns false (no
|
|
5
|
+
* rules), exactly like any other non-2xx: only the listener tells them apart.
|
|
6
|
+
* A throwing listener is ignored — the hook must never crash on a notice.
|
|
7
|
+
*/
|
|
8
|
+
export async function reportUsageSignal(res, listener) {
|
|
9
|
+
const emit = (signal) => {
|
|
10
|
+
try {
|
|
11
|
+
listener?.(signal);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// best-effort
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
if (!res.ok) {
|
|
18
|
+
const block = await readVibedefendBlock(res);
|
|
19
|
+
if (block)
|
|
20
|
+
emit({ kind: 'blocked', block });
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const warning = readUsageWarning(res);
|
|
24
|
+
if (warning)
|
|
25
|
+
emit({ kind: 'warning', warning });
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
1
28
|
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
2
29
|
/**
|
|
3
30
|
* POST /project/<id>/business-rules/fetch
|
|
@@ -29,7 +56,7 @@ export async function fetchBusinessRules(opts) {
|
|
|
29
56
|
catch {
|
|
30
57
|
return null;
|
|
31
58
|
}
|
|
32
|
-
if (!res.
|
|
59
|
+
if (!(await reportUsageSignal(res, opts.onUsageSignal)))
|
|
33
60
|
return null;
|
|
34
61
|
let body;
|
|
35
62
|
try {
|
|
@@ -80,7 +107,7 @@ export async function fetchSecurityRules(opts) {
|
|
|
80
107
|
catch {
|
|
81
108
|
return null;
|
|
82
109
|
}
|
|
83
|
-
if (!res.
|
|
110
|
+
if (!(await reportUsageSignal(res, opts.onUsageSignal)))
|
|
84
111
|
return null;
|
|
85
112
|
let body;
|
|
86
113
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/hooks/runtime/api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/hooks/runtime/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { sniff } from './sniff.js';
|
|
17
17
|
import { resolveProjectIdWithApi, resolveToken, } from './resolve.js';
|
|
18
|
-
import { fetchBusinessRules, fetchSecurityRules } from './api.js';
|
|
18
|
+
import { fetchBusinessRules, fetchSecurityRules, } from './api.js';
|
|
19
|
+
import { makeUsageNotifier } from './usage-block.js';
|
|
19
20
|
import { emitContext } from './emit.js';
|
|
20
21
|
import { loadRuntimeConfig, readStdinJson } from './config.js';
|
|
21
22
|
/**
|
|
@@ -42,6 +43,7 @@ export async function fetchRulesHook(deps = {}) {
|
|
|
42
43
|
const fetchRules = deps.fetchRulesFn ?? fetchBusinessRules;
|
|
43
44
|
const fetchSecRules = deps.fetchSecurityRulesFn ?? fetchSecurityRules;
|
|
44
45
|
const emitFn = deps.emitFn ?? emitPreToolUseContext;
|
|
46
|
+
const usageNotifier = deps.usageNotifier ?? makeUsageNotifier();
|
|
45
47
|
const stdin = await readStdin();
|
|
46
48
|
const event = sniff(stdin);
|
|
47
49
|
// Self-filter: ignore tool calls we don't care about. Crucial for
|
|
@@ -70,6 +72,18 @@ export async function fetchRulesHook(deps = {}) {
|
|
|
70
72
|
// for all of them and label the callout with the whole list.
|
|
71
73
|
const files = event.filePaths.length > 0 ? event.filePaths : [event.filePath];
|
|
72
74
|
const fileLabel = files.join(', ');
|
|
75
|
+
// VibeDefend usage billing: a refused unit (402 VIBEDEFEND_BLOCKED) and a
|
|
76
|
+
// usage warning are told to the agent once per session, in a fixed sentence.
|
|
77
|
+
// A refusal returns `null` like an outage, so nothing else changes.
|
|
78
|
+
const sessionId = sessionIdOf(stdin);
|
|
79
|
+
const usageNotices = [];
|
|
80
|
+
const onUsageSignal = (signal) => {
|
|
81
|
+
const sentence = signal.kind === 'blocked'
|
|
82
|
+
? usageNotifier.notifyBlock(sessionId, signal.block)
|
|
83
|
+
: usageNotifier.notifyWarning(sessionId, signal.warning);
|
|
84
|
+
if (sentence)
|
|
85
|
+
usageNotices.push(sentence);
|
|
86
|
+
};
|
|
73
87
|
const fetchOpts = {
|
|
74
88
|
apiBase,
|
|
75
89
|
projectId,
|
|
@@ -77,6 +91,7 @@ export async function fetchRulesHook(deps = {}) {
|
|
|
77
91
|
files,
|
|
78
92
|
intent,
|
|
79
93
|
topK: 5,
|
|
94
|
+
onUsageSignal,
|
|
80
95
|
};
|
|
81
96
|
// Fetch both corpora in parallel. They are independent — either one
|
|
82
97
|
// failing (returning null) must NEVER suppress the other's block.
|
|
@@ -99,9 +114,20 @@ export async function fetchRulesHook(deps = {}) {
|
|
|
99
114
|
securityResult.markdown.length > 0) {
|
|
100
115
|
blocks.push(composeSecurityBody(securityResult.markdown, securityResult.total, fileLabel));
|
|
101
116
|
}
|
|
117
|
+
if (usageNotices.length > 0) {
|
|
118
|
+
blocks.push(['## CybeDefend VibeDefend usage', ...usageNotices.map((n) => `- ${n}`), ''].join('\n'));
|
|
119
|
+
}
|
|
102
120
|
if (blocks.length > 0)
|
|
103
121
|
emitFn(blocks.join('\n'), event.client);
|
|
104
122
|
}
|
|
123
|
+
/** The agent's session id, as the guard reads it (`session_id` or `sessionId`). */
|
|
124
|
+
function sessionIdOf(stdin) {
|
|
125
|
+
if (typeof stdin.session_id === 'string' && stdin.session_id)
|
|
126
|
+
return stdin.session_id;
|
|
127
|
+
if (typeof stdin.sessionId === 'string' && stdin.sessionId)
|
|
128
|
+
return stdin.sessionId;
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
105
131
|
/** Build the retrieval `intent` string from the event content. */
|
|
106
132
|
function buildIntent(event) {
|
|
107
133
|
const limit = parseInt(process.env.CYBEDEFEND_INTENT_BYTES ?? '800', 10);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-rules.js","sourceRoot":"","sources":["../../../src/hooks/runtime/fetch-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EACL,uBAAuB,EACvB,YAAY,GAEb,MAAM,cAAc,CAAC;AACtB,OAAO,
|
|
1
|
+
{"version":3,"file":"fetch-rules.js","sourceRoot":"","sources":["../../../src/hooks/runtime/fetch-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,7 @@ import { homedir } from 'node:os';
|
|
|
31
31
|
import { join } from 'node:path';
|
|
32
32
|
import { validateRule } from '../../guards-evaluator/index.js';
|
|
33
33
|
import { parseRuleFields } from './rule-schema.js';
|
|
34
|
+
import { readVibedefendBlock } from './usage-block.js';
|
|
34
35
|
export const DEFAULT_CACHE_FILE = join(homedir(), '.cybedefend', 'guards-cache.json');
|
|
35
36
|
export const DEFAULT_STALE_SEC = 60;
|
|
36
37
|
// ─── Category-id → evaluator category string ─────────────────────────────────
|
|
@@ -181,15 +182,31 @@ export function makeGuardRulesCache(opts) {
|
|
|
181
182
|
const ageSec = entry ? (Date.now() - entry.fetchedAt) / 1000 : Infinity;
|
|
182
183
|
if (entry && ageSec < staleSec) {
|
|
183
184
|
// Cache is fresh — return immediately
|
|
185
|
+
if (entry.blocked)
|
|
186
|
+
return { kind: 'blocked', block: entry.blocked };
|
|
184
187
|
return { kind: 'rules', rules: entry.rules, llmJudge: entry.llmJudge };
|
|
185
188
|
}
|
|
186
189
|
// Fetch (with ETag for conditional request if we have one)
|
|
187
190
|
try {
|
|
188
191
|
const result = await fetchFn({
|
|
189
192
|
...ctx,
|
|
190
|
-
etag: entry?.etag ?? null,
|
|
193
|
+
etag: entry?.blocked ? null : (entry?.etag ?? null),
|
|
191
194
|
});
|
|
192
|
-
if (result.
|
|
195
|
+
if (result.blocked) {
|
|
196
|
+
// Usage billing refused the rules: no guard, whatever is cached. The
|
|
197
|
+
// refusal is cached like rules (same TTL), so it is not refetched on
|
|
198
|
+
// every tool call, and it lifts at the first refresh that serves rules.
|
|
199
|
+
writeCache({
|
|
200
|
+
projectId: ctx.projectId,
|
|
201
|
+
rules: [],
|
|
202
|
+
etag: null,
|
|
203
|
+
fetchedAt: Date.now(),
|
|
204
|
+
llmJudge: null,
|
|
205
|
+
blocked: result.blocked,
|
|
206
|
+
});
|
|
207
|
+
return { kind: 'blocked', block: result.blocked };
|
|
208
|
+
}
|
|
209
|
+
if (result.notModified && entry && !entry.blocked) {
|
|
193
210
|
// 304 — touch the TTL and return original rules + cached hint
|
|
194
211
|
writeCache({
|
|
195
212
|
...entry,
|
|
@@ -214,7 +231,7 @@ export function makeGuardRulesCache(opts) {
|
|
|
214
231
|
}
|
|
215
232
|
catch (e) {
|
|
216
233
|
const msg = e instanceof Error ? e.message : String(e);
|
|
217
|
-
if (entry?.rules?.length) {
|
|
234
|
+
if (entry?.rules?.length && !entry.blocked) {
|
|
218
235
|
// We have something to work with — use cached rules and emit a warning
|
|
219
236
|
// so the operator is aware that there is an auth/network issue brewing.
|
|
220
237
|
const ageSec = Math.round((Date.now() - entry.fetchedAt) / 1000);
|
|
@@ -288,6 +305,11 @@ export async function fetchEffectiveRulesFromGateway(ctx, opts = {}) {
|
|
|
288
305
|
return { rules: [], etag: ctx.etag ?? null, notModified: true };
|
|
289
306
|
}
|
|
290
307
|
if (!res.ok) {
|
|
308
|
+
// VibeDefend usage billing: a refusal is an answer, not an outage.
|
|
309
|
+
const blocked = await readVibedefendBlock(res);
|
|
310
|
+
if (blocked) {
|
|
311
|
+
return { rules: [], etag: null, notModified: false, blocked };
|
|
312
|
+
}
|
|
291
313
|
throw new Error(`HTTP ${res.status} from effective-rules endpoint`);
|
|
292
314
|
}
|
|
293
315
|
const body = (await res.json());
|
|
@@ -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;AACjC,OAAO,EAAE,YAAY,EAAa,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,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,3 +1,7 @@
|
|
|
1
|
+
import { readUsageWarning, readVibedefendBlock, } from './usage-block.js';
|
|
2
|
+
export function isJudgeBlocked(res) {
|
|
3
|
+
return res !== null && 'blocked' in res;
|
|
4
|
+
}
|
|
1
5
|
const DEFAULT_TIMEOUT_MS = 1_500;
|
|
2
6
|
export async function callJudge(input, opts = {}) {
|
|
3
7
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
@@ -21,8 +25,11 @@ export async function callJudge(input, opts = {}) {
|
|
|
21
25
|
}),
|
|
22
26
|
signal: AbortSignal.timeout(timeoutMs),
|
|
23
27
|
});
|
|
24
|
-
if (!res.ok)
|
|
25
|
-
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
const blocked = await readVibedefendBlock(res);
|
|
30
|
+
return blocked ? { blocked } : null;
|
|
31
|
+
}
|
|
32
|
+
const usageWarning = readUsageWarning(res);
|
|
26
33
|
const body = (await res.json());
|
|
27
34
|
const data = body.data ?? body;
|
|
28
35
|
const decision = data['decision'];
|
|
@@ -36,6 +43,7 @@ export async function callJudge(input, opts = {}) {
|
|
|
36
43
|
? data['quota_remaining']
|
|
37
44
|
: -1,
|
|
38
45
|
quotaExceeded: Boolean(data['quota_exceeded']),
|
|
46
|
+
...(usageWarning ? { usageWarning } : {}),
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
49
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"judge.js","sourceRoot":"","sources":["../../../src/hooks/runtime/judge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"judge.js","sourceRoot":"","sources":["../../../src/hooks/runtime/judge.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAGpB,MAAM,kBAAkB,CAAC;AAiD1B,MAAM,UAAU,cAAc,CAC5B,GAAsC;IAEtC,OAAO,GAAG,KAAK,IAAI,IAAI,SAAS,IAAI,GAAG,CAAC;AAC1C,CAAC;AAED,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,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAC;YAC/C,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACtC,CAAC;QACD,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAE3C,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;YAC9C,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VibeDefend usage billing — what the hook does when the gateway says an
|
|
3
|
+
* organisation's usage is blocked or close to its limit.
|
|
4
|
+
*
|
|
5
|
+
* The gateway answers a refused unit with HTTP 402 and the body
|
|
6
|
+
* `{ success: false, code: 'VIBEDEFEND_BLOCKED', reason, unit, message }`, and
|
|
7
|
+
* flags a successful answer close to a limit with the header
|
|
8
|
+
* `x-vibedefend-usage-warning: <unit>:<approaching_limit|limit_reached>`.
|
|
9
|
+
*
|
|
10
|
+
* A block is NOT an outage: it must not trip the "policy engine unreachable"
|
|
11
|
+
* banner on every tool call, nor be retried on every call. It is told to the
|
|
12
|
+
* user once per session, in a fixed sentence per reason. The server's
|
|
13
|
+
* `message`, `reason` and `unit` are never printed as such: each is compared
|
|
14
|
+
* against the fixed values below, and only the matched literal picks a
|
|
15
|
+
* sentence (an unknown value reads as `unknown`).
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { homedir } from 'node:os';
|
|
19
|
+
import { dirname, join } from 'node:path';
|
|
20
|
+
export const BLOCKED_CODE = 'VIBEDEFEND_BLOCKED';
|
|
21
|
+
export const USAGE_WARNING_HEADER = 'x-vibedefend-usage-warning';
|
|
22
|
+
const UNITS = ['injection', 'judgment', 'diff_scan'];
|
|
23
|
+
const REASONS = [
|
|
24
|
+
'free_tier_exhausted',
|
|
25
|
+
'cap_reached',
|
|
26
|
+
'unpaid',
|
|
27
|
+
'product_inactive',
|
|
28
|
+
];
|
|
29
|
+
const WARNINGS = [
|
|
30
|
+
'approaching_limit',
|
|
31
|
+
'limit_reached',
|
|
32
|
+
];
|
|
33
|
+
function pick(allowed, value) {
|
|
34
|
+
return allowed.find((v) => v === value);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Read a gateway answer as a VibeDefend block. `null` for anything else —
|
|
38
|
+
* another status, another code, a body that is not JSON — which the caller
|
|
39
|
+
* keeps treating as it always has (fail-open).
|
|
40
|
+
*
|
|
41
|
+
* Consumes the body of a 402 only; any other response is left untouched.
|
|
42
|
+
*/
|
|
43
|
+
export async function readVibedefendBlock(res) {
|
|
44
|
+
if (res.status !== 402)
|
|
45
|
+
return null;
|
|
46
|
+
let body;
|
|
47
|
+
try {
|
|
48
|
+
body = await res.json();
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
if (!body || typeof body !== 'object')
|
|
54
|
+
return null;
|
|
55
|
+
const root = body;
|
|
56
|
+
const data = root.data && typeof root.data === 'object'
|
|
57
|
+
? root.data
|
|
58
|
+
: root;
|
|
59
|
+
const source = data.code === BLOCKED_CODE ? data : root;
|
|
60
|
+
if (source.code !== BLOCKED_CODE)
|
|
61
|
+
return null;
|
|
62
|
+
return {
|
|
63
|
+
reason: pick(REASONS, source.reason) ?? 'unknown',
|
|
64
|
+
unit: pick(UNITS, source.unit) ?? 'unknown',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Read the usage warning header of a successful answer, `null` if absent or not one of the fixed values. */
|
|
68
|
+
export function readUsageWarning(res) {
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = res.headers?.get?.(USAGE_WARNING_HEADER);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (typeof raw !== 'string')
|
|
77
|
+
return null;
|
|
78
|
+
const parts = raw.trim().split(':');
|
|
79
|
+
if (parts.length !== 2)
|
|
80
|
+
return null;
|
|
81
|
+
const unit = pick(UNITS, parts[0]);
|
|
82
|
+
const warning = pick(WARNINGS, parts[1]);
|
|
83
|
+
if (!unit || !warning)
|
|
84
|
+
return null;
|
|
85
|
+
return { unit, warning };
|
|
86
|
+
}
|
|
87
|
+
const UNIT_LABEL = {
|
|
88
|
+
injection: 'Security rules injection',
|
|
89
|
+
judgment: 'Action Guards judgments',
|
|
90
|
+
diff_scan: 'Diff scans',
|
|
91
|
+
unknown: 'Part of VibeDefend',
|
|
92
|
+
};
|
|
93
|
+
/** What stops when the unit is blocked. */
|
|
94
|
+
const UNIT_EFFECT = {
|
|
95
|
+
injection: 'no security or business rules are added to your edits',
|
|
96
|
+
judgment: 'Action Guards are off for this session',
|
|
97
|
+
diff_scan: 'no diff scan can be started',
|
|
98
|
+
unknown: 'part of VibeDefend is paused',
|
|
99
|
+
};
|
|
100
|
+
/** One fixed sentence per reason. The unit only picks among fixed labels. */
|
|
101
|
+
export function blockSentence(block) {
|
|
102
|
+
const label = UNIT_LABEL[block.unit];
|
|
103
|
+
const effect = UNIT_EFFECT[block.unit];
|
|
104
|
+
switch (block.reason) {
|
|
105
|
+
case 'free_tier_exhausted':
|
|
106
|
+
return (`VibeDefend paused: ${label} used up this month's free tier, so ${effect}. ` +
|
|
107
|
+
'An administrator of your organisation can add a card in the VibeDefend usage page to continue.');
|
|
108
|
+
case 'cap_reached':
|
|
109
|
+
return (`VibeDefend paused: ${label} reached the monthly spending cap of your organisation, so ${effect}. ` +
|
|
110
|
+
'An administrator can raise the cap in the VibeDefend usage page.');
|
|
111
|
+
case 'unpaid':
|
|
112
|
+
return ("VibeDefend paused: your organisation's last VibeDefend invoice is unpaid, so rules, Action Guards and diff scans are off. " +
|
|
113
|
+
'An administrator can update the card in the VibeDefend usage page.');
|
|
114
|
+
case 'product_inactive':
|
|
115
|
+
return ('VibeDefend is not active for your organisation, so rules, Action Guards and diff scans are off. ' +
|
|
116
|
+
'An administrator can activate it in the CybeDefend dashboard.');
|
|
117
|
+
default:
|
|
118
|
+
return (`VibeDefend paused: ${label} is blocked for your organisation, so ${effect}. ` +
|
|
119
|
+
'An administrator can check the VibeDefend usage page.');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function warningSentence(w) {
|
|
123
|
+
const label = UNIT_LABEL[w.unit];
|
|
124
|
+
if (w.warning === 'approaching_limit') {
|
|
125
|
+
return (`VibeDefend: ${label} has used 80 % of this month's allowance of your organisation. ` +
|
|
126
|
+
'An administrator can follow it in the VibeDefend usage page.');
|
|
127
|
+
}
|
|
128
|
+
return (`VibeDefend: ${label} has reached this month's limit of your organisation; the next requests will be refused. ` +
|
|
129
|
+
'An administrator can add a card or raise the cap in the VibeDefend usage page.');
|
|
130
|
+
}
|
|
131
|
+
/** Reasons that stop every unit: told once per session, whatever the unit. */
|
|
132
|
+
const ORG_WIDE_REASONS = new Set([
|
|
133
|
+
'unpaid',
|
|
134
|
+
'product_inactive',
|
|
135
|
+
]);
|
|
136
|
+
function blockKey(block) {
|
|
137
|
+
return ORG_WIDE_REASONS.has(block.reason)
|
|
138
|
+
? `block:${block.reason}`
|
|
139
|
+
: `block:${block.reason}:${block.unit}`;
|
|
140
|
+
}
|
|
141
|
+
/** Bounded, like the other per-session trackers of the hook. */
|
|
142
|
+
const NOTICES_CAP = 300;
|
|
143
|
+
export function defaultUsageNoticesFile() {
|
|
144
|
+
const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join(homedir(), '.cybedefend');
|
|
145
|
+
return join(dir, 'usage-notices-sessions.json');
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Once-per-session notices, kept on disk because every hook call is its own
|
|
149
|
+
* process. Without a session id there is nothing to dedupe on, so the sentence
|
|
150
|
+
* is always printed (the same choice as the judge's warn-once helper).
|
|
151
|
+
* Never throws: an unreadable or unwritable tracker only means printing again.
|
|
152
|
+
*/
|
|
153
|
+
export function makeUsageNotifier(opts = {}) {
|
|
154
|
+
const file = opts.file ?? defaultUsageNoticesFile();
|
|
155
|
+
const write = opts.write ??
|
|
156
|
+
((line) => {
|
|
157
|
+
try {
|
|
158
|
+
process.stderr.write(line);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// best-effort
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
function load() {
|
|
165
|
+
try {
|
|
166
|
+
if (!existsSync(file))
|
|
167
|
+
return [];
|
|
168
|
+
const data = JSON.parse(readFileSync(file, 'utf8'));
|
|
169
|
+
return Array.isArray(data.seen)
|
|
170
|
+
? data.seen.filter((s) => typeof s === 'string')
|
|
171
|
+
: [];
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function once(sessionId, key, sentence) {
|
|
178
|
+
if (sessionId) {
|
|
179
|
+
const marker = `${sessionId}|${key}`;
|
|
180
|
+
const seen = load();
|
|
181
|
+
if (seen.includes(marker))
|
|
182
|
+
return null;
|
|
183
|
+
try {
|
|
184
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
185
|
+
writeFileSync(file, JSON.stringify({ seen: [...seen, marker].slice(-NOTICES_CAP) }), 'utf8');
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// non-fatal
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
write(`[VibeDefend] ${sentence}\n`);
|
|
192
|
+
return sentence;
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
notifyBlock: (sessionId, block) => once(sessionId, blockKey(block), blockSentence(block)),
|
|
196
|
+
notifyWarning: (sessionId, w) => once(sessionId, `warning:${w.unit}:${w.warning}`, warningSentence(w)),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=usage-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-block.js","sourceRoot":"","sources":["../../../src/hooks/runtime/usage-block.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED