brakit 0.9.2 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +148 -5
- package/dist/api.js +232 -54
- package/dist/bin/brakit.js +228 -35
- package/dist/dashboard-client.global.js +742 -385
- package/dist/dashboard.html +933 -432
- package/dist/mcp/server.js +99 -21
- package/dist/runtime/index.js +1551 -430
- package/package.json +1 -1
package/dist/bin/brakit.js
CHANGED
|
@@ -73,7 +73,7 @@ var init_type_guards = __esm({
|
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
// src/constants/labels.ts
|
|
76
|
-
var DASHBOARD_PREFIX, DASHBOARD_API_REQUESTS, DASHBOARD_API_EVENTS, DASHBOARD_API_FLOWS, DASHBOARD_API_CLEAR, DASHBOARD_API_LOGS, DASHBOARD_API_FETCHES, DASHBOARD_API_ERRORS, DASHBOARD_API_QUERIES, DASHBOARD_API_INGEST, DASHBOARD_API_METRICS, DASHBOARD_API_ACTIVITY, DASHBOARD_API_METRICS_LIVE, DASHBOARD_API_INSIGHTS, DASHBOARD_API_SECURITY, DASHBOARD_API_TAB, DASHBOARD_API_FINDINGS, DASHBOARD_API_FINDINGS_REPORT, VALID_TABS_TUPLE, VALID_TABS, POSTHOG_HOST, POSTHOG_CAPTURE_PATH, POSTHOG_REQUEST_TIMEOUT_MS;
|
|
76
|
+
var DASHBOARD_PREFIX, DASHBOARD_API_REQUESTS, DASHBOARD_API_EVENTS, DASHBOARD_API_FLOWS, DASHBOARD_API_CLEAR, DASHBOARD_API_LOGS, DASHBOARD_API_FETCHES, DASHBOARD_API_ERRORS, DASHBOARD_API_QUERIES, DASHBOARD_API_INGEST, DASHBOARD_API_METRICS, DASHBOARD_API_ACTIVITY, DASHBOARD_API_METRICS_LIVE, DASHBOARD_API_INSIGHTS, DASHBOARD_API_SECURITY, DASHBOARD_API_TAB, DASHBOARD_API_FINDINGS, DASHBOARD_API_FINDINGS_REPORT, DASHBOARD_API_GRAPH, VALID_TABS_TUPLE, VALID_TABS, POSTHOG_HOST, POSTHOG_CAPTURE_PATH, POSTHOG_REQUEST_TIMEOUT_MS;
|
|
77
77
|
var init_labels = __esm({
|
|
78
78
|
"src/constants/labels.ts"() {
|
|
79
79
|
"use strict";
|
|
@@ -95,16 +95,14 @@ var init_labels = __esm({
|
|
|
95
95
|
DASHBOARD_API_TAB = `${DASHBOARD_PREFIX}/api/tab`;
|
|
96
96
|
DASHBOARD_API_FINDINGS = `${DASHBOARD_PREFIX}/api/findings`;
|
|
97
97
|
DASHBOARD_API_FINDINGS_REPORT = `${DASHBOARD_PREFIX}/api/findings/report`;
|
|
98
|
+
DASHBOARD_API_GRAPH = `${DASHBOARD_PREFIX}/api/graph`;
|
|
98
99
|
VALID_TABS_TUPLE = [
|
|
99
100
|
"overview",
|
|
100
101
|
"actions",
|
|
101
|
-
"
|
|
102
|
-
"fetches",
|
|
103
|
-
"queries",
|
|
104
|
-
"errors",
|
|
105
|
-
"logs",
|
|
102
|
+
"insights",
|
|
106
103
|
"performance",
|
|
107
|
-
"
|
|
104
|
+
"graph",
|
|
105
|
+
"explorer"
|
|
108
106
|
];
|
|
109
107
|
VALID_TABS = new Set(VALID_TABS_TUPLE);
|
|
110
108
|
POSTHOG_HOST = "https://us.i.posthog.com";
|
|
@@ -138,7 +136,7 @@ var init_features = __esm({
|
|
|
138
136
|
MAX_TIMELINE_EVENTS = 20;
|
|
139
137
|
MAX_RESOLVED_DISPLAY = 5;
|
|
140
138
|
ENRICHMENT_SEVERITY_FILTER = ["critical", "warning"];
|
|
141
|
-
MCP_SERVER_VERSION = "0.
|
|
139
|
+
MCP_SERVER_VERSION = "0.10.1";
|
|
142
140
|
RECOVERY_WINDOW_MS = 5 * 60 * 1e3;
|
|
143
141
|
PORT_MIN = 1;
|
|
144
142
|
PORT_MAX = 65535;
|
|
@@ -364,10 +362,27 @@ async function enrichFindings(client) {
|
|
|
364
362
|
if (reqData.requests.length > 0) {
|
|
365
363
|
const req = reqData.requests[0];
|
|
366
364
|
if (req.id) {
|
|
367
|
-
const activity = await
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
365
|
+
const [activity, queries, fetches] = await Promise.all([
|
|
366
|
+
client.getActivity(req.id),
|
|
367
|
+
client.getQueries(req.id),
|
|
368
|
+
client.getFetches(req.id)
|
|
369
|
+
]);
|
|
370
|
+
const lines = [`Request took ${req.durationMs}ms.`];
|
|
371
|
+
if (queries.entries.length > 0) {
|
|
372
|
+
lines.push(`DB Queries (${queries.entries.length}):`);
|
|
373
|
+
for (const q of queries.entries.slice(0, 5)) {
|
|
374
|
+
const sql = q.sql ?? `${q.operation ?? ""} ${q.table ?? q.model ?? ""}`;
|
|
375
|
+
lines.push(` [${q.durationMs}ms] ${sql}`);
|
|
376
|
+
}
|
|
377
|
+
if (queries.entries.length > 5) lines.push(` ... and ${queries.entries.length - 5} more`);
|
|
378
|
+
}
|
|
379
|
+
if (fetches.entries.length > 0) {
|
|
380
|
+
lines.push(`Fetches (${fetches.entries.length}):`);
|
|
381
|
+
for (const f of fetches.entries.slice(0, 3)) {
|
|
382
|
+
lines.push(` [${f.durationMs}ms] ${f.method} ${f.url} \u2192 ${f.statusCode}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return lines.join("\n");
|
|
371
386
|
}
|
|
372
387
|
}
|
|
373
388
|
} catch {
|
|
@@ -486,6 +501,9 @@ var init_get_findings = __esm({
|
|
|
486
501
|
return { content: [{ type: "text", text: `Invalid state "${state}". Use: open, fixing, resolved, stale, regressed.` }], isError: true };
|
|
487
502
|
}
|
|
488
503
|
let findings = await enrichFindings(client);
|
|
504
|
+
if (!state) {
|
|
505
|
+
findings = findings.filter((f) => f.aiStatus !== "wont_fix");
|
|
506
|
+
}
|
|
489
507
|
if (severity) {
|
|
490
508
|
findings = findings.filter((f) => f.severity === severity);
|
|
491
509
|
}
|
|
@@ -497,21 +515,25 @@ var init_get_findings = __esm({
|
|
|
497
515
|
if (findings.length === 0) {
|
|
498
516
|
return { content: [{ type: "text", text: "No findings detected. The application looks healthy." }] };
|
|
499
517
|
}
|
|
500
|
-
const lines = [
|
|
501
|
-
`
|
|
518
|
+
const lines = [
|
|
519
|
+
`Found ${findings.length} issue(s). Full context included below \u2014 no need to call get_request_detail separately.`,
|
|
520
|
+
`After fixing, call report_fixes ONCE with all results.
|
|
521
|
+
`
|
|
522
|
+
];
|
|
502
523
|
for (const f of findings) {
|
|
503
524
|
lines.push(`[${f.severity.toUpperCase()}] ${f.title}`);
|
|
504
525
|
lines.push(` ID: ${f.findingId}`);
|
|
505
526
|
lines.push(` Endpoint: ${f.endpoint}`);
|
|
506
527
|
lines.push(` Issue: ${f.description}`);
|
|
507
|
-
if (f.context)
|
|
528
|
+
if (f.context) {
|
|
529
|
+
for (const ctxLine of f.context.split("\n")) {
|
|
530
|
+
lines.push(` ${ctxLine}`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
508
533
|
lines.push(` Fix: ${f.hint}`);
|
|
509
534
|
if (f.aiStatus === "fixed") {
|
|
510
535
|
lines.push(` AI Status: fixed (awaiting verification)`);
|
|
511
536
|
if (f.aiNotes) lines.push(` AI Notes: ${f.aiNotes}`);
|
|
512
|
-
} else if (f.aiStatus === "wont_fix") {
|
|
513
|
-
lines.push(` AI Status: won't fix`);
|
|
514
|
-
if (f.aiNotes) lines.push(` AI Notes: ${f.aiNotes}`);
|
|
515
537
|
}
|
|
516
538
|
lines.push("");
|
|
517
539
|
}
|
|
@@ -899,6 +921,69 @@ var init_report_fix = __esm({
|
|
|
899
921
|
}
|
|
900
922
|
});
|
|
901
923
|
|
|
924
|
+
// src/mcp/tools/report-fixes.ts
|
|
925
|
+
var reportFixes;
|
|
926
|
+
var init_report_fixes = __esm({
|
|
927
|
+
"src/mcp/tools/report-fixes.ts"() {
|
|
928
|
+
"use strict";
|
|
929
|
+
init_type_guards();
|
|
930
|
+
reportFixes = {
|
|
931
|
+
name: "report_fixes",
|
|
932
|
+
description: "Report results for multiple findings in a single call. Use this instead of calling report_fix repeatedly \u2014 it's faster and requires only one confirmation. Pass a JSON array string where each item has finding_id, status ('fixed' or 'wont_fix'), and summary.",
|
|
933
|
+
inputSchema: {
|
|
934
|
+
type: "object",
|
|
935
|
+
properties: {
|
|
936
|
+
fixes: {
|
|
937
|
+
type: "string",
|
|
938
|
+
description: 'JSON array of fix reports. Example: [{"finding_id":"abc123","status":"fixed","summary":"Added input validation"}]'
|
|
939
|
+
}
|
|
940
|
+
},
|
|
941
|
+
required: ["fixes"]
|
|
942
|
+
},
|
|
943
|
+
async handler(client, args) {
|
|
944
|
+
let fixes;
|
|
945
|
+
try {
|
|
946
|
+
const raw = typeof args.fixes === "string" ? JSON.parse(args.fixes) : args.fixes;
|
|
947
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
948
|
+
return { content: [{ type: "text", text: "fixes must be a non-empty JSON array." }], isError: true };
|
|
949
|
+
}
|
|
950
|
+
fixes = raw.filter(
|
|
951
|
+
(item) => typeof item === "object" && item !== null && typeof item.finding_id === "string" && typeof item.status === "string" && typeof item.summary === "string"
|
|
952
|
+
);
|
|
953
|
+
if (fixes.length === 0) {
|
|
954
|
+
return { content: [{ type: "text", text: "No valid fix entries found. Each entry needs finding_id, status, and summary." }], isError: true };
|
|
955
|
+
}
|
|
956
|
+
} catch {
|
|
957
|
+
return { content: [{ type: "text", text: "fixes must be valid JSON." }], isError: true };
|
|
958
|
+
}
|
|
959
|
+
const results = [];
|
|
960
|
+
let errors = 0;
|
|
961
|
+
for (const fix of fixes) {
|
|
962
|
+
if (!fix.finding_id || !isValidAiFixStatus(fix.status) || !fix.summary) {
|
|
963
|
+
results.push(`\u2717 Invalid entry: ${fix.finding_id || "missing ID"}`);
|
|
964
|
+
errors++;
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
const ok = await client.reportFix(fix.finding_id, fix.status, fix.summary);
|
|
968
|
+
if (ok) {
|
|
969
|
+
const label = fix.status === "fixed" ? "fixed" : "won't fix";
|
|
970
|
+
results.push(`\u2713 ${fix.finding_id} \u2192 ${label}`);
|
|
971
|
+
} else {
|
|
972
|
+
results.push(`\u2717 ${fix.finding_id} \u2192 not found`);
|
|
973
|
+
errors++;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
const errorSuffix = errors > 0 ? ` (${errors} error${errors !== 1 ? "s" : ""})` : "";
|
|
977
|
+
const summary = `Processed ${fixes.length} finding(s)${errorSuffix}. Dashboard updated.`;
|
|
978
|
+
return {
|
|
979
|
+
content: [{ type: "text", text: summary + "\n\n" + results.join("\n") }],
|
|
980
|
+
...errors > 0 ? { isError: true } : {}
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
});
|
|
986
|
+
|
|
902
987
|
// src/mcp/tools/index.ts
|
|
903
988
|
function getToolDefinitions() {
|
|
904
989
|
return [...TOOL_MAP.values()].map((t) => ({
|
|
@@ -928,8 +1013,9 @@ var init_tools = __esm({
|
|
|
928
1013
|
init_get_report();
|
|
929
1014
|
init_clear_findings();
|
|
930
1015
|
init_report_fix();
|
|
1016
|
+
init_report_fixes();
|
|
931
1017
|
TOOL_MAP = new Map(
|
|
932
|
-
[getFindings, getEndpoints, getRequestDetail, verifyFix, getReport, clearFindings, reportFix].map((t) => [t.name, t])
|
|
1018
|
+
[getFindings, getEndpoints, getRequestDetail, verifyFix, getReport, clearFindings, reportFix, reportFixes].map((t) => [t.name, t])
|
|
933
1019
|
);
|
|
934
1020
|
}
|
|
935
1021
|
});
|
|
@@ -939,7 +1025,7 @@ var SERVER_INSTRUCTIONS, PROMPTS, PROMPT_MESSAGES;
|
|
|
939
1025
|
var init_prompts = __esm({
|
|
940
1026
|
"src/mcp/prompts.ts"() {
|
|
941
1027
|
"use strict";
|
|
942
|
-
SERVER_INSTRUCTIONS = "Brakit is a dev tool that monitors your running app for security vulnerabilities, performance issues, and query problems. IMPORTANT: After fixing
|
|
1028
|
+
SERVER_INSTRUCTIONS = "Brakit is a dev tool that monitors your running app for security vulnerabilities, performance issues, and query problems. IMPORTANT: After fixing brakit findings, call report_fixes (batch) with all results at once instead of calling report_fix individually. This is faster and requires only one confirmation.";
|
|
943
1029
|
PROMPTS = [
|
|
944
1030
|
{
|
|
945
1031
|
name: "check-app",
|
|
@@ -951,8 +1037,8 @@ var init_prompts = __esm({
|
|
|
951
1037
|
}
|
|
952
1038
|
];
|
|
953
1039
|
PROMPT_MESSAGES = {
|
|
954
|
-
"check-app": "Check my running app for security and performance issues using brakit. First get all findings, then get the endpoint summary. For any critical or warning findings, get the request detail to understand the root cause. Give me a clear report of what's wrong and offer to fix each issue. After fixing
|
|
955
|
-
"fix-findings": "Get all open brakit findings. For each finding:\n1. Get the request detail to understand the exact issue\n2. Find the source code responsible and fix it\n3.
|
|
1040
|
+
"check-app": "Check my running app for security and performance issues using brakit. First get all findings, then get the endpoint summary. For any critical or warning findings, get the request detail to understand the root cause. Give me a clear report of what's wrong and offer to fix each issue. After fixing issues, call report_fixes once with all results.",
|
|
1041
|
+
"fix-findings": "Get all open brakit findings. For each finding:\n1. Get the request detail to understand the exact issue\n2. Find the source code responsible and fix it\n3. Track the finding_id, status ('fixed' or 'wont_fix'), and a brief summary\n\nAfter processing ALL findings, call report_fixes ONCE with the full array of results. Do not call report_fix individually for each finding.\n\nAfter reporting, ask me to re-trigger the endpoints so brakit can verify the fixes."
|
|
956
1042
|
};
|
|
957
1043
|
}
|
|
958
1044
|
});
|
|
@@ -1121,11 +1207,22 @@ import { readFile as readFile3, readdir } from "fs/promises";
|
|
|
1121
1207
|
import { existsSync as existsSync4 } from "fs";
|
|
1122
1208
|
import { join as join2, relative } from "path";
|
|
1123
1209
|
var FRAMEWORKS = [
|
|
1210
|
+
// Meta-frameworks first (they bundle Express/Vite internally)
|
|
1124
1211
|
{ name: "nextjs", dep: "next", devCmd: "next dev", bin: "next", defaultPort: 3e3, devArgs: ["dev", "--port"] },
|
|
1125
1212
|
{ name: "remix", dep: "@remix-run/dev", devCmd: "remix dev", bin: "remix", defaultPort: 3e3, devArgs: ["dev"] },
|
|
1126
1213
|
{ name: "nuxt", dep: "nuxt", devCmd: "nuxt dev", bin: "nuxt", defaultPort: 3e3, devArgs: ["dev", "--port"] },
|
|
1127
|
-
{ name: "
|
|
1128
|
-
{ name: "
|
|
1214
|
+
{ name: "astro", dep: "astro", devCmd: "astro dev", bin: "astro", defaultPort: 4321, devArgs: ["dev", "--port"] },
|
|
1215
|
+
{ name: "nestjs", dep: "@nestjs/core", devCmd: "nest start", bin: "nest", defaultPort: 3e3, devArgs: ["--watch"] },
|
|
1216
|
+
{ name: "adonis", dep: "@adonisjs/core", devCmd: "node ace serve", bin: "ace", defaultPort: 3333, devArgs: ["serve", "--watch"] },
|
|
1217
|
+
{ name: "sails", dep: "sails", devCmd: "sails lift", bin: "sails", defaultPort: 1337, devArgs: ["lift"] },
|
|
1218
|
+
// Server frameworks
|
|
1219
|
+
{ name: "hono", dep: "hono", devCmd: "node", bin: "node", defaultPort: 3e3 },
|
|
1220
|
+
{ name: "fastify", dep: "fastify", devCmd: "node", bin: "node", defaultPort: 3e3 },
|
|
1221
|
+
{ name: "koa", dep: "koa", devCmd: "node", bin: "node", defaultPort: 3e3 },
|
|
1222
|
+
{ name: "hapi", dep: "@hapi/hapi", devCmd: "node", bin: "node", defaultPort: 3e3 },
|
|
1223
|
+
{ name: "express", dep: "express", devCmd: "node", bin: "node", defaultPort: 3e3 },
|
|
1224
|
+
// Bundlers (last — likely used alongside a framework above)
|
|
1225
|
+
{ name: "vite", dep: "vite", devCmd: "vite", bin: "vite", defaultPort: 5173, devArgs: ["--port"] }
|
|
1129
1226
|
];
|
|
1130
1227
|
async function detectProject(rootDir) {
|
|
1131
1228
|
const pkgPath = join2(rootDir, "package.json");
|
|
@@ -1207,7 +1304,8 @@ async function detectPythonFramework(rootDir, hasPyproject, hasRequirements) {
|
|
|
1207
1304
|
const content = await readFile3(join2(rootDir, "requirements.txt"), "utf-8");
|
|
1208
1305
|
const lines = content.toLowerCase().split("\n");
|
|
1209
1306
|
for (const [dep, fw] of Object.entries(PYTHON_FRAMEWORK_MAP)) {
|
|
1210
|
-
|
|
1307
|
+
const versionChars = /* @__PURE__ */ new Set(["=", "<", ">", "~", "!", "["]);
|
|
1308
|
+
if (lines.some((l) => l.startsWith(dep) && (l.length === dep.length || versionChars.has(l[dep.length])))) {
|
|
1211
1309
|
return fw;
|
|
1212
1310
|
}
|
|
1213
1311
|
}
|
|
@@ -1313,20 +1411,115 @@ init_log();
|
|
|
1313
1411
|
init_type_guards();
|
|
1314
1412
|
|
|
1315
1413
|
// src/analysis/rules/patterns.ts
|
|
1316
|
-
var
|
|
1317
|
-
|
|
1318
|
-
|
|
1414
|
+
var SECRET_KEY_SET = /* @__PURE__ */ new Set([
|
|
1415
|
+
"password",
|
|
1416
|
+
"passwd",
|
|
1417
|
+
"secret",
|
|
1418
|
+
"api_key",
|
|
1419
|
+
"apiKey",
|
|
1420
|
+
"api_secret",
|
|
1421
|
+
"apiSecret",
|
|
1422
|
+
"private_key",
|
|
1423
|
+
"privateKey",
|
|
1424
|
+
"client_secret",
|
|
1425
|
+
"clientSecret"
|
|
1426
|
+
]);
|
|
1427
|
+
var SECRET_KEYS = { test: (s) => SECRET_KEY_SET.has(s) };
|
|
1428
|
+
var TOKEN_PARAM_SET = /* @__PURE__ */ new Set([
|
|
1429
|
+
"token",
|
|
1430
|
+
"api_key",
|
|
1431
|
+
"apiKey",
|
|
1432
|
+
"secret",
|
|
1433
|
+
"password",
|
|
1434
|
+
"access_token",
|
|
1435
|
+
"session_id",
|
|
1436
|
+
"sessionId"
|
|
1437
|
+
]);
|
|
1438
|
+
var TOKEN_PARAMS = { test: (s) => TOKEN_PARAM_SET.has(s) };
|
|
1439
|
+
var SAFE_PARAM_SET = /* @__PURE__ */ new Set([
|
|
1440
|
+
"_rsc",
|
|
1441
|
+
"__clerk_handshake",
|
|
1442
|
+
"__clerk_db_jwt",
|
|
1443
|
+
"callback",
|
|
1444
|
+
"code",
|
|
1445
|
+
"state",
|
|
1446
|
+
"nonce",
|
|
1447
|
+
"redirect_uri",
|
|
1448
|
+
"utm_",
|
|
1449
|
+
"fbclid",
|
|
1450
|
+
"gclid"
|
|
1451
|
+
]);
|
|
1452
|
+
var SAFE_PARAMS = { test: (s) => SAFE_PARAM_SET.has(s) };
|
|
1453
|
+
var INTERNAL_ID_KEY_SET = /* @__PURE__ */ new Set([
|
|
1454
|
+
"id",
|
|
1455
|
+
"_id",
|
|
1456
|
+
"userId",
|
|
1457
|
+
"user_id",
|
|
1458
|
+
"createdBy",
|
|
1459
|
+
"updatedBy",
|
|
1460
|
+
"organizationId",
|
|
1461
|
+
"org_id",
|
|
1462
|
+
"tenantId",
|
|
1463
|
+
"tenant_id"
|
|
1464
|
+
]);
|
|
1465
|
+
var INTERNAL_ID_KEYS = { test: (s) => INTERNAL_ID_KEY_SET.has(s) };
|
|
1466
|
+
var INTERNAL_ID_SUFFIX = {
|
|
1467
|
+
test: (s) => s.endsWith("Id") || s.endsWith("_id")
|
|
1468
|
+
};
|
|
1469
|
+
var SENSITIVE_FIELD_SET = /* @__PURE__ */ new Set([
|
|
1470
|
+
"phone",
|
|
1471
|
+
"phonenumber",
|
|
1472
|
+
"phone_number",
|
|
1473
|
+
"ssn",
|
|
1474
|
+
"socialsecuritynumber",
|
|
1475
|
+
"social_security_number",
|
|
1476
|
+
"dateofbirth",
|
|
1477
|
+
"date_of_birth",
|
|
1478
|
+
"dob",
|
|
1479
|
+
"address",
|
|
1480
|
+
"streetaddress",
|
|
1481
|
+
"street_address",
|
|
1482
|
+
"creditcard",
|
|
1483
|
+
"credit_card",
|
|
1484
|
+
"cardnumber",
|
|
1485
|
+
"card_number",
|
|
1486
|
+
"bankaccount",
|
|
1487
|
+
"bank_account",
|
|
1488
|
+
"passport",
|
|
1489
|
+
"passportnumber",
|
|
1490
|
+
"passport_number",
|
|
1491
|
+
"nationalid",
|
|
1492
|
+
"national_id"
|
|
1493
|
+
]);
|
|
1494
|
+
var SENSITIVE_FIELD_NAMES = {
|
|
1495
|
+
test: (s) => SENSITIVE_FIELD_SET.has(s.toLowerCase())
|
|
1496
|
+
};
|
|
1497
|
+
var SELF_SERVICE_SEGMENTS = /* @__PURE__ */ new Set(["me", "account", "profile", "settings", "self"]);
|
|
1498
|
+
var SELF_SERVICE_PATH = {
|
|
1499
|
+
test: (path) => {
|
|
1500
|
+
const segments = path.toLowerCase().split(/[/?#]/);
|
|
1501
|
+
return segments.some((seg) => SELF_SERVICE_SEGMENTS.has(seg));
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
var MASKED_LITERALS = ["[REDACTED]", "[FILTERED]", "CHANGE_ME"];
|
|
1505
|
+
var MASKED_RE = {
|
|
1506
|
+
test: (s) => {
|
|
1507
|
+
const upper = s.toUpperCase();
|
|
1508
|
+
if (MASKED_LITERALS.some((m) => upper.includes(m))) return true;
|
|
1509
|
+
if (s.length > 0 && s.split("").every((c) => c === "*")) return true;
|
|
1510
|
+
if (s.length >= 3 && s.split("").every((c) => c === "x" || c === "X")) return true;
|
|
1511
|
+
return false;
|
|
1512
|
+
}
|
|
1513
|
+
};
|
|
1514
|
+
var DB_PROTOCOLS = ["postgres://", "mysql://", "mongodb://", "redis://"];
|
|
1515
|
+
var DB_CONN_RE = {
|
|
1516
|
+
test: (s) => DB_PROTOCOLS.some((p) => s.includes(p))
|
|
1517
|
+
};
|
|
1319
1518
|
var STACK_TRACE_RE = /at\s+.+\(.+:\d+:\d+\)|at\s+Module\._compile|at\s+Object\.<anonymous>|at\s+processTicksAndRejections|Traceback \(most recent call last\)|File ".+", line \d+/;
|
|
1320
|
-
var DB_CONN_RE = /(postgres|mysql|mongodb|redis):\/\//;
|
|
1321
1519
|
var SQL_FRAGMENT_RE = /\b(SELECT\s+[\w.*]+\s+FROM|INSERT\s+INTO|UPDATE\s+\w+\s+SET|DELETE\s+FROM)\b/i;
|
|
1322
1520
|
var SECRET_VAL_RE = /(api_key|apiKey|secret|token)\s*[:=]\s*["']?[A-Za-z0-9_\-.+/]{8,}/;
|
|
1323
1521
|
var LOG_SECRET_RE = /(password|secret|token|api_key|apiKey)\s*[:=]\s*["']?[A-Za-z0-9_\-.+/]{8,}/i;
|
|
1324
|
-
var MASKED_RE = /^\*+$|\[REDACTED\]|\[FILTERED\]|CHANGE_ME|^x{3,}$/i;
|
|
1325
1522
|
var EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
|
|
1326
|
-
var INTERNAL_ID_KEYS = /^(id|_id|userId|user_id|createdBy|updatedBy|organizationId|org_id|tenantId|tenant_id)$/;
|
|
1327
|
-
var INTERNAL_ID_SUFFIX = /Id$|_id$/;
|
|
1328
|
-
var SELF_SERVICE_PATH = /\/(?:me|account|profile|settings|self)(?=\/|\?|#|$)/i;
|
|
1329
|
-
var SENSITIVE_FIELD_NAMES = /^(phone|phoneNumber|phone_number|ssn|socialSecurityNumber|social_security_number|dateOfBirth|date_of_birth|dob|address|streetAddress|street_address|creditCard|credit_card|cardNumber|card_number|bankAccount|bank_account|passport|passportNumber|passport_number|nationalId|national_id)$/i;
|
|
1330
1523
|
var RULE_HINTS = {
|
|
1331
1524
|
"exposed-secret": "Never include secret fields in API responses. Strip sensitive fields before returning.",
|
|
1332
1525
|
"token-in-url": "Pass tokens in the Authorization header, not URL query parameters.",
|
|
@@ -1812,7 +2005,7 @@ init_constants();
|
|
|
1812
2005
|
init_endpoint();
|
|
1813
2006
|
|
|
1814
2007
|
// src/index.ts
|
|
1815
|
-
var VERSION = "0.
|
|
2008
|
+
var VERSION = "0.10.1";
|
|
1816
2009
|
|
|
1817
2010
|
// src/cli/commands/install.ts
|
|
1818
2011
|
init_constants();
|