@vibecheckai/cli 3.2.2 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/.generated +25 -25
- package/bin/dev/run-v2-torture.js +30 -30
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -121
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +117 -28
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +23 -14
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +72 -1
- package/bin/runners/lib/agent-firewall/interceptor/base.js +2 -2
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +6 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +34 -3
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +29 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +12 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +21 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/analyzers.js +606 -325
- package/bin/runners/lib/auth-truth.js +193 -193
- package/bin/runners/lib/backup.js +62 -62
- package/bin/runners/lib/billing.js +107 -107
- package/bin/runners/lib/claims.js +118 -118
- package/bin/runners/lib/cli-ui.js +540 -540
- package/bin/runners/lib/contracts/auth-contract.js +202 -202
- package/bin/runners/lib/contracts/env-contract.js +181 -181
- package/bin/runners/lib/contracts/external-contract.js +206 -206
- package/bin/runners/lib/contracts/guard.js +168 -168
- package/bin/runners/lib/contracts/index.js +89 -89
- package/bin/runners/lib/contracts/plan-validator.js +311 -311
- package/bin/runners/lib/contracts/route-contract.js +199 -199
- package/bin/runners/lib/contracts.js +804 -804
- package/bin/runners/lib/detect.js +89 -89
- package/bin/runners/lib/doctor/autofix.js +254 -254
- package/bin/runners/lib/doctor/index.js +37 -37
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
- package/bin/runners/lib/doctor/modules/index.js +46 -46
- package/bin/runners/lib/doctor/modules/network.js +250 -250
- package/bin/runners/lib/doctor/modules/project.js +312 -312
- package/bin/runners/lib/doctor/modules/runtime.js +224 -224
- package/bin/runners/lib/doctor/modules/security.js +348 -348
- package/bin/runners/lib/doctor/modules/system.js +213 -213
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
- package/bin/runners/lib/doctor/reporter.js +262 -262
- package/bin/runners/lib/doctor/service.js +262 -262
- package/bin/runners/lib/doctor/types.js +113 -113
- package/bin/runners/lib/doctor/ui.js +263 -263
- package/bin/runners/lib/doctor-v2.js +608 -608
- package/bin/runners/lib/drift.js +425 -425
- package/bin/runners/lib/enforcement.js +72 -72
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -603
- package/bin/runners/lib/enterprise-init.js +942 -942
- package/bin/runners/lib/env-resolver.js +417 -417
- package/bin/runners/lib/env-template.js +66 -66
- package/bin/runners/lib/env.js +189 -189
- package/bin/runners/lib/extractors/client-calls.js +990 -990
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
- package/bin/runners/lib/extractors/fastify-routes.js +426 -426
- package/bin/runners/lib/extractors/index.js +363 -363
- package/bin/runners/lib/extractors/next-routes.js +524 -524
- package/bin/runners/lib/extractors/proof-graph.js +431 -431
- package/bin/runners/lib/extractors/route-matcher.js +451 -451
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
- package/bin/runners/lib/extractors/ui-bindings.js +547 -547
- package/bin/runners/lib/findings-schema.js +281 -281
- package/bin/runners/lib/firewall-prompt.js +50 -50
- package/bin/runners/lib/global-flags.js +213 -213
- package/bin/runners/lib/graph/graph-builder.js +265 -265
- package/bin/runners/lib/graph/html-renderer.js +413 -413
- package/bin/runners/lib/graph/index.js +32 -32
- package/bin/runners/lib/graph/runtime-collector.js +215 -215
- package/bin/runners/lib/graph/static-extractor.js +518 -518
- package/bin/runners/lib/html-report.js +650 -650
- package/bin/runners/lib/interactive-menu.js +1496 -1496
- package/bin/runners/lib/llm.js +75 -75
- package/bin/runners/lib/meter.js +61 -61
- package/bin/runners/lib/missions/evidence.js +126 -126
- package/bin/runners/lib/patch.js +40 -40
- package/bin/runners/lib/permissions/auth-model.js +213 -213
- package/bin/runners/lib/permissions/idor-prover.js +205 -205
- package/bin/runners/lib/permissions/index.js +45 -45
- package/bin/runners/lib/permissions/matrix-builder.js +198 -198
- package/bin/runners/lib/pkgjson.js +28 -28
- package/bin/runners/lib/policy.js +295 -295
- package/bin/runners/lib/preflight.js +142 -142
- package/bin/runners/lib/reality/correlation-detectors.js +359 -359
- package/bin/runners/lib/reality/index.js +318 -318
- package/bin/runners/lib/reality/request-hashing.js +416 -416
- package/bin/runners/lib/reality/request-mapper.js +453 -453
- package/bin/runners/lib/reality/safety-rails.js +463 -463
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
- package/bin/runners/lib/reality/toast-detector.js +393 -393
- package/bin/runners/lib/reality-findings.js +84 -84
- package/bin/runners/lib/receipts.js +179 -179
- package/bin/runners/lib/redact.js +29 -29
- package/bin/runners/lib/replay/capsule-manager.js +154 -154
- package/bin/runners/lib/replay/index.js +263 -263
- package/bin/runners/lib/replay/player.js +348 -348
- package/bin/runners/lib/replay/recorder.js +331 -331
- package/bin/runners/lib/report-output.js +187 -187
- package/bin/runners/lib/report.js +135 -135
- package/bin/runners/lib/route-detection.js +1140 -1140
- package/bin/runners/lib/sandbox/index.js +59 -59
- package/bin/runners/lib/sandbox/proof-chain.js +399 -399
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
- package/bin/runners/lib/sandbox/worktree.js +174 -174
- package/bin/runners/lib/scan-output.js +525 -190
- package/bin/runners/lib/schema-validator.js +350 -350
- package/bin/runners/lib/schemas/contracts.schema.json +160 -160
- package/bin/runners/lib/schemas/finding.schema.json +100 -100
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
- package/bin/runners/lib/schemas/validator.js +438 -438
- package/bin/runners/lib/score-history.js +282 -282
- package/bin/runners/lib/share-pack.js +239 -239
- package/bin/runners/lib/snippets.js +67 -67
- package/bin/runners/lib/status-output.js +253 -253
- package/bin/runners/lib/terminal-ui.js +351 -271
- package/bin/runners/lib/upsell.js +510 -510
- package/bin/runners/lib/usage.js +153 -153
- package/bin/runners/lib/validate-patch.js +156 -156
- package/bin/runners/lib/verdict-engine.js +628 -628
- package/bin/runners/reality/engine.js +917 -917
- package/bin/runners/reality/flows.js +122 -122
- package/bin/runners/reality/report.js +378 -378
- package/bin/runners/reality/session.js +193 -193
- package/bin/runners/runGuard.js +168 -168
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runProve.js +8 -0
- package/bin/runners/runReality.js +14 -0
- package/bin/runners/runScan.js +17 -1
- package/bin/runners/runTruth.js +15 -3
- package/mcp-server/tier-auth.js +4 -4
- package/mcp-server/tools/index.js +72 -72
- package/package.json +1 -1
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reality Proof Graph - Module Index
|
|
3
|
-
*
|
|
4
|
-
* Exports all graph functionality for CLI and MCP use
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
"use strict";
|
|
8
|
-
|
|
9
|
-
const { extractStaticGraph } = require("./static-extractor");
|
|
10
|
-
const { buildProofGraph, mergeRuntimeResults, computeGraphDiff, getFindingsFromGraph } = require("./graph-builder");
|
|
11
|
-
const { renderGraphHtml, renderGraphMermaid } = require("./html-renderer");
|
|
12
|
-
const { generateFetchWrapper, collectRequests, buildRuntimeEdges } = require("./runtime-collector");
|
|
13
|
-
|
|
14
|
-
module.exports = {
|
|
15
|
-
// Static extraction
|
|
16
|
-
extractStaticGraph,
|
|
17
|
-
|
|
18
|
-
// Graph building
|
|
19
|
-
buildProofGraph,
|
|
20
|
-
mergeRuntimeResults,
|
|
21
|
-
computeGraphDiff,
|
|
22
|
-
getFindingsFromGraph,
|
|
23
|
-
|
|
24
|
-
// Rendering
|
|
25
|
-
renderGraphHtml,
|
|
26
|
-
renderGraphMermaid,
|
|
27
|
-
|
|
28
|
-
// Runtime collection
|
|
29
|
-
generateFetchWrapper,
|
|
30
|
-
collectRequests,
|
|
31
|
-
buildRuntimeEdges
|
|
32
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Reality Proof Graph - Module Index
|
|
3
|
+
*
|
|
4
|
+
* Exports all graph functionality for CLI and MCP use
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
const { extractStaticGraph } = require("./static-extractor");
|
|
10
|
+
const { buildProofGraph, mergeRuntimeResults, computeGraphDiff, getFindingsFromGraph } = require("./graph-builder");
|
|
11
|
+
const { renderGraphHtml, renderGraphMermaid } = require("./html-renderer");
|
|
12
|
+
const { generateFetchWrapper, collectRequests, buildRuntimeEdges } = require("./runtime-collector");
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
// Static extraction
|
|
16
|
+
extractStaticGraph,
|
|
17
|
+
|
|
18
|
+
// Graph building
|
|
19
|
+
buildProofGraph,
|
|
20
|
+
mergeRuntimeResults,
|
|
21
|
+
computeGraphDiff,
|
|
22
|
+
getFindingsFromGraph,
|
|
23
|
+
|
|
24
|
+
// Rendering
|
|
25
|
+
renderGraphHtml,
|
|
26
|
+
renderGraphMermaid,
|
|
27
|
+
|
|
28
|
+
// Runtime collection
|
|
29
|
+
generateFetchWrapper,
|
|
30
|
+
collectRequests,
|
|
31
|
+
buildRuntimeEdges
|
|
32
|
+
};
|
|
@@ -1,215 +1,215 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runtime Collector
|
|
3
|
-
* Collects runtime edges during reality mode execution
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
"use strict";
|
|
7
|
-
|
|
8
|
-
const crypto = require("crypto");
|
|
9
|
-
|
|
10
|
-
function sha256(text) {
|
|
11
|
-
return crypto.createHash("sha256").update(text).digest("hex").slice(0, 16);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Generate client-side fetch wrapper code to inject
|
|
16
|
-
*/
|
|
17
|
-
function generateFetchWrapper() {
|
|
18
|
-
return `
|
|
19
|
-
(function() {
|
|
20
|
-
if (window.__vibecheck_fetch_patched) return;
|
|
21
|
-
window.__vibecheck_fetch_patched = true;
|
|
22
|
-
window.__vibecheck_requests = [];
|
|
23
|
-
|
|
24
|
-
const originalFetch = window.fetch;
|
|
25
|
-
window.fetch = async function(...args) {
|
|
26
|
-
const start = Date.now();
|
|
27
|
-
const url = typeof args[0] === 'string' ? args[0] : args[0]?.url;
|
|
28
|
-
const method = args[1]?.method || 'GET';
|
|
29
|
-
const correlationId = Math.random().toString(36).slice(2);
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
const newArgs = [...args];
|
|
33
|
-
if (typeof newArgs[1] === 'object') {
|
|
34
|
-
newArgs[1] = { ...newArgs[1], headers: { ...newArgs[1].headers, 'x-vibecheck-trace': correlationId } };
|
|
35
|
-
} else {
|
|
36
|
-
newArgs[1] = { headers: { 'x-vibecheck-trace': correlationId } };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const response = await originalFetch.apply(this, newArgs);
|
|
40
|
-
const latencyMs = Date.now() - start;
|
|
41
|
-
|
|
42
|
-
window.__vibecheck_requests.push({
|
|
43
|
-
correlationId,
|
|
44
|
-
method: method.toUpperCase(),
|
|
45
|
-
url,
|
|
46
|
-
status: response.status,
|
|
47
|
-
latencyMs,
|
|
48
|
-
error: null,
|
|
49
|
-
timestamp: Date.now()
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
return response;
|
|
53
|
-
} catch (error) {
|
|
54
|
-
window.__vibecheck_requests.push({
|
|
55
|
-
correlationId,
|
|
56
|
-
method: method.toUpperCase(),
|
|
57
|
-
url,
|
|
58
|
-
status: 0,
|
|
59
|
-
latencyMs: Date.now() - start,
|
|
60
|
-
error: error.message,
|
|
61
|
-
timestamp: Date.now()
|
|
62
|
-
});
|
|
63
|
-
throw error;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
})();
|
|
67
|
-
`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Collect requests from page
|
|
72
|
-
*/
|
|
73
|
-
async function collectRequests(page) {
|
|
74
|
-
try {
|
|
75
|
-
return await page.evaluate(() => {
|
|
76
|
-
const requests = window.__vibecheck_requests || [];
|
|
77
|
-
window.__vibecheck_requests = [];
|
|
78
|
-
return requests;
|
|
79
|
-
});
|
|
80
|
-
} catch {
|
|
81
|
-
return [];
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Build runtime edges from collected requests
|
|
87
|
-
*/
|
|
88
|
-
function buildRuntimeEdges(requests, staticGraph) {
|
|
89
|
-
const edges = [];
|
|
90
|
-
const nodeMap = new Map(staticGraph.nodes.map(n => [n.id, n]));
|
|
91
|
-
|
|
92
|
-
// Find network_call nodes that match requests
|
|
93
|
-
const networkNodes = staticGraph.nodes.filter(n => n.type === "network_call");
|
|
94
|
-
const routeNodes = staticGraph.nodes.filter(n => n.type === "server_route");
|
|
95
|
-
|
|
96
|
-
for (const req of requests) {
|
|
97
|
-
// Find matching network call node
|
|
98
|
-
const networkNode = networkNodes.find(n =>
|
|
99
|
-
n.url === req.url &&
|
|
100
|
-
(n.method === "*" || n.method === req.method)
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
// Find matching server route node
|
|
104
|
-
const routeNode = routeNodes.find(n =>
|
|
105
|
-
matchesRoute(n.path, req.url) &&
|
|
106
|
-
(n.method === "*" || n.method === req.method)
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
if (networkNode && routeNode) {
|
|
110
|
-
edges.push({
|
|
111
|
-
id: `runtime_${sha256(networkNode.id + "_" + routeNode.id + "_" + req.correlationId)}`,
|
|
112
|
-
from: networkNode.id,
|
|
113
|
-
to: routeNode.id,
|
|
114
|
-
type: "runtime_verified",
|
|
115
|
-
confidence: "high",
|
|
116
|
-
data: {
|
|
117
|
-
status: req.status,
|
|
118
|
-
latencyMs: req.latencyMs,
|
|
119
|
-
error: req.error,
|
|
120
|
-
correlationId: req.correlationId
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Check for failed requests that indicate broken edges
|
|
126
|
-
if (req.status >= 400 || req.error) {
|
|
127
|
-
edges.push({
|
|
128
|
-
id: `runtime_error_${sha256(req.url + "_" + req.correlationId)}`,
|
|
129
|
-
from: networkNode?.id || `client_${sha256(req.url)}`,
|
|
130
|
-
to: routeNode?.id || `route_${sha256(req.url)}`,
|
|
131
|
-
type: "runtime_error",
|
|
132
|
-
confidence: "high",
|
|
133
|
-
broken: true,
|
|
134
|
-
brokenReason: req.error || `Server returned ${req.status}`,
|
|
135
|
-
data: {
|
|
136
|
-
status: req.status,
|
|
137
|
-
latencyMs: req.latencyMs,
|
|
138
|
-
error: req.error,
|
|
139
|
-
url: req.url,
|
|
140
|
-
method: req.method
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return edges;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function matchesRoute(pattern, url) {
|
|
150
|
-
// Extract path from URL
|
|
151
|
-
let path;
|
|
152
|
-
try {
|
|
153
|
-
path = new URL(url, "http://localhost").pathname;
|
|
154
|
-
} catch {
|
|
155
|
-
path = url;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Normalize
|
|
159
|
-
const normPattern = pattern.replace(/\/$/, "") || "/";
|
|
160
|
-
const normPath = path.replace(/\/$/, "") || "/";
|
|
161
|
-
|
|
162
|
-
if (normPattern === normPath) return true;
|
|
163
|
-
|
|
164
|
-
// Check parameterized match
|
|
165
|
-
const patternParts = normPattern.split("/").filter(Boolean);
|
|
166
|
-
const pathParts = normPath.split("/").filter(Boolean);
|
|
167
|
-
|
|
168
|
-
if (patternParts.length !== pathParts.length) return false;
|
|
169
|
-
|
|
170
|
-
for (let i = 0; i < patternParts.length; i++) {
|
|
171
|
-
const p = patternParts[i];
|
|
172
|
-
if (p.startsWith(":") || p.startsWith("*")) continue;
|
|
173
|
-
if (p !== pathParts[i]) return false;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Generate Fastify hooks code for server-side tracing
|
|
181
|
-
*/
|
|
182
|
-
function generateFastifyHooks() {
|
|
183
|
-
return `
|
|
184
|
-
// Add to your Fastify server for runtime tracing
|
|
185
|
-
fastify.addHook('onRequest', async (request, reply) => {
|
|
186
|
-
request.vibecheckTrace = {
|
|
187
|
-
correlationId: request.headers['x-vibecheck-trace'] || null,
|
|
188
|
-
startTime: Date.now()
|
|
189
|
-
};
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
fastify.addHook('onResponse', async (request, reply) => {
|
|
193
|
-
if (!request.vibecheckTrace) return;
|
|
194
|
-
|
|
195
|
-
const trace = {
|
|
196
|
-
correlationId: request.vibecheckTrace.correlationId,
|
|
197
|
-
routeId: request.routeOptions?.url || request.url,
|
|
198
|
-
method: request.method,
|
|
199
|
-
status: reply.statusCode,
|
|
200
|
-
latencyMs: Date.now() - request.vibecheckTrace.startTime,
|
|
201
|
-
authed: !!request.user
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
// Log or send to vibecheck collector
|
|
205
|
-
console.log('[vibecheck-trace]', JSON.stringify(trace));
|
|
206
|
-
});
|
|
207
|
-
`;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
module.exports = {
|
|
211
|
-
generateFetchWrapper,
|
|
212
|
-
collectRequests,
|
|
213
|
-
buildRuntimeEdges,
|
|
214
|
-
generateFastifyHooks
|
|
215
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Collector
|
|
3
|
+
* Collects runtime edges during reality mode execution
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const crypto = require("crypto");
|
|
9
|
+
|
|
10
|
+
function sha256(text) {
|
|
11
|
+
return crypto.createHash("sha256").update(text).digest("hex").slice(0, 16);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generate client-side fetch wrapper code to inject
|
|
16
|
+
*/
|
|
17
|
+
function generateFetchWrapper() {
|
|
18
|
+
return `
|
|
19
|
+
(function() {
|
|
20
|
+
if (window.__vibecheck_fetch_patched) return;
|
|
21
|
+
window.__vibecheck_fetch_patched = true;
|
|
22
|
+
window.__vibecheck_requests = [];
|
|
23
|
+
|
|
24
|
+
const originalFetch = window.fetch;
|
|
25
|
+
window.fetch = async function(...args) {
|
|
26
|
+
const start = Date.now();
|
|
27
|
+
const url = typeof args[0] === 'string' ? args[0] : args[0]?.url;
|
|
28
|
+
const method = args[1]?.method || 'GET';
|
|
29
|
+
const correlationId = Math.random().toString(36).slice(2);
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const newArgs = [...args];
|
|
33
|
+
if (typeof newArgs[1] === 'object') {
|
|
34
|
+
newArgs[1] = { ...newArgs[1], headers: { ...newArgs[1].headers, 'x-vibecheck-trace': correlationId } };
|
|
35
|
+
} else {
|
|
36
|
+
newArgs[1] = { headers: { 'x-vibecheck-trace': correlationId } };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const response = await originalFetch.apply(this, newArgs);
|
|
40
|
+
const latencyMs = Date.now() - start;
|
|
41
|
+
|
|
42
|
+
window.__vibecheck_requests.push({
|
|
43
|
+
correlationId,
|
|
44
|
+
method: method.toUpperCase(),
|
|
45
|
+
url,
|
|
46
|
+
status: response.status,
|
|
47
|
+
latencyMs,
|
|
48
|
+
error: null,
|
|
49
|
+
timestamp: Date.now()
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return response;
|
|
53
|
+
} catch (error) {
|
|
54
|
+
window.__vibecheck_requests.push({
|
|
55
|
+
correlationId,
|
|
56
|
+
method: method.toUpperCase(),
|
|
57
|
+
url,
|
|
58
|
+
status: 0,
|
|
59
|
+
latencyMs: Date.now() - start,
|
|
60
|
+
error: error.message,
|
|
61
|
+
timestamp: Date.now()
|
|
62
|
+
});
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
})();
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Collect requests from page
|
|
72
|
+
*/
|
|
73
|
+
async function collectRequests(page) {
|
|
74
|
+
try {
|
|
75
|
+
return await page.evaluate(() => {
|
|
76
|
+
const requests = window.__vibecheck_requests || [];
|
|
77
|
+
window.__vibecheck_requests = [];
|
|
78
|
+
return requests;
|
|
79
|
+
});
|
|
80
|
+
} catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Build runtime edges from collected requests
|
|
87
|
+
*/
|
|
88
|
+
function buildRuntimeEdges(requests, staticGraph) {
|
|
89
|
+
const edges = [];
|
|
90
|
+
const nodeMap = new Map(staticGraph.nodes.map(n => [n.id, n]));
|
|
91
|
+
|
|
92
|
+
// Find network_call nodes that match requests
|
|
93
|
+
const networkNodes = staticGraph.nodes.filter(n => n.type === "network_call");
|
|
94
|
+
const routeNodes = staticGraph.nodes.filter(n => n.type === "server_route");
|
|
95
|
+
|
|
96
|
+
for (const req of requests) {
|
|
97
|
+
// Find matching network call node
|
|
98
|
+
const networkNode = networkNodes.find(n =>
|
|
99
|
+
n.url === req.url &&
|
|
100
|
+
(n.method === "*" || n.method === req.method)
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// Find matching server route node
|
|
104
|
+
const routeNode = routeNodes.find(n =>
|
|
105
|
+
matchesRoute(n.path, req.url) &&
|
|
106
|
+
(n.method === "*" || n.method === req.method)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if (networkNode && routeNode) {
|
|
110
|
+
edges.push({
|
|
111
|
+
id: `runtime_${sha256(networkNode.id + "_" + routeNode.id + "_" + req.correlationId)}`,
|
|
112
|
+
from: networkNode.id,
|
|
113
|
+
to: routeNode.id,
|
|
114
|
+
type: "runtime_verified",
|
|
115
|
+
confidence: "high",
|
|
116
|
+
data: {
|
|
117
|
+
status: req.status,
|
|
118
|
+
latencyMs: req.latencyMs,
|
|
119
|
+
error: req.error,
|
|
120
|
+
correlationId: req.correlationId
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Check for failed requests that indicate broken edges
|
|
126
|
+
if (req.status >= 400 || req.error) {
|
|
127
|
+
edges.push({
|
|
128
|
+
id: `runtime_error_${sha256(req.url + "_" + req.correlationId)}`,
|
|
129
|
+
from: networkNode?.id || `client_${sha256(req.url)}`,
|
|
130
|
+
to: routeNode?.id || `route_${sha256(req.url)}`,
|
|
131
|
+
type: "runtime_error",
|
|
132
|
+
confidence: "high",
|
|
133
|
+
broken: true,
|
|
134
|
+
brokenReason: req.error || `Server returned ${req.status}`,
|
|
135
|
+
data: {
|
|
136
|
+
status: req.status,
|
|
137
|
+
latencyMs: req.latencyMs,
|
|
138
|
+
error: req.error,
|
|
139
|
+
url: req.url,
|
|
140
|
+
method: req.method
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return edges;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function matchesRoute(pattern, url) {
|
|
150
|
+
// Extract path from URL
|
|
151
|
+
let path;
|
|
152
|
+
try {
|
|
153
|
+
path = new URL(url, "http://localhost").pathname;
|
|
154
|
+
} catch {
|
|
155
|
+
path = url;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Normalize
|
|
159
|
+
const normPattern = pattern.replace(/\/$/, "") || "/";
|
|
160
|
+
const normPath = path.replace(/\/$/, "") || "/";
|
|
161
|
+
|
|
162
|
+
if (normPattern === normPath) return true;
|
|
163
|
+
|
|
164
|
+
// Check parameterized match
|
|
165
|
+
const patternParts = normPattern.split("/").filter(Boolean);
|
|
166
|
+
const pathParts = normPath.split("/").filter(Boolean);
|
|
167
|
+
|
|
168
|
+
if (patternParts.length !== pathParts.length) return false;
|
|
169
|
+
|
|
170
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
171
|
+
const p = patternParts[i];
|
|
172
|
+
if (p.startsWith(":") || p.startsWith("*")) continue;
|
|
173
|
+
if (p !== pathParts[i]) return false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Generate Fastify hooks code for server-side tracing
|
|
181
|
+
*/
|
|
182
|
+
function generateFastifyHooks() {
|
|
183
|
+
return `
|
|
184
|
+
// Add to your Fastify server for runtime tracing
|
|
185
|
+
fastify.addHook('onRequest', async (request, reply) => {
|
|
186
|
+
request.vibecheckTrace = {
|
|
187
|
+
correlationId: request.headers['x-vibecheck-trace'] || null,
|
|
188
|
+
startTime: Date.now()
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
fastify.addHook('onResponse', async (request, reply) => {
|
|
193
|
+
if (!request.vibecheckTrace) return;
|
|
194
|
+
|
|
195
|
+
const trace = {
|
|
196
|
+
correlationId: request.vibecheckTrace.correlationId,
|
|
197
|
+
routeId: request.routeOptions?.url || request.url,
|
|
198
|
+
method: request.method,
|
|
199
|
+
status: reply.statusCode,
|
|
200
|
+
latencyMs: Date.now() - request.vibecheckTrace.startTime,
|
|
201
|
+
authed: !!request.user
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// Log or send to vibecheck collector
|
|
205
|
+
console.log('[vibecheck-trace]', JSON.stringify(trace));
|
|
206
|
+
});
|
|
207
|
+
`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
module.exports = {
|
|
211
|
+
generateFetchWrapper,
|
|
212
|
+
collectRequests,
|
|
213
|
+
buildRuntimeEdges,
|
|
214
|
+
generateFastifyHooks
|
|
215
|
+
};
|