@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
package/bin/runners/lib/llm.js
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
// bin/runners/lib/llm.js
|
|
2
|
-
const https = require("https");
|
|
3
|
-
const http = require("http");
|
|
4
|
-
const { URL } = require("url");
|
|
5
|
-
|
|
6
|
-
function postJson(urlStr, headers, bodyObj) {
|
|
7
|
-
const url = new URL(urlStr);
|
|
8
|
-
const lib = url.protocol === "https:" ? https : http;
|
|
9
|
-
|
|
10
|
-
const data = JSON.stringify(bodyObj);
|
|
11
|
-
|
|
12
|
-
return new Promise((resolve, reject) => {
|
|
13
|
-
const req = lib.request(
|
|
14
|
-
{
|
|
15
|
-
method: "POST",
|
|
16
|
-
hostname: url.hostname,
|
|
17
|
-
port: url.port || (url.protocol === "https:" ? 443 : 80),
|
|
18
|
-
path: url.pathname,
|
|
19
|
-
headers: {
|
|
20
|
-
"Content-Type": "application/json",
|
|
21
|
-
"Content-Length": Buffer.byteLength(data),
|
|
22
|
-
...headers
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
(res) => {
|
|
26
|
-
let buf = "";
|
|
27
|
-
res.on("data", (d) => (buf += d));
|
|
28
|
-
res.on("end", () => {
|
|
29
|
-
try {
|
|
30
|
-
const json = JSON.parse(buf);
|
|
31
|
-
resolve({ status: res.statusCode, json, raw: buf });
|
|
32
|
-
} catch (e) {
|
|
33
|
-
reject(new Error(`LLM response not JSON (status ${res.statusCode}): ${buf.slice(0, 400)}`));
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
req.on("error", reject);
|
|
40
|
-
req.write(data);
|
|
41
|
-
req.end();
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function generatePatchJson(prompt) {
|
|
46
|
-
const baseUrl = process.env.VIBECHECK_LLM_BASE_URL;
|
|
47
|
-
const apiKey = process.env.VIBECHECK_LLM_API_KEY;
|
|
48
|
-
const model = process.env.VIBECHECK_LLM_MODEL || "gpt-4.1-mini";
|
|
49
|
-
|
|
50
|
-
if (!baseUrl || !apiKey) {
|
|
51
|
-
const err = new Error("LLM not configured: set VIBECHECK_LLM_BASE_URL and VIBECHECK_LLM_API_KEY");
|
|
52
|
-
err.code = "VIBECHECK_LLM_NOT_CONFIGURED";
|
|
53
|
-
throw err;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const headers = { Authorization: `Bearer ${apiKey}` };
|
|
57
|
-
|
|
58
|
-
const body = {
|
|
59
|
-
model,
|
|
60
|
-
temperature: 0.1,
|
|
61
|
-
messages: [
|
|
62
|
-
{ role: "system", content: "Return JSON only." },
|
|
63
|
-
{ role: "user", content: prompt }
|
|
64
|
-
]
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const r = await postJson(baseUrl, headers, body);
|
|
68
|
-
|
|
69
|
-
const content = r.json?.choices?.[0]?.message?.content;
|
|
70
|
-
if (!content) throw new Error("LLM response missing choices[0].message.content");
|
|
71
|
-
|
|
72
|
-
return JSON.parse(content);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
module.exports = { generatePatchJson };
|
|
1
|
+
// bin/runners/lib/llm.js
|
|
2
|
+
const https = require("https");
|
|
3
|
+
const http = require("http");
|
|
4
|
+
const { URL } = require("url");
|
|
5
|
+
|
|
6
|
+
function postJson(urlStr, headers, bodyObj) {
|
|
7
|
+
const url = new URL(urlStr);
|
|
8
|
+
const lib = url.protocol === "https:" ? https : http;
|
|
9
|
+
|
|
10
|
+
const data = JSON.stringify(bodyObj);
|
|
11
|
+
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const req = lib.request(
|
|
14
|
+
{
|
|
15
|
+
method: "POST",
|
|
16
|
+
hostname: url.hostname,
|
|
17
|
+
port: url.port || (url.protocol === "https:" ? 443 : 80),
|
|
18
|
+
path: url.pathname,
|
|
19
|
+
headers: {
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
"Content-Length": Buffer.byteLength(data),
|
|
22
|
+
...headers
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
(res) => {
|
|
26
|
+
let buf = "";
|
|
27
|
+
res.on("data", (d) => (buf += d));
|
|
28
|
+
res.on("end", () => {
|
|
29
|
+
try {
|
|
30
|
+
const json = JSON.parse(buf);
|
|
31
|
+
resolve({ status: res.statusCode, json, raw: buf });
|
|
32
|
+
} catch (e) {
|
|
33
|
+
reject(new Error(`LLM response not JSON (status ${res.statusCode}): ${buf.slice(0, 400)}`));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
req.on("error", reject);
|
|
40
|
+
req.write(data);
|
|
41
|
+
req.end();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function generatePatchJson(prompt) {
|
|
46
|
+
const baseUrl = process.env.VIBECHECK_LLM_BASE_URL;
|
|
47
|
+
const apiKey = process.env.VIBECHECK_LLM_API_KEY;
|
|
48
|
+
const model = process.env.VIBECHECK_LLM_MODEL || "gpt-4.1-mini";
|
|
49
|
+
|
|
50
|
+
if (!baseUrl || !apiKey) {
|
|
51
|
+
const err = new Error("LLM not configured: set VIBECHECK_LLM_BASE_URL and VIBECHECK_LLM_API_KEY");
|
|
52
|
+
err.code = "VIBECHECK_LLM_NOT_CONFIGURED";
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const headers = { Authorization: `Bearer ${apiKey}` };
|
|
57
|
+
|
|
58
|
+
const body = {
|
|
59
|
+
model,
|
|
60
|
+
temperature: 0.1,
|
|
61
|
+
messages: [
|
|
62
|
+
{ role: "system", content: "Return JSON only." },
|
|
63
|
+
{ role: "user", content: prompt }
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const r = await postJson(baseUrl, headers, body);
|
|
68
|
+
|
|
69
|
+
const content = r.json?.choices?.[0]?.message?.content;
|
|
70
|
+
if (!content) throw new Error("LLM response missing choices[0].message.content");
|
|
71
|
+
|
|
72
|
+
return JSON.parse(content);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { generatePatchJson };
|
package/bin/runners/lib/meter.js
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
// bin/runners/lib/meter.js
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const os = require("os");
|
|
5
|
-
|
|
6
|
-
function monthKey(d = new Date()) {
|
|
7
|
-
const y = d.getUTCFullYear();
|
|
8
|
-
const m = String(d.getUTCMonth() + 1).padStart(2, "0");
|
|
9
|
-
return `${y}-${m}`;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function ensureDir(p) {
|
|
13
|
-
fs.mkdirSync(p, { recursive: true });
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function readJson(p, fallback) {
|
|
17
|
-
try { return JSON.parse(fs.readFileSync(p, "utf8")); } catch { return fallback; }
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function writeJson(p, obj) {
|
|
21
|
-
fs.writeFileSync(p, JSON.stringify(obj, null, 2));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function defaultStorePath() {
|
|
25
|
-
return path.join(os.homedir(), ".vibecheck", "usage.json");
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Local meter:
|
|
30
|
-
* - Free tier: 10 ship checks per calendar month
|
|
31
|
-
* - Paid tiers: unlimited (you can override tier via env while developing)
|
|
32
|
-
*/
|
|
33
|
-
function consumeShipCheckOrThrow({ tier, limitFree = 10 } = {}) {
|
|
34
|
-
const effectiveTier = (tier || process.env.VIBECHECK_TIER || "free").toLowerCase();
|
|
35
|
-
|
|
36
|
-
if (effectiveTier !== "free") {
|
|
37
|
-
return { ok: true, remaining: Infinity, tier: effectiveTier };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const storePath = process.env.VIBECHECK_USAGE_PATH || defaultStorePath();
|
|
41
|
-
ensureDir(path.dirname(storePath));
|
|
42
|
-
const store = readJson(storePath, { months: {} });
|
|
43
|
-
|
|
44
|
-
const key = monthKey();
|
|
45
|
-
const used = store.months[key]?.shipChecks || 0;
|
|
46
|
-
|
|
47
|
-
if (used >= limitFree) {
|
|
48
|
-
const err = new Error(`Free tier limit reached: ${limitFree} full ship checks/month. Upgrade to continue.`);
|
|
49
|
-
err.code = "VIBECHECK_LIMIT_REACHED";
|
|
50
|
-
err.meta = { used, limitFree, month: key };
|
|
51
|
-
throw err;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
store.months[key] = store.months[key] || {};
|
|
55
|
-
store.months[key].shipChecks = used + 1;
|
|
56
|
-
writeJson(storePath, store);
|
|
57
|
-
|
|
58
|
-
return { ok: true, remaining: limitFree - (used + 1), tier: effectiveTier };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
module.exports = { consumeShipCheckOrThrow };
|
|
1
|
+
// bin/runners/lib/meter.js
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const os = require("os");
|
|
5
|
+
|
|
6
|
+
function monthKey(d = new Date()) {
|
|
7
|
+
const y = d.getUTCFullYear();
|
|
8
|
+
const m = String(d.getUTCMonth() + 1).padStart(2, "0");
|
|
9
|
+
return `${y}-${m}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function ensureDir(p) {
|
|
13
|
+
fs.mkdirSync(p, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function readJson(p, fallback) {
|
|
17
|
+
try { return JSON.parse(fs.readFileSync(p, "utf8")); } catch { return fallback; }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function writeJson(p, obj) {
|
|
21
|
+
fs.writeFileSync(p, JSON.stringify(obj, null, 2));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function defaultStorePath() {
|
|
25
|
+
return path.join(os.homedir(), ".vibecheck", "usage.json");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Local meter:
|
|
30
|
+
* - Free tier: 10 ship checks per calendar month
|
|
31
|
+
* - Paid tiers: unlimited (you can override tier via env while developing)
|
|
32
|
+
*/
|
|
33
|
+
function consumeShipCheckOrThrow({ tier, limitFree = 10 } = {}) {
|
|
34
|
+
const effectiveTier = (tier || process.env.VIBECHECK_TIER || "free").toLowerCase();
|
|
35
|
+
|
|
36
|
+
if (effectiveTier !== "free") {
|
|
37
|
+
return { ok: true, remaining: Infinity, tier: effectiveTier };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const storePath = process.env.VIBECHECK_USAGE_PATH || defaultStorePath();
|
|
41
|
+
ensureDir(path.dirname(storePath));
|
|
42
|
+
const store = readJson(storePath, { months: {} });
|
|
43
|
+
|
|
44
|
+
const key = monthKey();
|
|
45
|
+
const used = store.months[key]?.shipChecks || 0;
|
|
46
|
+
|
|
47
|
+
if (used >= limitFree) {
|
|
48
|
+
const err = new Error(`Free tier limit reached: ${limitFree} full ship checks/month. Upgrade to continue.`);
|
|
49
|
+
err.code = "VIBECHECK_LIMIT_REACHED";
|
|
50
|
+
err.meta = { used, limitFree, month: key };
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
store.months[key] = store.months[key] || {};
|
|
55
|
+
store.months[key].shipChecks = used + 1;
|
|
56
|
+
writeJson(storePath, store);
|
|
57
|
+
|
|
58
|
+
return { ok: true, remaining: limitFree - (used + 1), tier: effectiveTier };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = { consumeShipCheckOrThrow };
|
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
// bin/runners/lib/missions/evidence.js
|
|
2
|
-
const fg = require("fast-glob");
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const { collectEvidenceSnippets, collectRegexSnippets } = require("../snippets");
|
|
6
|
-
|
|
7
|
-
async function findFiles(repoRoot, patterns, limit = 12) {
|
|
8
|
-
const files = await fg(patterns, {
|
|
9
|
-
cwd: repoRoot,
|
|
10
|
-
onlyFiles: true,
|
|
11
|
-
absolute: false,
|
|
12
|
-
ignore: ["**/node_modules/**","**/.next/**","**/dist/**","**/build/**"]
|
|
13
|
-
});
|
|
14
|
-
return files.slice(0, limit);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function uniq(arr) {
|
|
18
|
-
return Array.from(new Set((arr || []).filter(Boolean)));
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function evidenceFilesFromFindings(findings) {
|
|
22
|
-
const files = [];
|
|
23
|
-
for (const f of findings || []) {
|
|
24
|
-
for (const ev of (f.evidence || [])) {
|
|
25
|
-
if (ev.file) files.push(ev.file);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return uniq(files);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function handlerFilesFromTruthpack(truthpack) {
|
|
32
|
-
const server = truthpack?.routes?.server || [];
|
|
33
|
-
return uniq(server.map(r => r.handler).filter(Boolean));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function enforcementHandlerFiles(truthpack) {
|
|
37
|
-
const checks = truthpack?.enforcement?.checks || [];
|
|
38
|
-
return uniq(checks.map(c => c.handler).filter(Boolean));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function stripeWebhookFiles(truthpack) {
|
|
42
|
-
const c = truthpack?.billing?.webhookCandidates || [];
|
|
43
|
-
return uniq(c.map(x => x.file).filter(Boolean));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function middlewareFiles(truthpack) {
|
|
47
|
-
const m = truthpack?.auth?.nextMiddleware || [];
|
|
48
|
-
return uniq(m.map(x => x.file).filter(Boolean));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async function expandEvidence({ repoRoot, truthpack, mission, targetFindings }) {
|
|
52
|
-
const type = mission?.type || "GENERIC_FIX";
|
|
53
|
-
|
|
54
|
-
let allowedFiles = evidenceFilesFromFindings(targetFindings);
|
|
55
|
-
|
|
56
|
-
if (type === "FIX_ENV_CONTRACT") {
|
|
57
|
-
allowedFiles = uniq([
|
|
58
|
-
...allowedFiles,
|
|
59
|
-
".env.example", ".env.template", ".env.sample", ".env"
|
|
60
|
-
]);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (type === "FIX_MISSING_ROUTE") {
|
|
64
|
-
allowedFiles = uniq([
|
|
65
|
-
...allowedFiles,
|
|
66
|
-
...handlerFilesFromTruthpack(truthpack)
|
|
67
|
-
]);
|
|
68
|
-
const nextApiFiles = await findFiles(repoRoot, ["app/api/**/route.@(ts|js)", "pages/api/**/*.@(ts|js)"], 24);
|
|
69
|
-
allowedFiles = uniq([...allowedFiles, ...nextApiFiles]);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (type === "ADD_SERVER_AUTH") {
|
|
73
|
-
allowedFiles = uniq([
|
|
74
|
-
...allowedFiles,
|
|
75
|
-
...middlewareFiles(truthpack),
|
|
76
|
-
...handlerFilesFromTruthpack(truthpack)
|
|
77
|
-
]);
|
|
78
|
-
const authLibs = await findFiles(repoRoot, ["**/*auth*.@(ts|js)","**/*session*.@(ts|js)","**/*jwt*.@(ts|js)"], 12);
|
|
79
|
-
allowedFiles = uniq([...allowedFiles, ...authLibs]);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (type === "FIX_STRIPE_WEBHOOKS") {
|
|
83
|
-
allowedFiles = uniq([...allowedFiles, ...stripeWebhookFiles(truthpack)]);
|
|
84
|
-
const billingLibs = await findFiles(repoRoot, ["**/*stripe*.@(ts|js)","**/*billing*.@(ts|js)","**/*webhook*.@(ts|js)"], 12);
|
|
85
|
-
allowedFiles = uniq([...allowedFiles, ...billingLibs]);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (type === "ENFORCE_PAID_SURFACE") {
|
|
89
|
-
allowedFiles = uniq([...allowedFiles, ...enforcementHandlerFiles(truthpack)]);
|
|
90
|
-
const entitlementLibs = await findFiles(repoRoot, ["**/*entitlement*.@(ts|js)","**/*plan*.@(ts|js)","**/*tier*.@(ts|js)"], 12);
|
|
91
|
-
allowedFiles = uniq([...allowedFiles, ...entitlementLibs]);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (type === "REMOVE_OWNER_MODE") {
|
|
95
|
-
const bypassFiles = await findFiles(repoRoot, ["**/*owner*mode*.@(ts|js)","**/*entitlement*.@(ts|js)","**/*auth*.@(ts|js)"], 20);
|
|
96
|
-
allowedFiles = uniq([...allowedFiles, ...bypassFiles]);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (type === "FIX_FAKE_SUCCESS") {
|
|
100
|
-
const uiFiles = await findFiles(repoRoot, ["app/**/*.@(ts|tsx|js|jsx)","src/**/*.@(ts|tsx|js|jsx)"], 20);
|
|
101
|
-
allowedFiles = uniq([...allowedFiles, ...uiFiles]);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const evidenceSnips = collectEvidenceSnippets(repoRoot, targetFindings, 12);
|
|
105
|
-
|
|
106
|
-
const regexByType = {
|
|
107
|
-
FIX_STRIPE_WEBHOOKS: /(constructEvent|stripe-signature|bodyParser\s*:\s*false|req\.(text|arrayBuffer)\(|event\.id|idempotenc)/i,
|
|
108
|
-
ENFORCE_PAID_SURFACE: /(enforceFeature|enforceLimit|getEntitlements|tier|plan|subscription|credits)/i,
|
|
109
|
-
ADD_SERVER_AUTH: /(authorization|bearer|jwtVerify|getServerSession|clerk|supabase|preHandler|onRequest|rbac|permissions)/i,
|
|
110
|
-
REMOVE_OWNER_MODE: /(OWNER_MODE|GUARDRAIL_OWNER_MODE|VIBECHECK_OWNER_MODE)/i,
|
|
111
|
-
FIX_FAKE_SUCCESS: /(toast\.success|router\.push|navigate\(|fetch\(|axios\.)/i,
|
|
112
|
-
FIX_ENV_CONTRACT: /(^|\s)(export\s+)?[A-Z0-9_]+\s*=/,
|
|
113
|
-
FIX_MISSING_ROUTE: /(\/api\/|fetch\(|axios\.)/i,
|
|
114
|
-
FIX_DEAD_UI: /(onClick|onclick|router\.push|navigate\(|toast\.success|fetch\(|axios\.|\/api\/)/i
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const rx = regexByType[type];
|
|
118
|
-
const regexSnips = rx ? collectRegexSnippets(repoRoot, allowedFiles, rx, { pad: 4, limit: 10 }) : [];
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
allowedFiles,
|
|
122
|
-
snippets: [...evidenceSnips, ...regexSnips]
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
module.exports = { expandEvidence };
|
|
1
|
+
// bin/runners/lib/missions/evidence.js
|
|
2
|
+
const fg = require("fast-glob");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { collectEvidenceSnippets, collectRegexSnippets } = require("../snippets");
|
|
6
|
+
|
|
7
|
+
async function findFiles(repoRoot, patterns, limit = 12) {
|
|
8
|
+
const files = await fg(patterns, {
|
|
9
|
+
cwd: repoRoot,
|
|
10
|
+
onlyFiles: true,
|
|
11
|
+
absolute: false,
|
|
12
|
+
ignore: ["**/node_modules/**","**/.next/**","**/dist/**","**/build/**"]
|
|
13
|
+
});
|
|
14
|
+
return files.slice(0, limit);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function uniq(arr) {
|
|
18
|
+
return Array.from(new Set((arr || []).filter(Boolean)));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function evidenceFilesFromFindings(findings) {
|
|
22
|
+
const files = [];
|
|
23
|
+
for (const f of findings || []) {
|
|
24
|
+
for (const ev of (f.evidence || [])) {
|
|
25
|
+
if (ev.file) files.push(ev.file);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return uniq(files);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function handlerFilesFromTruthpack(truthpack) {
|
|
32
|
+
const server = truthpack?.routes?.server || [];
|
|
33
|
+
return uniq(server.map(r => r.handler).filter(Boolean));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function enforcementHandlerFiles(truthpack) {
|
|
37
|
+
const checks = truthpack?.enforcement?.checks || [];
|
|
38
|
+
return uniq(checks.map(c => c.handler).filter(Boolean));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function stripeWebhookFiles(truthpack) {
|
|
42
|
+
const c = truthpack?.billing?.webhookCandidates || [];
|
|
43
|
+
return uniq(c.map(x => x.file).filter(Boolean));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function middlewareFiles(truthpack) {
|
|
47
|
+
const m = truthpack?.auth?.nextMiddleware || [];
|
|
48
|
+
return uniq(m.map(x => x.file).filter(Boolean));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function expandEvidence({ repoRoot, truthpack, mission, targetFindings }) {
|
|
52
|
+
const type = mission?.type || "GENERIC_FIX";
|
|
53
|
+
|
|
54
|
+
let allowedFiles = evidenceFilesFromFindings(targetFindings);
|
|
55
|
+
|
|
56
|
+
if (type === "FIX_ENV_CONTRACT") {
|
|
57
|
+
allowedFiles = uniq([
|
|
58
|
+
...allowedFiles,
|
|
59
|
+
".env.example", ".env.template", ".env.sample", ".env"
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (type === "FIX_MISSING_ROUTE") {
|
|
64
|
+
allowedFiles = uniq([
|
|
65
|
+
...allowedFiles,
|
|
66
|
+
...handlerFilesFromTruthpack(truthpack)
|
|
67
|
+
]);
|
|
68
|
+
const nextApiFiles = await findFiles(repoRoot, ["app/api/**/route.@(ts|js)", "pages/api/**/*.@(ts|js)"], 24);
|
|
69
|
+
allowedFiles = uniq([...allowedFiles, ...nextApiFiles]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (type === "ADD_SERVER_AUTH") {
|
|
73
|
+
allowedFiles = uniq([
|
|
74
|
+
...allowedFiles,
|
|
75
|
+
...middlewareFiles(truthpack),
|
|
76
|
+
...handlerFilesFromTruthpack(truthpack)
|
|
77
|
+
]);
|
|
78
|
+
const authLibs = await findFiles(repoRoot, ["**/*auth*.@(ts|js)","**/*session*.@(ts|js)","**/*jwt*.@(ts|js)"], 12);
|
|
79
|
+
allowedFiles = uniq([...allowedFiles, ...authLibs]);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (type === "FIX_STRIPE_WEBHOOKS") {
|
|
83
|
+
allowedFiles = uniq([...allowedFiles, ...stripeWebhookFiles(truthpack)]);
|
|
84
|
+
const billingLibs = await findFiles(repoRoot, ["**/*stripe*.@(ts|js)","**/*billing*.@(ts|js)","**/*webhook*.@(ts|js)"], 12);
|
|
85
|
+
allowedFiles = uniq([...allowedFiles, ...billingLibs]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (type === "ENFORCE_PAID_SURFACE") {
|
|
89
|
+
allowedFiles = uniq([...allowedFiles, ...enforcementHandlerFiles(truthpack)]);
|
|
90
|
+
const entitlementLibs = await findFiles(repoRoot, ["**/*entitlement*.@(ts|js)","**/*plan*.@(ts|js)","**/*tier*.@(ts|js)"], 12);
|
|
91
|
+
allowedFiles = uniq([...allowedFiles, ...entitlementLibs]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (type === "REMOVE_OWNER_MODE") {
|
|
95
|
+
const bypassFiles = await findFiles(repoRoot, ["**/*owner*mode*.@(ts|js)","**/*entitlement*.@(ts|js)","**/*auth*.@(ts|js)"], 20);
|
|
96
|
+
allowedFiles = uniq([...allowedFiles, ...bypassFiles]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (type === "FIX_FAKE_SUCCESS") {
|
|
100
|
+
const uiFiles = await findFiles(repoRoot, ["app/**/*.@(ts|tsx|js|jsx)","src/**/*.@(ts|tsx|js|jsx)"], 20);
|
|
101
|
+
allowedFiles = uniq([...allowedFiles, ...uiFiles]);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const evidenceSnips = collectEvidenceSnippets(repoRoot, targetFindings, 12);
|
|
105
|
+
|
|
106
|
+
const regexByType = {
|
|
107
|
+
FIX_STRIPE_WEBHOOKS: /(constructEvent|stripe-signature|bodyParser\s*:\s*false|req\.(text|arrayBuffer)\(|event\.id|idempotenc)/i,
|
|
108
|
+
ENFORCE_PAID_SURFACE: /(enforceFeature|enforceLimit|getEntitlements|tier|plan|subscription|credits)/i,
|
|
109
|
+
ADD_SERVER_AUTH: /(authorization|bearer|jwtVerify|getServerSession|clerk|supabase|preHandler|onRequest|rbac|permissions)/i,
|
|
110
|
+
REMOVE_OWNER_MODE: /(OWNER_MODE|GUARDRAIL_OWNER_MODE|VIBECHECK_OWNER_MODE)/i,
|
|
111
|
+
FIX_FAKE_SUCCESS: /(toast\.success|router\.push|navigate\(|fetch\(|axios\.)/i,
|
|
112
|
+
FIX_ENV_CONTRACT: /(^|\s)(export\s+)?[A-Z0-9_]+\s*=/,
|
|
113
|
+
FIX_MISSING_ROUTE: /(\/api\/|fetch\(|axios\.)/i,
|
|
114
|
+
FIX_DEAD_UI: /(onClick|onclick|router\.push|navigate\(|toast\.success|fetch\(|axios\.|\/api\/)/i
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const rx = regexByType[type];
|
|
118
|
+
const regexSnips = rx ? collectRegexSnippets(repoRoot, allowedFiles, rx, { pad: 4, limit: 10 }) : [];
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
allowedFiles,
|
|
122
|
+
snippets: [...evidenceSnips, ...regexSnips]
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = { expandEvidence };
|
package/bin/runners/lib/patch.js
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
// bin/runners/lib/patch.js
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const { spawnSync } = require("child_process");
|
|
5
|
-
|
|
6
|
-
function ensureDir(p) {
|
|
7
|
-
fs.mkdirSync(p, { recursive: true });
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function writeTempPatch(repoRoot, diffText) {
|
|
11
|
-
const dir = path.join(repoRoot, ".vibecheck", "tmp");
|
|
12
|
-
ensureDir(dir);
|
|
13
|
-
const p = path.join(dir, `patch_${Date.now()}.diff`);
|
|
14
|
-
fs.writeFileSync(p, diffText, "utf8");
|
|
15
|
-
return p;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function applyPatchWithGit(repoRoot, patchPath) {
|
|
19
|
-
const r = spawnSync("git", ["apply", "--reject", "--whitespace=fix", patchPath], {
|
|
20
|
-
cwd: repoRoot,
|
|
21
|
-
stdio: "pipe",
|
|
22
|
-
encoding: "utf8"
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return { ok: r.status === 0, stdout: r.stdout, stderr: r.stderr, code: r.status };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function applyUnifiedDiff(repoRoot, diffText) {
|
|
29
|
-
const patchPath = writeTempPatch(repoRoot, diffText);
|
|
30
|
-
|
|
31
|
-
const check = spawnSync("git", ["--version"], { stdio: "ignore" });
|
|
32
|
-
if (check.status !== 0) {
|
|
33
|
-
return { ok: false, error: "git not found; cannot apply unified diff safely" };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const res = applyPatchWithGit(repoRoot, patchPath);
|
|
37
|
-
return res.ok ? { ok: true } : { ok: false, error: res.stderr || "git apply failed", details: res };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
module.exports = { applyUnifiedDiff };
|
|
1
|
+
// bin/runners/lib/patch.js
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { spawnSync } = require("child_process");
|
|
5
|
+
|
|
6
|
+
function ensureDir(p) {
|
|
7
|
+
fs.mkdirSync(p, { recursive: true });
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function writeTempPatch(repoRoot, diffText) {
|
|
11
|
+
const dir = path.join(repoRoot, ".vibecheck", "tmp");
|
|
12
|
+
ensureDir(dir);
|
|
13
|
+
const p = path.join(dir, `patch_${Date.now()}.diff`);
|
|
14
|
+
fs.writeFileSync(p, diffText, "utf8");
|
|
15
|
+
return p;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function applyPatchWithGit(repoRoot, patchPath) {
|
|
19
|
+
const r = spawnSync("git", ["apply", "--reject", "--whitespace=fix", patchPath], {
|
|
20
|
+
cwd: repoRoot,
|
|
21
|
+
stdio: "pipe",
|
|
22
|
+
encoding: "utf8"
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return { ok: r.status === 0, stdout: r.stdout, stderr: r.stderr, code: r.status };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function applyUnifiedDiff(repoRoot, diffText) {
|
|
29
|
+
const patchPath = writeTempPatch(repoRoot, diffText);
|
|
30
|
+
|
|
31
|
+
const check = spawnSync("git", ["--version"], { stdio: "ignore" });
|
|
32
|
+
if (check.status !== 0) {
|
|
33
|
+
return { ok: false, error: "git not found; cannot apply unified diff safely" };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const res = applyPatchWithGit(repoRoot, patchPath);
|
|
37
|
+
return res.ok ? { ok: true } : { ok: false, error: res.stderr || "git apply failed", details: res };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = { applyUnifiedDiff };
|