secufusion-mcp 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/index.js +45 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -228,6 +228,7 @@ This writes to `.rejected-patterns.json`:
|
|
|
228
228
|
| **SPEC** | `.current-task-spec.md` is missing or has unchecked `- [ ]` boxes |
|
|
229
229
|
| **LINTING** | AST linters (ESLint, Checkstyle) fail in any discovered microservice. Fix natively, do not suppress! (Falls back to regex if no linters exist) |
|
|
230
230
|
| **SECURITY** | Hardcoded IPs or `uat.*` / `prod.*` / `staging.*` URLs in source or config files |
|
|
231
|
+
| **TENANT ISOLATION** | `*Repository.java` files contain query methods or `@Query` annotations that do NOT include `tenant` filtering |
|
|
231
232
|
| **FLYWAY** | `@Entity`-annotated Java files exist but no `V*__.sql` Flyway migrations found |
|
|
232
233
|
|
|
233
234
|
**Example — Run checks before PR:**
|
|
@@ -517,7 +518,7 @@ Timestamp: 2026-08-26T16:00:00.000Z
|
|
|
517
518
|
## PR Summary
|
|
518
519
|
- Work Item: #2847
|
|
519
520
|
- Spec: All acceptance criteria verified ✅
|
|
520
|
-
- Guardrails:
|
|
521
|
+
- Guardrails: tenant isolation secured, no debug logs, no hardcoded URLs, Flyway covered ✅
|
|
521
522
|
- Ready to raise PR 🚀
|
|
522
523
|
|
|
523
524
|
🚫 Rejected Patterns Reminder (1 on record)
|
|
@@ -585,7 +586,7 @@ You are an elite Senior Developer and Architect working on the SecuFusion worksp
|
|
|
585
586
|
|
|
586
587
|
## Phase 1 — Planning (TRIGGER: user assigns a task or work item)
|
|
587
588
|
- Do NOT write code immediately. First, call `manage_feature_spec`.
|
|
588
|
-
- Determine which microservices are likely affected. Pass a `reference_file_path` to observe exact coding patterns.
|
|
589
|
+
- Determine which microservices are likely affected. Pass a `reference_file_path` from each to observe exact coding patterns.
|
|
589
590
|
- Pass the user's requirements into `task_description` to generate the workspace-level `.current-task-spec.md` blueprint.
|
|
590
591
|
- Wait for the spec to be generated before writing any code.
|
|
591
592
|
|
|
@@ -600,11 +601,11 @@ You are an elite Senior Developer and Architect working on the SecuFusion worksp
|
|
|
600
601
|
- Always check `.rejected-patterns.json` implicitly before suggesting architectural choices to ensure you never repeat past mistakes.
|
|
601
602
|
|
|
602
603
|
## Phase 4 — PR Handoff (TRIGGER: user says "prepare PR", "finish up", or "run checks")
|
|
603
|
-
- Call `run_pre_pr_checks` with the Azure DevOps `work_item_id`. The tool will automatically discover all modified microservices in the workspace and run
|
|
604
|
-
- If the tool throws an error for a specific repository (e.g., missing Flyway SQL migration,
|
|
604
|
+
- Call `run_pre_pr_checks` with the Azure DevOps `work_item_id`. The tool will automatically discover all modified microservices in the workspace and run native linters, database script checks, and strict tenant-isolation scanners.
|
|
605
|
+
- If the tool throws an error for a specific repository (e.g., missing Flyway SQL migration, missing `tenantId` in a query, or a linter failing), YOU MUST navigate to that specific microservice, FIX THE ERROR in the codebase natively, and run the tool again until the entire workspace passes. Do not suppress warnings.
|
|
605
606
|
|
|
606
607
|
## Guardrails (enforce always, no exceptions)
|
|
607
|
-
-
|
|
608
|
+
- TENANT SAFETY IS AUTOMATED: The PR Gatekeeper actively scans all `*Repository.java` files. If you write a database query (derived method or `@Query`) that does not explicitly filter by `tenantId` or contain the word `tenant`, the PR will be blocked. Write secure, tenant-isolated queries on your first attempt.
|
|
608
609
|
- Do not ignore linter errors. AST-level tools (ESLint, Checkstyle/Maven) are the source of truth for hygiene. Fix them natively.
|
|
609
610
|
- Never hardcode UAT/Prod IPs or URLs. Use environment variables or configuration properties.
|
|
610
611
|
- If you modify a JPA `@Entity` in any backend repo, you MUST create the corresponding Flyway `.sql` migration script before running PR checks.
|
package/index.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - run_pre_pr_checks : gate PRs via AST-level linters (ESLint / Maven Checkstyle) + structural checks
|
|
9
9
|
*
|
|
10
10
|
* Guardrails enforced:
|
|
11
|
-
* 1.
|
|
11
|
+
* 1. TENANT SAFETY AUTOMATED: Active scanning of *Repository.java for tenantId scoping.
|
|
12
12
|
* 2. Code hygiene (console.log, unused vars, formatting) enforced via ESLint / Checkstyle — not regex.
|
|
13
13
|
* 3. No hardcoded UAT/Prod IPs or environment URLs.
|
|
14
14
|
* 4. Every modified JPA @Entity must have a matching Flyway SQL migration.
|
|
@@ -246,6 +246,31 @@ function findProjectRoots(dir, depth = 0) {
|
|
|
246
246
|
}
|
|
247
247
|
return [...new Set(roots)];
|
|
248
248
|
}
|
|
249
|
+
// ── Automated Tenant Isolation Scanner ────────────────────────────────────────
|
|
250
|
+
function checkTenantIsolation(rootDir) {
|
|
251
|
+
const violations = [];
|
|
252
|
+
const files = walkDir(rootDir, [".java"]).filter(f => f.endsWith("Repository.java"));
|
|
253
|
+
const queryMethodRegex = /\b(?:find|get|read|query|search|stream|count|exists|delete|remove)(?:All)?By[A-Z0-9]/;
|
|
254
|
+
const atQueryRegex = /@Query\s*\(/;
|
|
255
|
+
for (const file of files) {
|
|
256
|
+
const content = readFileSafe(file);
|
|
257
|
+
if (!content)
|
|
258
|
+
continue;
|
|
259
|
+
const lines = content.split("\n");
|
|
260
|
+
for (let i = 0; i < lines.length; i++) {
|
|
261
|
+
const line = lines[i];
|
|
262
|
+
if (queryMethodRegex.test(line) || atQueryRegex.test(line)) {
|
|
263
|
+
// Look at current line and the next to handle simple wrapping
|
|
264
|
+
const combinedContext = line + (lines[i + 1] || "");
|
|
265
|
+
if (!/tenant/i.test(combinedContext)) {
|
|
266
|
+
violations.push(`Missing tenant isolation in ${path.relative(rootDir, file)}:${i + 1} — query lacks 'tenantId':\n` +
|
|
267
|
+
` ${line.trim()}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return violations;
|
|
273
|
+
}
|
|
249
274
|
function checkFlywayMigrations(rootDir) {
|
|
250
275
|
const warnings = [];
|
|
251
276
|
const javaFiles = walkDir(rootDir, [".java"]);
|
|
@@ -464,9 +489,9 @@ server.tool("log_rejected_pattern", "Record a coding pattern that was rejected b
|
|
|
464
489
|
});
|
|
465
490
|
// ─── Tool 3: run_pre_pr_checks ───────────────────────────────────────────────
|
|
466
491
|
server.tool("run_pre_pr_checks", "Run all SecuFusion pre-PR guardrail checks across the workspace. " +
|
|
467
|
-
"Automatically discovers modified microservices and runs
|
|
468
|
-
"
|
|
469
|
-
"Linter errors must be fixed natively — do not suppress warnings to pass the gate. " +
|
|
492
|
+
"Automatically discovers modified microservices and runs native linters, database script checks, and strict tenant-isolation scanners. " +
|
|
493
|
+
"Validates: spec checkboxes, hardcoded IPs/URLs, tenantId in Repositories, and Flyway migration coverage for JPA entities. " +
|
|
494
|
+
"Linter/isolation errors must be fixed natively — do not suppress warnings to pass the gate. " +
|
|
470
495
|
"MUST pass with zero errors before a PR is raised.", {
|
|
471
496
|
work_item_id: z
|
|
472
497
|
.string()
|
|
@@ -479,6 +504,7 @@ server.tool("run_pre_pr_checks", "Run all SecuFusion pre-PR guardrail checks acr
|
|
|
479
504
|
.array(z.enum([
|
|
480
505
|
"spec_boxes",
|
|
481
506
|
"console_logs",
|
|
507
|
+
"tenant_isolation",
|
|
482
508
|
"hardcoded_urls",
|
|
483
509
|
"flyway_migrations",
|
|
484
510
|
]))
|
|
@@ -556,7 +582,21 @@ server.tool("run_pre_pr_checks", "Run all SecuFusion pre-PR guardrail checks acr
|
|
|
556
582
|
else {
|
|
557
583
|
warnings.push("⚠️ [LINTING] Linter check SKIPPED (manually bypassed).");
|
|
558
584
|
}
|
|
559
|
-
// ── 3.
|
|
585
|
+
// ── 3. Tenant Isolation Scanner ──────────────────────────────────────────
|
|
586
|
+
if (!skip_checks.includes("tenant_isolation")) {
|
|
587
|
+
const tenantViolations = checkTenantIsolation(scanRoot);
|
|
588
|
+
if (tenantViolations.length > 0) {
|
|
589
|
+
errors.push(`❌ [SECURITY] Tenant Isolation Failed: Found ${tenantViolations.length} query method(s) in *Repository.java without tenant scoping:\n` +
|
|
590
|
+
tenantViolations.map((v) => ` • ${v}`).join("\n"));
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
passed.push("✅ [SECURITY] Tenant isolation active: All database queries correctly scoped with tenantId.");
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
warnings.push("⚠️ [SECURITY] Tenant isolation check SKIPPED (manually bypassed).");
|
|
598
|
+
}
|
|
599
|
+
// ── 4. Hardcoded URL check (regex) ───────────────────────────────────────
|
|
560
600
|
if (!skip_checks.includes("hardcoded_urls")) {
|
|
561
601
|
const urlViolations = checkHardcodedUrls(scanRoot);
|
|
562
602
|
if (urlViolations.length > 0) {
|