@cybedefend/vibedefend 1.5.0 → 1.7.0
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 +71 -2
- package/dist/api/gateway-request.js +49 -0
- package/dist/api/gateway-request.js.map +1 -0
- package/dist/api/projects.js +67 -0
- package/dist/api/projects.js.map +1 -1
- package/dist/api/repository-link.js +157 -0
- package/dist/api/repository-link.js.map +1 -0
- package/dist/auth/auth-store.js +107 -25
- package/dist/auth/auth-store.js.map +1 -1
- package/dist/auth/auth.js +21 -0
- package/dist/auth/auth.js.map +1 -1
- package/dist/clients/cursor.js +5 -1
- package/dist/clients/cursor.js.map +1 -1
- package/dist/clients/vscode.js +38 -29
- package/dist/clients/vscode.js.map +1 -1
- package/dist/commands/mcp/allow.js +219 -0
- package/dist/commands/mcp/allow.js.map +1 -0
- package/dist/commands/mcp/connect.js +337 -0
- package/dist/commands/mcp/connect.js.map +1 -0
- package/dist/commands/mcp/index.js +170 -0
- package/dist/commands/mcp/index.js.map +1 -0
- package/dist/commands/mcp/proxy.js +320 -0
- package/dist/commands/mcp/proxy.js.map +1 -0
- package/dist/commands/mcp/scan.js +349 -0
- package/dist/commands/mcp/scan.js.map +1 -0
- package/dist/commands/mcp/sync.js +215 -0
- package/dist/commands/mcp/sync.js.map +1 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/diagnostics.js +78 -12
- package/dist/diagnostics.js.map +1 -1
- package/dist/doctor.js +19 -0
- package/dist/doctor.js.map +1 -1
- package/dist/guards-evaluator/analysis-types.js +27 -0
- package/dist/guards-evaluator/analysis-types.js.map +1 -0
- package/dist/guards-evaluator/command-analysis.js +572 -0
- package/dist/guards-evaluator/command-analysis.js.map +1 -0
- package/dist/guards-evaluator/command-view.js +586 -0
- package/dist/guards-evaluator/command-view.js.map +1 -0
- package/dist/guards-evaluator/env.js +11 -0
- package/dist/guards-evaluator/env.js.map +1 -0
- package/dist/guards-evaluator/evaluate.js +91 -41
- package/dist/guards-evaluator/evaluate.js.map +1 -1
- package/dist/guards-evaluator/index.js +2 -1
- package/dist/guards-evaluator/index.js.map +1 -1
- package/dist/guards-evaluator/inline-code.js +259 -0
- package/dist/guards-evaluator/inline-code.js.map +1 -0
- package/dist/guards-evaluator/normalize.js +716 -0
- package/dist/guards-evaluator/normalize.js.map +1 -0
- package/dist/guards-evaluator/preprocess.js +13 -5
- package/dist/guards-evaluator/preprocess.js.map +1 -1
- package/dist/guards-evaluator/redact.js +19 -0
- package/dist/guards-evaluator/redact.js.map +1 -1
- package/dist/guards-evaluator/regex.js +25 -3
- package/dist/guards-evaluator/regex.js.map +1 -1
- package/dist/guards-evaluator/safe-commands.js +155 -0
- package/dist/guards-evaluator/safe-commands.js.map +1 -0
- package/dist/guards-evaluator/triage.js +315 -0
- package/dist/guards-evaluator/triage.js.map +1 -0
- package/dist/hook-runner.js +24679 -5079
- package/dist/hooks/install.js +38 -0
- package/dist/hooks/install.js.map +1 -1
- package/dist/hooks/runtime/config.js +38 -0
- package/dist/hooks/runtime/config.js.map +1 -1
- package/dist/hooks/runtime/emit.js +94 -61
- package/dist/hooks/runtime/emit.js.map +1 -1
- package/dist/hooks/runtime/fetch-rules.js +22 -7
- package/dist/hooks/runtime/fetch-rules.js.map +1 -1
- package/dist/hooks/runtime/gateway-http-error.js +34 -0
- package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
- package/dist/hooks/runtime/guard-rules-cache.js +139 -17
- package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
- package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
- package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
- package/dist/hooks/runtime/judge-cache.js +6 -0
- package/dist/hooks/runtime/judge-cache.js.map +1 -1
- package/dist/hooks/runtime/judge-triage.js +193 -0
- package/dist/hooks/runtime/judge-triage.js.map +1 -0
- package/dist/hooks/runtime/judge.js +7 -1
- package/dist/hooks/runtime/judge.js.map +1 -1
- package/dist/hooks/runtime/pre-compact.js +12 -6
- package/dist/hooks/runtime/pre-compact.js.map +1 -1
- package/dist/hooks/runtime/resolve.js +90 -8
- package/dist/hooks/runtime/resolve.js.map +1 -1
- package/dist/hooks/runtime/retry-policy.js +57 -0
- package/dist/hooks/runtime/retry-policy.js.map +1 -0
- package/dist/hooks/runtime/review-sessions.js +74 -0
- package/dist/hooks/runtime/review-sessions.js.map +1 -0
- package/dist/hooks/runtime/script-resolve.js +695 -0
- package/dist/hooks/runtime/script-resolve.js.map +1 -0
- package/dist/hooks/runtime/session-activation.js +5 -1
- package/dist/hooks/runtime/session-activation.js.map +1 -1
- package/dist/hooks/runtime/session-review.js +163 -45
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/session-start.js +2 -1
- package/dist/hooks/runtime/session-start.js.map +1 -1
- package/dist/hooks/runtime/session-writes.js +232 -0
- package/dist/hooks/runtime/session-writes.js.map +1 -0
- package/dist/hooks/runtime/sniff.js +26 -7
- package/dist/hooks/runtime/sniff.js.map +1 -1
- package/dist/hooks/runtime/target-resolve.js +336 -0
- package/dist/hooks/runtime/target-resolve.js.map +1 -0
- package/dist/hooks/runtime/unmapped-tools.js +93 -0
- package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
- package/dist/hooks/runtime/usage-block.js +4 -0
- package/dist/hooks/runtime/usage-block.js.map +1 -1
- package/dist/hooks/runtime/user-prompt-submit.js +2 -1
- package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
- package/dist/hooks/runtime/wire-text.js +41 -0
- package/dist/hooks/runtime/wire-text.js.map +1 -0
- package/dist/hooks/runtime/work-dir.js +84 -0
- package/dist/hooks/runtime/work-dir.js.map +1 -0
- package/dist/index.js +45 -12
- package/dist/index.js.map +1 -1
- package/dist/install.js +174 -11
- package/dist/install.js.map +1 -1
- package/dist/link.js +74 -48
- package/dist/link.js.map +1 -1
- package/dist/login.js +77 -11
- package/dist/login.js.map +1 -1
- package/dist/mcp/auth/agent-sign-ins.js +174 -0
- package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
- package/dist/mcp/auth/callback.js +200 -0
- package/dist/mcp/auth/callback.js.map +1 -0
- package/dist/mcp/auth/connect.js +392 -0
- package/dist/mcp/auth/connect.js.map +1 -0
- package/dist/mcp/auth/discovery.js +399 -0
- package/dist/mcp/auth/discovery.js.map +1 -0
- package/dist/mcp/auth/oauth.js +326 -0
- package/dist/mcp/auth/oauth.js.map +1 -0
- package/dist/mcp/auth/probe.js +128 -0
- package/dist/mcp/auth/probe.js.map +1 -0
- package/dist/mcp/auth/secrets.js +446 -0
- package/dist/mcp/auth/secrets.js.map +1 -0
- package/dist/mcp/auth/store.js +260 -0
- package/dist/mcp/auth/store.js.map +1 -0
- package/dist/mcp/auth/tokenSource.js +55 -0
- package/dist/mcp/auth/tokenSource.js.map +1 -0
- package/dist/mcp/config/atomicWrite.js +98 -0
- package/dist/mcp/config/atomicWrite.js.map +1 -0
- package/dist/mcp/config/clients.js +171 -0
- package/dist/mcp/config/clients.js.map +1 -0
- package/dist/mcp/config/cybedefend-servers.js +48 -0
- package/dist/mcp/config/cybedefend-servers.js.map +1 -0
- package/dist/mcp/config/discover.js +114 -0
- package/dist/mcp/config/discover.js.map +1 -0
- package/dist/mcp/config/hook.js +123 -0
- package/dist/mcp/config/hook.js.map +1 -0
- package/dist/mcp/config/index.js +11 -0
- package/dist/mcp/config/index.js.map +1 -0
- package/dist/mcp/config/install.js +132 -0
- package/dist/mcp/config/install.js.map +1 -0
- package/dist/mcp/config/installed.js +37 -0
- package/dist/mcp/config/installed.js.map +1 -0
- package/dist/mcp/config/jsonEdit.js +119 -0
- package/dist/mcp/config/jsonEdit.js.map +1 -0
- package/dist/mcp/config/lock.js +102 -0
- package/dist/mcp/config/lock.js.map +1 -0
- package/dist/mcp/config/proxyBinary.js +211 -0
- package/dist/mcp/config/proxyBinary.js.map +1 -0
- package/dist/mcp/config/rewrite.js +388 -0
- package/dist/mcp/config/rewrite.js.map +1 -0
- package/dist/mcp/config/types.js +34 -0
- package/dist/mcp/config/types.js.map +1 -0
- package/dist/mcp/proxy/audit.js +83 -0
- package/dist/mcp/proxy/audit.js.map +1 -0
- package/dist/mcp/proxy/authInterceptor.js +119 -0
- package/dist/mcp/proxy/authInterceptor.js.map +1 -0
- package/dist/mcp/proxy/expand.js +93 -0
- package/dist/mcp/proxy/expand.js.map +1 -0
- package/dist/mcp/proxy/inject.js +412 -0
- package/dist/mcp/proxy/inject.js.map +1 -0
- package/dist/mcp/proxy/intercept.js +63 -0
- package/dist/mcp/proxy/intercept.js.map +1 -0
- package/dist/mcp/proxy/jsonrpc.js +153 -0
- package/dist/mcp/proxy/jsonrpc.js.map +1 -0
- package/dist/mcp/proxy/log.js +109 -0
- package/dist/mcp/proxy/log.js.map +1 -0
- package/dist/mcp/proxy/paths.js +57 -0
- package/dist/mcp/proxy/paths.js.map +1 -0
- package/dist/mcp/proxy/proxy.js +520 -0
- package/dist/mcp/proxy/proxy.js.map +1 -0
- package/dist/mcp/proxy/serverCheckTimer.js +75 -0
- package/dist/mcp/proxy/serverCheckTimer.js.map +1 -0
- package/dist/mcp/proxy/sessionLifecycle.js +29 -0
- package/dist/mcp/proxy/sessionLifecycle.js.map +1 -0
- package/dist/mcp/proxy/spec.js +203 -0
- package/dist/mcp/proxy/spec.js.map +1 -0
- package/dist/mcp/proxy/sse.js +77 -0
- package/dist/mcp/proxy/sse.js.map +1 -0
- package/dist/mcp/proxy/upstream.js +2 -0
- package/dist/mcp/proxy/upstream.js.map +1 -0
- package/dist/mcp/proxy/upstreamHttp.js +499 -0
- package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
- package/dist/mcp/proxy/upstreamStdio.js +188 -0
- package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
- package/dist/mcp/proxy/upstreams.js +143 -0
- package/dist/mcp/proxy/upstreams.js.map +1 -0
- package/dist/mcp/proxy/verifyInterceptor.js +718 -0
- package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
- package/dist/mcp/proxy/windowsCommand.js +99 -0
- package/dist/mcp/proxy/windowsCommand.js.map +1 -0
- package/dist/mcp/report/buffer.js +351 -0
- package/dist/mcp/report/buffer.js.map +1 -0
- package/dist/mcp/report/coalesce.js +165 -0
- package/dist/mcp/report/coalesce.js.map +1 -0
- package/dist/mcp/report/constants.js +51 -0
- package/dist/mcp/report/constants.js.map +1 -0
- package/dist/mcp/report/project.js +83 -0
- package/dist/mcp/report/project.js.map +1 -0
- package/dist/mcp/report/reporter.js +443 -0
- package/dist/mcp/report/reporter.js.map +1 -0
- package/dist/mcp/report/types.js +3 -0
- package/dist/mcp/report/types.js.map +1 -0
- package/dist/mcp/report/validate.js +179 -0
- package/dist/mcp/report/validate.js.map +1 -0
- package/dist/mcp/scan/args.js +228 -0
- package/dist/mcp/scan/args.js.map +1 -0
- package/dist/mcp/scan/results.js +253 -0
- package/dist/mcp/scan/results.js.map +1 -0
- package/dist/mcp/scan/types.js +40 -0
- package/dist/mcp/scan/types.js.map +1 -0
- package/dist/mcp/verify/api.js +514 -0
- package/dist/mcp/verify/api.js.map +1 -0
- package/dist/mcp/verify/backend.js +143 -0
- package/dist/mcp/verify/backend.js.map +1 -0
- package/dist/mcp/verify/cache.js +200 -0
- package/dist/mcp/verify/cache.js.map +1 -0
- package/dist/mcp/verify/contract-errors.js +198 -0
- package/dist/mcp/verify/contract-errors.js.map +1 -0
- package/dist/mcp/verify/digest.js +91 -0
- package/dist/mcp/verify/digest.js.map +1 -0
- package/dist/mcp/verify/factory.js +56 -0
- package/dist/mcp/verify/factory.js.map +1 -0
- package/dist/mcp/verify/identity.js +286 -0
- package/dist/mcp/verify/identity.js.map +1 -0
- package/dist/mcp/verify/policy-store.js +63 -0
- package/dist/mcp/verify/policy-store.js.map +1 -0
- package/dist/mcp/verify/policy.js +160 -0
- package/dist/mcp/verify/policy.js.map +1 -0
- package/dist/mcp/verify/pool.js +27 -0
- package/dist/mcp/verify/pool.js.map +1 -0
- package/dist/mcp/verify/token-refresh.js +44 -0
- package/dist/mcp/verify/token-refresh.js.map +1 -0
- package/dist/mcp/verify/token.js +67 -0
- package/dist/mcp/verify/token.js.map +1 -0
- package/dist/mcp/verify/verifier.js +1166 -0
- package/dist/mcp/verify/verifier.js.map +1 -0
- package/dist/org-gate.js +1 -1
- package/dist/org-gate.js.map +1 -1
- package/dist/org.js +146 -0
- package/dist/org.js.map +1 -0
- package/dist/project-create.js +129 -0
- package/dist/project-create.js.map +1 -0
- package/dist/prompts.js +21 -0
- package/dist/prompts.js.map +1 -1
- package/dist/re2.wasm +0 -0
- package/dist/status.js +61 -0
- package/dist/status.js.map +1 -1
- package/dist/uninstall.js +49 -4
- package/dist/uninstall.js.map +1 -1
- package/dist/utils.js +62 -6
- package/dist/utils.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// ─── Coalescing of call events ────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// An agent looping on a refused tool would otherwise send thousands of events.
|
|
4
|
+
// Identical events (kind, reason, tool) inside COALESCE_WINDOW_MS are ONE event:
|
|
5
|
+
// one eventId whose count rises. The gateway upserts by eventId, so a resend
|
|
6
|
+
// with a higher count replaces the earlier one.
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import { COALESCE_WINDOW_MS, REPORT_BUFFER_MAX_RECORDS, REPORT_MAX_EVENT_COUNT, REPORT_MAX_EVENTS, } from './constants.js';
|
|
9
|
+
const CATEGORY_PATTERN = /^[a-z0-9_-]{1,64}$/;
|
|
10
|
+
const SEVERITY_PATTERN = /^[a-z]{1,16}$/;
|
|
11
|
+
const RULE_PATTERN = /^[a-z0-9._-]{1,64}$/;
|
|
12
|
+
const DIGEST_PATTERN = /^d1:[0-9a-f]{64}$/;
|
|
13
|
+
const MAX_RULES = 5;
|
|
14
|
+
const MAX_TOOL_NAME = 128;
|
|
15
|
+
export function toReportVerdict(verdict) {
|
|
16
|
+
if (verdict === undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
if (verdict === 'ok')
|
|
19
|
+
return 'clean';
|
|
20
|
+
if (verdict === 'malicious' || verdict === 'suspicious')
|
|
21
|
+
return verdict;
|
|
22
|
+
return 'unverified';
|
|
23
|
+
}
|
|
24
|
+
/** A tool name as it leaves the machine: the gateway's charset and length. */
|
|
25
|
+
export function reportToolName(name) {
|
|
26
|
+
const cleaned = name.replace(/[^A-Za-z0-9._/-]/g, '_').slice(0, MAX_TOOL_NAME);
|
|
27
|
+
return cleaned === '' ? 'unnamed' : cleaned;
|
|
28
|
+
}
|
|
29
|
+
const SWEEP_EVERY_MS = 1_000;
|
|
30
|
+
export class EventCoalescer {
|
|
31
|
+
now;
|
|
32
|
+
windowMs;
|
|
33
|
+
newId;
|
|
34
|
+
maxGroups;
|
|
35
|
+
groups = new Map();
|
|
36
|
+
lastSweepMs = -Infinity;
|
|
37
|
+
constructor(opts = {}) {
|
|
38
|
+
this.now = opts.now ?? Date.now;
|
|
39
|
+
this.windowMs = opts.windowMs ?? COALESCE_WINDOW_MS;
|
|
40
|
+
this.newId = opts.newId ?? randomUUID;
|
|
41
|
+
// Nothing may be sent for a long time (no organization, offline): the
|
|
42
|
+
// memory a proxy keeps for its reports stays bounded all the same.
|
|
43
|
+
this.maxGroups = Math.max(1, opts.maxGroups ?? REPORT_BUFFER_MAX_RECORDS);
|
|
44
|
+
}
|
|
45
|
+
add(input) {
|
|
46
|
+
const nowMs = this.now();
|
|
47
|
+
// On the hot path: forgetting closed groups is worth one pass a second,
|
|
48
|
+
// not one per call (`pending()` sweeps before reading anyway).
|
|
49
|
+
if (nowMs < this.lastSweepMs || nowMs - this.lastSweepMs >= SWEEP_EVERY_MS)
|
|
50
|
+
this.sweep(nowMs);
|
|
51
|
+
const tool = reportToolName(input.tool);
|
|
52
|
+
const key = groupKey(input.kind, input.reason, tool);
|
|
53
|
+
const iso = new Date(nowMs).toISOString();
|
|
54
|
+
let group = this.groups.get(key);
|
|
55
|
+
if (group !== undefined && nowMs - group.firstMs >= this.windowMs) {
|
|
56
|
+
// The window is over. A group still unsent keeps its own key slot until
|
|
57
|
+
// replaced here, so it is lost only if it was never sent: keep it under
|
|
58
|
+
// its eventId by moving it aside.
|
|
59
|
+
if (group.dirty)
|
|
60
|
+
this.groups.set(`${key}#${group.event.eventId}`, group);
|
|
61
|
+
group = undefined;
|
|
62
|
+
}
|
|
63
|
+
if (group === undefined) {
|
|
64
|
+
group = {
|
|
65
|
+
event: {
|
|
66
|
+
eventId: this.newId(),
|
|
67
|
+
kind: input.kind,
|
|
68
|
+
reason: input.reason,
|
|
69
|
+
tool,
|
|
70
|
+
count: 0,
|
|
71
|
+
firstAt: iso,
|
|
72
|
+
lastAt: iso,
|
|
73
|
+
},
|
|
74
|
+
firstMs: nowMs,
|
|
75
|
+
lastMs: nowMs,
|
|
76
|
+
dirty: true,
|
|
77
|
+
};
|
|
78
|
+
this.groups.set(key, group);
|
|
79
|
+
this.evictOldest();
|
|
80
|
+
}
|
|
81
|
+
const e = group.event;
|
|
82
|
+
// Stops at the gateway's bound: past it, the group's every later send
|
|
83
|
+
// would be refused and the event lost. `lastAt` still moves on below.
|
|
84
|
+
e.count = Math.min(e.count + 1, REPORT_MAX_EVENT_COUNT);
|
|
85
|
+
// `lastAt` only moves forward. A wall clock can step back (NTP, a resume),
|
|
86
|
+
// and an event that ends before it starts is refused by the gateway: one such
|
|
87
|
+
// event would poison its whole report, and the report would keep coming back
|
|
88
|
+
// from the buffer for the 7 days it lives there.
|
|
89
|
+
if (nowMs > group.lastMs) {
|
|
90
|
+
group.lastMs = nowMs;
|
|
91
|
+
e.lastAt = iso;
|
|
92
|
+
}
|
|
93
|
+
if (input.digest !== undefined && DIGEST_PATTERN.test(input.digest))
|
|
94
|
+
e.toolDigest = input.digest;
|
|
95
|
+
const verdict = toReportVerdict(input.verdict);
|
|
96
|
+
if (verdict !== undefined)
|
|
97
|
+
e.verdict = verdict;
|
|
98
|
+
if (input.category !== undefined && CATEGORY_PATTERN.test(input.category))
|
|
99
|
+
e.category = input.category;
|
|
100
|
+
if (input.severity !== undefined && SEVERITY_PATTERN.test(input.severity))
|
|
101
|
+
e.severity = input.severity;
|
|
102
|
+
if (input.rules !== undefined) {
|
|
103
|
+
const merged = new Set(e.rules ?? []);
|
|
104
|
+
for (const r of input.rules) {
|
|
105
|
+
if (RULE_PATTERN.test(r))
|
|
106
|
+
merged.add(r);
|
|
107
|
+
}
|
|
108
|
+
const rules = [...merged].slice(0, MAX_RULES);
|
|
109
|
+
if (rules.length > 0)
|
|
110
|
+
e.rules = rules;
|
|
111
|
+
}
|
|
112
|
+
group.dirty = true;
|
|
113
|
+
}
|
|
114
|
+
/** Dirty groups, oldest first, copied. */
|
|
115
|
+
pending(limit = REPORT_MAX_EVENTS) {
|
|
116
|
+
this.sweep(this.now());
|
|
117
|
+
return [...this.groups.values()]
|
|
118
|
+
.filter((g) => g.dirty)
|
|
119
|
+
.sort((a, b) => a.firstMs - b.firstMs)
|
|
120
|
+
.slice(0, limit)
|
|
121
|
+
.map((g) => ({ ...g.event, ...(g.event.rules ? { rules: [...g.event.rules] } : {}) }));
|
|
122
|
+
}
|
|
123
|
+
markSent(sent) {
|
|
124
|
+
for (const s of sent) {
|
|
125
|
+
for (const g of this.groups.values()) {
|
|
126
|
+
if (g.event.eventId === s.eventId && g.event.count === s.count)
|
|
127
|
+
g.dirty = false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
hasPending() {
|
|
132
|
+
for (const g of this.groups.values())
|
|
133
|
+
if (g.dirty)
|
|
134
|
+
return true;
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
/** Over the bound, the oldest groups go first, sent or not. */
|
|
138
|
+
evictOldest() {
|
|
139
|
+
while (this.groups.size > this.maxGroups) {
|
|
140
|
+
let oldestKey;
|
|
141
|
+
let oldestMs = Infinity;
|
|
142
|
+
for (const [key, g] of this.groups) {
|
|
143
|
+
if (g.firstMs < oldestMs) {
|
|
144
|
+
oldestMs = g.firstMs;
|
|
145
|
+
oldestKey = key;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (oldestKey === undefined)
|
|
149
|
+
return;
|
|
150
|
+
this.groups.delete(oldestKey);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** Closed and clean groups are forgotten. */
|
|
154
|
+
sweep(nowMs) {
|
|
155
|
+
this.lastSweepMs = nowMs;
|
|
156
|
+
for (const [key, g] of this.groups) {
|
|
157
|
+
if (!g.dirty && nowMs - g.firstMs >= this.windowMs)
|
|
158
|
+
this.groups.delete(key);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function groupKey(kind, reason, tool) {
|
|
163
|
+
return `${kind}|${reason}|${tool}`;
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=coalesce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coalesce.js","sourceRoot":"","sources":["../../../src/mcp/report/coalesce.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// ─── Constants of MCP call reporting (contract C6 and the validation of C4) ──
|
|
2
|
+
/** Events of one report, at most. */
|
|
3
|
+
export const REPORT_MAX_EVENTS = 200;
|
|
4
|
+
/** Repeated events of one (server, tool, kind, reason) are one event over this window. */
|
|
5
|
+
export const COALESCE_WINDOW_MS = 600_000;
|
|
6
|
+
/** The first send goes this long after an event. */
|
|
7
|
+
export const FIRST_SEND_DELAY_MS = 5_000;
|
|
8
|
+
/** Then at most one send per this interval. */
|
|
9
|
+
export const MIN_SEND_INTERVAL_MS = 60_000;
|
|
10
|
+
/** The inventory is resent at least this often. */
|
|
11
|
+
export const INVENTORY_REFRESH_MS = 3_600_000;
|
|
12
|
+
/** The report buffer holds this many records, at most... */
|
|
13
|
+
export const REPORT_BUFFER_MAX_RECORDS = 500;
|
|
14
|
+
/** ...and none older than this. */
|
|
15
|
+
export const REPORT_BUFFER_MAX_AGE_MS = 7 * 24 * 3_600_000;
|
|
16
|
+
/** How long an organisation is left alone after a 400, 403, 404 or 422. */
|
|
17
|
+
export const REPORT_HOLD_MS = 3_600_000;
|
|
18
|
+
/** Timeout of one report request. */
|
|
19
|
+
export const REPORT_HTTP_TIMEOUT_MS = 5_000;
|
|
20
|
+
/** `servers/check` runs this often for the whole life of the proxy. */
|
|
21
|
+
export const SERVER_CHECK_INTERVAL_MS = 900_000;
|
|
22
|
+
/** A known organisation block stays applied this long while the backend cannot be reached. */
|
|
23
|
+
export const ORG_BLOCK_STICKY_MAX_MS = 7 * 24 * 3_600_000;
|
|
24
|
+
// What a report may carry, field by field (C4). Anything else is not sent.
|
|
25
|
+
/** A config entry name or a launcher name, as it leaves the machine. */
|
|
26
|
+
export const LABEL_PATTERN = /^[A-Za-z0-9._-]{1,64}$/;
|
|
27
|
+
/**
|
|
28
|
+
* A lowercase hostname, no scheme, port or path: labels of 1 to 63 characters
|
|
29
|
+
* that neither start nor end with a hyphen, 253 characters at most. The
|
|
30
|
+
* gateway's pattern, so an empty label (`mcp..example.com`) or a trailing dot
|
|
31
|
+
* is refused here instead of costing the whole report a 400.
|
|
32
|
+
*/
|
|
33
|
+
export const HOST_PATTERN = /^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/;
|
|
34
|
+
/** At most 214 characters in all, scope included: npm's own limit (ruling R30). */
|
|
35
|
+
export const NPM_NAME_PATTERN = /^(?=.{1,214}$)(@[a-z0-9._~-]+\/)?[a-z0-9._~-]{1,214}$/;
|
|
36
|
+
export const PYPI_NAME_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;
|
|
37
|
+
export const PACKAGE_VERSION_PATTERN = /^[A-Za-z0-9.+_-]{1,64}$/;
|
|
38
|
+
export const SERVER_KEY_PATTERN = /^[a-f0-9]{64}$/;
|
|
39
|
+
/** The gateway's pattern for `vibedefendVersion`: semver, at most one pre-release and one build part. */
|
|
40
|
+
export const VIBEDEFEND_VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
41
|
+
/** `server.toolCount` and `server.flaggedToolCount`, at most (the gateway refuses more). */
|
|
42
|
+
export const REPORT_MAX_TOOL_COUNT = 100_000;
|
|
43
|
+
/** An event's `count`, at most (the gateway refuses more). */
|
|
44
|
+
export const REPORT_MAX_EVENT_COUNT = 100_000;
|
|
45
|
+
/**
|
|
46
|
+
* How far ahead of this machine's clock an organisation block's confirmation
|
|
47
|
+
* may be and still count: a clock set back a little while offline (an NTP
|
|
48
|
+
* correction) must not lift a block that is in force.
|
|
49
|
+
*/
|
|
50
|
+
export const ORG_BLOCK_CLOCK_SKEW_MS = 5 * 60_000;
|
|
51
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/mcp/report/constants.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,qCAAqC;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC,0FAA0F;AAC1F,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAC1C,oDAAoD;AACpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AACzC,+CAA+C;AAC/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAC3C,mDAAmD;AACnD,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAE9C,4DAA4D;AAC5D,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAC7C,mCAAmC;AACnC,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;AAC3D,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AACxC,qCAAqC;AACrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAE5C,uEAAuE;AACvE,MAAM,CAAC,MAAM,wBAAwB,GAAG,OAAO,CAAC;AAChD,8FAA8F;AAC9F,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;AAE1D,2EAA2E;AAE3E,wEAAwE;AACxE,MAAM,CAAC,MAAM,aAAa,GAAG,wBAAwB,CAAC;AACtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,gGAAgG,CAAC;AACnG,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAG,uDAAuD,CAAC;AACxF,MAAM,CAAC,MAAM,iBAAiB,GAAG,yBAAyB,CAAC;AAC3D,MAAM,CAAC,MAAM,uBAAuB,GAAG,yBAAyB,CAAC;AACjE,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AACnD,yGAAyG;AACzG,MAAM,CAAC,MAAM,0BAA0B,GAAG,0DAA0D,CAAC;AACrG,4FAA4F;AAC5F,MAAM,CAAC,MAAM,qBAAqB,GAAG,OAAO,CAAC;AAC7C,8DAA8D;AAC9D,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAC9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The project a proxy reports for, resolved once per process.
|
|
3
|
+
*
|
|
4
|
+
* Off the hot path: the caller (the reporter) awaits it in the background and
|
|
5
|
+
* never before forwarding a call. It never throws.
|
|
6
|
+
*
|
|
7
|
+
* Only Claude Code has its project read from the proxy's working directory
|
|
8
|
+
* (`.cybedefend/config.json`, then the git origin through
|
|
9
|
+
* `GET /user/projects/resolve`): that the working directory is the agent's
|
|
10
|
+
* launch folder is verified for Claude Code alone. Any other agent, or one
|
|
11
|
+
* that did not say who it is, gets a project only from an explicit
|
|
12
|
+
* `CYBEDEFEND_PROJECT_ID`; otherwise its reports carry none. Where it is not
|
|
13
|
+
* reliable, the project is omitted rather than guessed (spec §2.3).
|
|
14
|
+
*/
|
|
15
|
+
import { execFile } from 'node:child_process';
|
|
16
|
+
import { resolveProjectIdWithApi } from '../../hooks/runtime/resolve.js';
|
|
17
|
+
import { findRepoRoot } from '../../hooks/runtime/work-dir.js';
|
|
18
|
+
import { verifyTokenResolver } from '../verify/token.js';
|
|
19
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20
|
+
const ORIGIN_TIMEOUT_MS = 3000;
|
|
21
|
+
/** The agents whose working directory says which project they work on (normalised names). */
|
|
22
|
+
const PROJECT_FROM_WORKING_DIRECTORY = new Set(['claude-code']);
|
|
23
|
+
/**
|
|
24
|
+
* A client name as the gateway stores it (`toClientName`): lowercase, every run
|
|
25
|
+
* of other characters a single `-`, no `-` at either end, 64 characters at most.
|
|
26
|
+
*/
|
|
27
|
+
export function normaliseClientName(name) {
|
|
28
|
+
if (typeof name !== 'string')
|
|
29
|
+
return '';
|
|
30
|
+
return name
|
|
31
|
+
.toLowerCase()
|
|
32
|
+
.replace(/[^a-z0-9._-]+/g, '-')
|
|
33
|
+
.replace(/-{2,}/g, '-')
|
|
34
|
+
.replace(/^-+|-+$/g, '')
|
|
35
|
+
.slice(0, 64)
|
|
36
|
+
.replace(/-+$/, '');
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Asynchronous on purpose: the sync `spawnSync` of `src/git.ts` would block the
|
|
40
|
+
* forwarding loop for up to its timeout.
|
|
41
|
+
*/
|
|
42
|
+
function readGitOrigin(cwd) {
|
|
43
|
+
return new Promise((resolve) => {
|
|
44
|
+
try {
|
|
45
|
+
execFile('git', ['remote', 'get-url', 'origin'], { cwd, timeout: ORIGIN_TIMEOUT_MS }, (err, stdout) => {
|
|
46
|
+
const out = err ? '' : String(stdout).trim();
|
|
47
|
+
resolve(out === '' ? null : out);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
resolve(null);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export async function resolveReportProjectId(deps) {
|
|
56
|
+
try {
|
|
57
|
+
const explicit = deps.env.CYBEDEFEND_PROJECT_ID?.trim();
|
|
58
|
+
if (explicit && UUID_RE.test(explicit))
|
|
59
|
+
return explicit;
|
|
60
|
+
if (!PROJECT_FROM_WORKING_DIRECTORY.has(normaliseClientName(deps.clientName)))
|
|
61
|
+
return null;
|
|
62
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
63
|
+
const root = findRepoRoot(cwd) ?? cwd;
|
|
64
|
+
let origin = null;
|
|
65
|
+
try {
|
|
66
|
+
origin = await (deps.readOrigin ?? readGitOrigin)(root);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
origin = null;
|
|
70
|
+
}
|
|
71
|
+
const resolve = deps.resolveProject ?? resolveProjectIdWithApi;
|
|
72
|
+
const resolution = await resolve(root, {
|
|
73
|
+
resolveTokenFn: verifyTokenResolver({ env: deps.env }),
|
|
74
|
+
getOrigin: () => origin,
|
|
75
|
+
});
|
|
76
|
+
const id = resolution?.projectId;
|
|
77
|
+
return typeof id === 'string' && UUID_RE.test(id) ? id : null;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/mcp/report/project.ts"],"names":[],"mappings":"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"}
|