secufusion-mcp 1.1.0 → 1.2.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/index.js +64 -22
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -2675,8 +2675,13 @@ server.tool("run_pre_pr_checks_with_reviewer_agent", "Unified, single-call PR re
|
|
|
2675
2675
|
skip_checks: z.array(z.enum(["tenant_isolation", "n_plus_one", "missing_index", "kafka_sync", "early_return", "ai_review", "context_review"])).optional().default([]).describe("Checks to skip. Mechanical: tenant_isolation | n_plus_one | missing_index | kafka_sync | early_return. " +
|
|
2676
2676
|
"Review tiers: ai_review (Tier 2) | context_review (Tier 3). " +
|
|
2677
2677
|
"Use sparingly — only for acknowledged legacy files or CI environments where context is unavailable."),
|
|
2678
|
-
|
|
2679
|
-
|
|
2678
|
+
suppressions: z.array(z.object({
|
|
2679
|
+
check: z.enum(["TENANT_ISOLATION", "N_PLUS_ONE", "MISSING_INDEX", "KAFKA_SYNC", "EARLY_RETURN"]),
|
|
2680
|
+
method: z.string().describe("Method name to suppress, e.g. 'countOrphanedByDeviceUserId'"),
|
|
2681
|
+
reason: z.string().describe("Mandatory justification for suppression")
|
|
2682
|
+
})).optional().default([]).describe("Method-scoped suppressions with mandatory reasons.")
|
|
2683
|
+
}, async ({ work_item_id, skip_checks = [], suppressions = [] }) => {
|
|
2684
|
+
const inputChars = JSON.stringify({ work_item_id, skip_checks, suppressions }).length;
|
|
2680
2685
|
const wsRoot = getWorkspaceRoot();
|
|
2681
2686
|
const startTime = Date.now();
|
|
2682
2687
|
// ══════════════════════════════════════════════════════════════════════
|
|
@@ -2806,10 +2811,15 @@ server.tool("run_pre_pr_checks_with_reviewer_agent", "Unified, single-call PR re
|
|
|
2806
2811
|
const dm = line.match(/(?:find|delete|count|exists)\w+By(\w+)/);
|
|
2807
2812
|
if (dm && !dm[1].toLowerCase().includes("tenant")) {
|
|
2808
2813
|
let suppressionReason = "";
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2814
|
+
const explicitSup = suppressions.find(s => s.check === "TENANT_ISOLATION" && (s.method === dm[0] || s.method.endsWith(`.${dm[0]}`)));
|
|
2815
|
+
if (explicitSup)
|
|
2816
|
+
suppressionReason = explicitSup.reason;
|
|
2817
|
+
else {
|
|
2818
|
+
for (let i = Math.max(0, idx - 5); i < idx; i++) {
|
|
2819
|
+
const match = f.lines[i].match(/@TenantScopeException\s*\(\s*"([^"]+)"\s*\)/i);
|
|
2820
|
+
if (match)
|
|
2821
|
+
suppressionReason = match[1];
|
|
2822
|
+
}
|
|
2813
2823
|
}
|
|
2814
2824
|
if (suppressionReason) {
|
|
2815
2825
|
p1Suppressed.push({ file: f.file_path, line: idx + 1, reason: suppressionReason, method: dm[0] });
|
|
@@ -2825,13 +2835,24 @@ server.tool("run_pre_pr_checks_with_reviewer_agent", "Unified, single-call PR re
|
|
|
2825
2835
|
const block = f.lines.slice(ai, ai + 5).join(" ");
|
|
2826
2836
|
if (!/tenantId|tenant_id|:tenantId/i.test(block)) {
|
|
2827
2837
|
let suppressionReason = "";
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2838
|
+
let queryMethodName = "";
|
|
2839
|
+
const methodDeclMatch = block.match(/(?:List|Optional|Page|long|int|boolean|void|[A-Z]\w+)\s+(\w+)\s*\(/);
|
|
2840
|
+
if (methodDeclMatch)
|
|
2841
|
+
queryMethodName = methodDeclMatch[1];
|
|
2842
|
+
if (queryMethodName) {
|
|
2843
|
+
const explicitSup = suppressions.find(s => s.check === "TENANT_ISOLATION" && (s.method === queryMethodName || s.method.endsWith(`.${queryMethodName}`)));
|
|
2844
|
+
if (explicitSup)
|
|
2845
|
+
suppressionReason = explicitSup.reason;
|
|
2846
|
+
}
|
|
2847
|
+
if (!suppressionReason) {
|
|
2848
|
+
for (let i = Math.max(0, ai - 5); i < ai; i++) {
|
|
2849
|
+
const match = f.lines[i].match(/@TenantScopeException\s*\(\s*"([^"]+)"\s*\)/i);
|
|
2850
|
+
if (match)
|
|
2851
|
+
suppressionReason = match[1];
|
|
2852
|
+
}
|
|
2832
2853
|
}
|
|
2833
2854
|
if (suppressionReason) {
|
|
2834
|
-
p1Suppressed.push({ file: f.file_path, line: ai + 1, reason: suppressionReason, method: "@Query method" });
|
|
2855
|
+
p1Suppressed.push({ file: f.file_path, line: ai + 1, reason: suppressionReason, method: queryMethodName || "@Query method" });
|
|
2835
2856
|
}
|
|
2836
2857
|
else {
|
|
2837
2858
|
p1.push({ check: "TENANT_ISOLATION", severity: "BLOCKING", file: f.file_path, line: ai + 1,
|
|
@@ -3480,8 +3501,13 @@ server.tool("run_pre_pr_checks", "Full-spectrum PR review system — runs BEFORE
|
|
|
3480
3501
|
work_item_id: z.string().describe("Active work item ID, e.g. 'WI-1234'."),
|
|
3481
3502
|
skip_checks: z.array(z.enum(["tenant_isolation", "n_plus_one", "missing_index", "kafka_sync", "early_return", "ai_review"])).optional().default([]).describe("Checks to skip. Options: tenant_isolation | n_plus_one | missing_index | kafka_sync | early_return | ai_review. " +
|
|
3482
3503
|
"Use sparingly — only for acknowledged legacy files that pre-date the rule."),
|
|
3483
|
-
|
|
3484
|
-
|
|
3504
|
+
suppressions: z.array(z.object({
|
|
3505
|
+
check: z.enum(["TENANT_ISOLATION", "N_PLUS_ONE", "MISSING_INDEX", "KAFKA_SYNC", "EARLY_RETURN"]),
|
|
3506
|
+
method: z.string().describe("Method name to suppress, e.g. 'countOrphanedByDeviceUserId'"),
|
|
3507
|
+
reason: z.string().describe("Mandatory justification for suppression")
|
|
3508
|
+
})).optional().default([]).describe("Method-scoped suppressions with mandatory reasons.")
|
|
3509
|
+
}, async ({ work_item_id, skip_checks = [], suppressions = [] }) => {
|
|
3510
|
+
const inputChars = JSON.stringify({ work_item_id, skip_checks, suppressions }).length;
|
|
3485
3511
|
const wsRoot = getWorkspaceRoot();
|
|
3486
3512
|
// ── Resolve task folder ────────────────────────────────────────────────
|
|
3487
3513
|
const registry = readRegistry();
|
|
@@ -3559,10 +3585,15 @@ server.tool("run_pre_pr_checks", "Full-spectrum PR review system — runs BEFORE
|
|
|
3559
3585
|
const byClause = derivedMatch[1].toLowerCase();
|
|
3560
3586
|
if (!byClause.includes("tenantid") && !byClause.includes("tenant")) {
|
|
3561
3587
|
let suppressionReason = "";
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3588
|
+
const explicitSup = suppressions.find(s => s.check === "TENANT_ISOLATION" && (s.method === derivedMatch[0] || s.method.endsWith(`.${derivedMatch[0]}`)));
|
|
3589
|
+
if (explicitSup)
|
|
3590
|
+
suppressionReason = explicitSup.reason;
|
|
3591
|
+
else {
|
|
3592
|
+
for (let i = Math.max(0, idx - 5); i < idx; i++) {
|
|
3593
|
+
const match = f.lines[i].match(/@TenantScopeException\s*\(\s*"([^"]+)"\s*\)/i);
|
|
3594
|
+
if (match)
|
|
3595
|
+
suppressionReason = match[1];
|
|
3596
|
+
}
|
|
3566
3597
|
}
|
|
3567
3598
|
if (suppressionReason) {
|
|
3568
3599
|
p1Suppressed.push({ file: f.file_path, line: idx + 1, reason: suppressionReason, method: derivedMatch[0] });
|
|
@@ -3586,13 +3617,24 @@ server.tool("run_pre_pr_checks", "Full-spectrum PR review system — runs BEFORE
|
|
|
3586
3617
|
const queryBlock = f.lines.slice(annotIdx, annotIdx + 5).join(" ");
|
|
3587
3618
|
if (!/tenantId|tenant_id|:tenantId/i.test(queryBlock)) {
|
|
3588
3619
|
let suppressionReason = "";
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3620
|
+
let queryMethodName = "";
|
|
3621
|
+
const methodDeclMatch = queryBlock.match(/(?:List|Optional|Page|long|int|boolean|void|[A-Z]\w+)\s+(\w+)\s*\(/);
|
|
3622
|
+
if (methodDeclMatch)
|
|
3623
|
+
queryMethodName = methodDeclMatch[1];
|
|
3624
|
+
if (queryMethodName) {
|
|
3625
|
+
const explicitSup = suppressions.find(s => s.check === "TENANT_ISOLATION" && (s.method === queryMethodName || s.method.endsWith(`.${queryMethodName}`)));
|
|
3626
|
+
if (explicitSup)
|
|
3627
|
+
suppressionReason = explicitSup.reason;
|
|
3628
|
+
}
|
|
3629
|
+
if (!suppressionReason) {
|
|
3630
|
+
for (let i = Math.max(0, annotIdx - 5); i < annotIdx; i++) {
|
|
3631
|
+
const match = f.lines[i].match(/@TenantScopeException\s*\(\s*"([^"]+)"\s*\)/i);
|
|
3632
|
+
if (match)
|
|
3633
|
+
suppressionReason = match[1];
|
|
3634
|
+
}
|
|
3593
3635
|
}
|
|
3594
3636
|
if (suppressionReason) {
|
|
3595
|
-
p1Suppressed.push({ file: f.file_path, line: annotIdx + 1, reason: suppressionReason, method: "@Query method" });
|
|
3637
|
+
p1Suppressed.push({ file: f.file_path, line: annotIdx + 1, reason: suppressionReason, method: queryMethodName || "@Query method" });
|
|
3596
3638
|
}
|
|
3597
3639
|
else {
|
|
3598
3640
|
p1Findings.push({
|