secufusion-mcp 1.0.50 → 1.0.52

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.
@@ -13,7 +13,19 @@
13
13
  "commit_message_pattern": "No single enforced convention. Recurring mixture: (1) Azure Repos auto-generated 'Merged PR <number>: <title>' on PR completion (dominant pattern in all 3 sampled repos), (2) ticket-prefixed 'TASK-<number>: <desc>' or 'TASK-<number>-<desc>' (common in sfn-events-api), (3) conventional-commit style 'feat(<scope>): ...' / 'fix(<scope>): ...' (used consistently within recent 'ai-ops' feature work in sfn-web-ui, not elsewhere), (4) plain imperative descriptive messages with no prefix at all. Work items referenced via https://dev.azure.com/secufusion/SFCloud-MSSP/_workitems/edit/<id>."
14
14
  },
15
15
  "coding_patterns": {
16
- "timestamp_handling": "backend ONLY produces UTC timestamp strings. All time formatting and local timezone conversion MUST be handled by the frontend."
16
+ "transactional_placement": "Method level only (never class level). @Transactional(readOnly = true) on read methods, plain @Transactional on write methods. Bulk-operation methods catch Exception per-item internally to accumulate a partial-failure result rather than aborting the whole batch.",
17
+ "exception_handling": "Custom unchecked exceptions (e.g. ResourceNotFoundException, ResourceConflictException) thrown from services, translated centrally by a @ControllerAdvice GlobalExceptionHandler into a flat JSON error body. Controllers additionally often wrap logic in try/catch to log with tenant/id context before rethrowing, which is somewhat redundant with the global handler.",
18
+ "tenant_id_passing": "Explicit String tenantId method parameter into services (not read from ThreadLocal inside the service itself); the controller resolves it once via TenantContextHolder.getActingTenantId() and passes it down.",
19
+ "dto_mapping": "Manual mapping via private convertToDTO()/convertToXxxDTO() helper methods in the service, building DTOs with Lombok @Builder. No MapStruct or ModelMapper used anywhere observed.",
20
+ "dto_suffix": "Inconsistent/mixed: DTO (uppercase) is most common for core domain response objects (e.g. IncidentDTO), Dto (mixed case) also appears (e.g. EventDto), Request is the standard suffix for inbound payloads (e.g. CreateIncidentRequest), Response appears in some newer modules (e.g. ExtensionApiKeyResponse).",
21
+ "lombok_style": "@Data + @Builder + @NoArgsConstructor + @AllArgsConstructor is the standard combination for request/response DTOs; @RequiredArgsConstructor for constructor-injected services; @Slf4j for logging on nearly every service/controller class.",
22
+ "response_wrapping": "Custom generic ResponseDto<T> { results, message, code } wrapper, always returned inside ResponseEntity<ResponseDto<T>>.",
23
+ "api_versioning": "None — base paths follow /api/<domain>/<resource> with no /v1/ or similar version segment anywhere across the platform.",
24
+ "test_naming_convention": "Not fully uniform. Predominantly camelCase descriptive sentence-style method names (e.g. refreshReplacesStaleSecretOnExistingRowAndPrimesCache); some newer test classes instead use snake_case sentence names with @Nested + @DisplayName groupings (e.g. blacklisted_extension_is_blocked_regardless_of_risk). Class-name suffixes are meaningful and consistent: *Test (unit), *IntegrationTest (Testcontainers-backed), *BaselineTest / *RegressionTest / *GuardrailTest (behavior-pinning regression tests), *ContractTest (Kafka payload contracts), *MigrationTest (Flyway migration verification).",
25
+ "assertion_library": "AssertJ (assertThat(...)) is the house standard; plain JUnit assertEquals/assertTrue not used in the sampled files.",
26
+ "query_style": "Mixed within the same repository interfaces: derived query methods (Spring Data naming, incl. nested-property navigation like findByXAndTenant_TenantID), plus @Query using both JPQL and native SQL (native used especially for optional-filter idioms and GROUP BY/aggregate stats queries).",
27
+ "tenant_filter_pattern": "No single universal mechanism. Combination of: (1) explicit tenantId predicate inside @Query/derived repository methods for most tenant-owned entities, (2) a centralized fail-closed HandlerInterceptor (TenantAccessInterceptor, most fully built out in sfn-iam-api and sfn-tenants-api) that validates any tenantId path-variable/query-param against the JWT-resolved acting tenant before the controller runs, (3) explicit service/controller-level TenantAccessGuard.requireCallerCanAccess(...) checks for endpoints addressed by a non-tenant id (e.g. a bare userId), and (4) a small number of repositories/entities are deliberately global/unscoped reference data (countries, package catalogs, scopes, etc.) — see manual_review_flags for entities where this determination could not be fully verified from code alone.",
28
+ "timestamp_handling": "Architecture Rule: The backend ONLY produces UTC timestamp strings. All time formatting and local timezone conversion MUST be handled by the frontend. The backend never returns pre-formatted display strings like timeDisplay or dateDisplay."
17
29
  },
18
30
  "microservices": {
19
31
  "sfn-auth-api": {
@@ -1012,21 +1024,6 @@
1012
1024
  "mismatch_validation": true
1013
1025
  }
1014
1026
  },
1015
- "coding_patterns": {
1016
- "transactional_placement": "Method level only (never class level). @Transactional(readOnly = true) on read methods, plain @Transactional on write methods. Bulk-operation methods catch Exception per-item internally to accumulate a partial-failure result rather than aborting the whole batch.",
1017
- "exception_handling": "Custom unchecked exceptions (e.g. ResourceNotFoundException, ResourceConflictException) thrown from services, translated centrally by a @ControllerAdvice GlobalExceptionHandler into a flat JSON error body. Controllers additionally often wrap logic in try/catch to log with tenant/id context before rethrowing, which is somewhat redundant with the global handler.",
1018
- "tenant_id_passing": "Explicit String tenantId method parameter into services (not read from ThreadLocal inside the service itself); the controller resolves it once via TenantContextHolder.getActingTenantId() and passes it down.",
1019
- "dto_mapping": "Manual mapping via private convertToDTO()/convertToXxxDTO() helper methods in the service, building DTOs with Lombok @Builder. No MapStruct or ModelMapper used anywhere observed.",
1020
- "dto_suffix": "Inconsistent/mixed: DTO (uppercase) is most common for core domain response objects (e.g. IncidentDTO), Dto (mixed case) also appears (e.g. EventDto), Request is the standard suffix for inbound payloads (e.g. CreateIncidentRequest), Response appears in some newer modules (e.g. ExtensionApiKeyResponse).",
1021
- "lombok_style": "@Data + @Builder + @NoArgsConstructor + @AllArgsConstructor is the standard combination for request/response DTOs; @RequiredArgsConstructor for constructor-injected services; @Slf4j for logging on nearly every service/controller class.",
1022
- "response_wrapping": "Custom generic ResponseDto<T> { results, message, code } wrapper, always returned inside ResponseEntity<ResponseDto<T>>.",
1023
- "api_versioning": "None — base paths follow /api/<domain>/<resource> with no /v1/ or similar version segment anywhere across the platform.",
1024
- "test_naming_convention": "Not fully uniform. Predominantly camelCase descriptive sentence-style method names (e.g. refreshReplacesStaleSecretOnExistingRowAndPrimesCache); some newer test classes instead use snake_case sentence names with @Nested + @DisplayName groupings (e.g. blacklisted_extension_is_blocked_regardless_of_risk). Class-name suffixes are meaningful and consistent: *Test (unit), *IntegrationTest (Testcontainers-backed), *BaselineTest / *RegressionTest / *GuardrailTest (behavior-pinning regression tests), *ContractTest (Kafka payload contracts), *MigrationTest (Flyway migration verification).",
1025
- "assertion_library": "AssertJ (assertThat(...)) is the house standard; plain JUnit assertEquals/assertTrue not used in the sampled files.",
1026
- "query_style": "Mixed within the same repository interfaces: derived query methods (Spring Data naming, incl. nested-property navigation like findByXAndTenant_TenantID), plus @Query using both JPQL and native SQL (native used especially for optional-filter idioms and GROUP BY/aggregate stats queries).",
1027
- "tenant_filter_pattern": "No single universal mechanism. Combination of: (1) explicit tenantId predicate inside @Query/derived repository methods for most tenant-owned entities, (2) a centralized fail-closed HandlerInterceptor (TenantAccessInterceptor, most fully built out in sfn-iam-api and sfn-tenants-api) that validates any tenantId path-variable/query-param against the JWT-resolved acting tenant before the controller runs, (3) explicit service/controller-level TenantAccessGuard.requireCallerCanAccess(...) checks for endpoints addressed by a non-tenant id (e.g. a bare userId), and (4) a small number of repositories/entities are deliberately global/unscoped reference data (countries, package catalogs, scopes, etc.) — see manual_review_flags for entities where this determination could not be fully verified from code alone.",
1028
- "timestamp_handling": "Architecture Rule: The backend ONLY produces UTC timestamp strings. All time formatting and local timezone conversion MUST be handled by the frontend. The backend never returns pre-formatted display strings like timeDisplay or dateDisplay."
1029
- },
1030
1027
  "golden_rules": {
1031
1028
  "tenant_isolation": "Multi-layered, not enforced by a single mechanism: JWT issuer resolves caller tenant via per-tenant DB-stored Keycloak config (DbJwtAuthenticationManagerResolver, duplicated across 5 services) -> TenantContextHolder holds the acting tenant for the request -> optional MSSP 'acting tenant' impersonation override via X-Acting-Tenant header or /api/tenants/{tenantId}/... path prefix, gated by ParentChainAuthorizer.isCallerAncestorOrSelf + PrivacyLevelEnforcer.canImpersonate -> TenantAccessInterceptor/TenantAccessGuard perform a fail-closed check of any tenantId path-var/query-param against the acting tenant (most complete in sfn-iam-api and sfn-tenants-api) -> individual repository query methods additionally filter by tenantId for tenant-owned entities. No .rejected-patterns.json file exists anywhere in the workspace to source a canonical, explicitly-authored rule set from — this description is reconstructed from code, not an authored policy document.",
1032
1029
  "rejected_patterns": [],
@@ -1035,7 +1032,17 @@
1035
1032
  "Platform-wide/cross-tenant operations bypass the per-domain authority scheme and instead use bespoke role/type checks: requirePlatformAdmin() and TenantTypeEnum.PLATFORM_ADMIN (sfn-iam-api), requireMasterMsspAdmin()/requireTenantBundleAdmin() checking for role strings 'MASTER MSSP ADMIN'/'MSSP ADMIN' (sfn-policy-api's rules-engine bundle publishing).",
1036
1033
  "Service-account/machine-to-machine requests (browser extension bootstrap, rules-engine publisher, public device/extension enrollment endpoints) are authenticated by JWT azp + issuer matching rather than a user authority, and are explicitly permitAll'd in each service's SecurityConfig under /api/*/public/** or /.well-known/** paths."
1037
1034
  ],
1038
- "explicitly_banned": []
1035
+ "explicitly_banned": [],
1036
+ "coding_style": {
1037
+ "applies_to": [
1038
+ "Java",
1039
+ "TypeScript",
1040
+ "all languages"
1041
+ ],
1042
+ "banned_pattern": "if (x == null) return; OR if (!valid) return value;",
1043
+ "conditionals": "Always nested positive if blocks. Never early returns or guard clauses. Single return point at method end.",
1044
+ "correct_pattern": "if (x != null) { if (valid) { result = work(); } } return result;"
1045
+ }
1039
1046
  },
1040
1047
  "current_state": {
1041
1048
  "active_branch": "Multi-repo — no single active branch. sfn-events-api and sfn-web-ui were checked out on 'develop' at analysis time; snf-browser-extn was checked out on 'main'.",
package/AGENTS.md CHANGED
@@ -466,21 +466,46 @@ STEP 3: do NOT repeat the rejected pattern — ever
466
466
  ## Phase 4 — PR Handoff
467
467
  (TRIGGER: developer says "prepare PR", "run checks", or "ready to merge")
468
468
 
469
- ### MANDATORY sequence
469
+ ### MANDATORY sequence — zero exceptions
470
470
 
471
471
  ```
472
- STEP 1: call manage_task(action: "complete", work_item_id: <id>)
473
- marks status complete, auto-generates pr-summary.md
474
-
475
- STEP 2: call generate_ado_comments(work_item_id, layman_summary, technical_deep_dive)
476
- Use this tool to output two distinct comments for the developer to paste into the Azure DevOps (ADO) board:
477
- 1. **Layman Summary**: A short, fundamental, non-technical explanation of the business value and what was resolved.
478
- 2. **Technical Deep-Dive**: A comprehensive, highly technical breakdown of the architectural changes, core optimizations, and exact implementation details.
472
+ STEP 1: call run_pre_pr_checks_with_reviewer_agent(work_item_id: <id>)
473
+ Tier 1: 5 mechanical checks
474
+ P1 TENANT_ISOLATION — every Repository query scoped to tenantId
475
+ P2 N_PLUS_ONE — no repo calls inside loops
476
+ P3 MISSING_INDEX new query columns have migration index
477
+ P4 KAFKA_SYNC — no sync work inside @KafkaListener
478
+ P5 EARLY_RETURN — no early returns (single-exit rule)
479
+ — Tier 2: AI File Reviewer (only after P1–P5 pass)
480
+ Checks: hardcoded URLs, missing @Transactional(readOnly),
481
+ missing @PreAuthorize, debug statements, exception swallowing,
482
+ TS `any` overuse, missing Flyway for @Entity, cross-service timeouts
483
+ — Tier 3: Context Reviewer (only after Tier 2 passes)
484
+ Reads: spec.json, progress.json, decisions.json, scenarios.json,
485
+ files-touched.json, project-spec golden_rules, rejected patterns
486
+ Cross-references: AC coverage, decision drift, scope creep,
487
+ rejected patterns in file content, test coverage gaps, golden rules
488
+ — Verdict: APPROVED | CHANGES_REQUESTED | DISCUSS
489
+ → If CHANGES_REQUESTED: fix all ❌ findings, then re-run this step
490
+ → If APPROVED or DISCUSS: proceed to Step 2
491
+
492
+ STEP 2: call manage_task(action: "complete", work_item_id: <id>)
493
+ — Only permitted after APPROVED or DISCUSS verdict
494
+ — Marks status complete, auto-generates pr-summary.md
495
+
496
+ STEP 3: call generate_ado_comments(work_item_id, layman_summary, technical_deep_dive)
497
+ — Generates two ADO board comments:
498
+ 1. Layman Summary: non-technical explanation of business value
499
+ 2. Technical Deep-Dive: architectural changes and implementation details
479
500
  ```
480
501
 
481
502
  ### Hard enforcement
482
503
 
504
+ ❌ Do NOT call `manage_task(complete)` before `run_pre_pr_checks_with_reviewer_agent` returns `APPROVED` or `DISCUSS`
483
505
  ❌ Do NOT raise a PR while `pending_acs` is non-empty
506
+ ❌ Do NOT raise a PR if the verdict is `CHANGES_REQUESTED`
507
+ ❌ Do NOT skip the tool and declare the code "obviously clean" — the three tiers catch different classes of issues
508
+
484
509
 
485
510
  ## Phase 5 — Retrospective
486
511
  (TRIGGER: after manage_task action=complete is called
package/README.md CHANGED
@@ -22,6 +22,7 @@
22
22
  | `manage_branch_state` | Legacy — Branch State | Backward-compatible branch-scoped JSON state tracker (for tasks before `manage_task`) |
23
23
  | `log_rejected_pattern` | **Phase 3** — Course Correction | Records bad patterns to `.rejected-patterns.json` so they are never repeated |
24
24
  | `generate_ado_comments` | **Phase 4** — PR Handoff | Generates distinct Layman and Technical Deep-Dive summaries for the Azure DevOps board |
25
+ | `run_pre_pr_checks_with_reviewer_agent` | **Phase 4** — PR Handoff | **NEW** — Unified 3-tier PR gate. Runs mechanical checks, AI file reviews, and context-aware task evaluation in a single pass. |
25
26
  | `get_secufusion_rules` | **Setup** | Returns the `AGENTS.md` rules for AI clients that don't natively support MCP Resources |
26
27
  | `classify_task` | **Phase 0.5** — Task Classification | **NEW** — Deep multi-pass analysis engine. Classifies any task as `BACKEND_ONLY`, `FRONTEND_ONLY`, `FULL_STACK`, or `EXTENSION_ONLY` based on root cause (where the fix lives), not surface symptoms. Must be the first tool called on any task. |
27
28
 
@@ -425,8 +426,9 @@ These rules are enforced automatically — the AI will never violate them:
425
426
  │ Phase 3 │ log_rejected_pattern │
426
427
  │ Correction │ → Record mistakes permanently to avoid repeat │
427
428
  ├──────────────┼──────────────────────────────────────────────────────────────┤
428
- │ Phase 4 │ manage_task (action=complete) → pr-summary.md generated
429
- │ PR Handoff │ generate_ado_comments Layman + Technical Deep-Dive for ADO
429
+ │ Phase 4 │ run_pre_pr_checks_with_reviewer_agent
430
+ │ PR Handoff │ → manage_task (action=complete) pr-summary.md generated
431
+ │ │ → generate_ado_comments → Layman & Technical Deep-Dive (ADO) │
430
432
  └──────────────┴──────────────────────────────────────────────────────────────┘
431
433
  ```
432
434
 
@@ -643,7 +645,8 @@ Phase 1: search_tasks (always) → get_task_history → manage_task initialize
643
645
 
644
646
  Phase 2: code + log_file_touched + log_decision + add_scenario (ALL mandatory)
645
647
 
646
- Phase 4: manage_task complete pr-summary.md generated
648
+ Phase 4: run_pre_pr_checks_with_reviewer_agentAPPROVED / DISCUSS
649
+ → manage_task complete → pr-summary.md generated
647
650
  → generate_ado_comments → Layman + Technical Deep-Dive for ADO board
648
651
  ```
649
652
 
@@ -686,6 +689,14 @@ As of version **1.0.24**, the MCP server introduces a fully automated **Retrospe
686
689
  - **record_retrospective**: A new tool that saves retrospective insights, tracking plan accuracy, classification accuracy, and pre-PR check attempts.
687
690
  - **Dynamic Learning (Pass 0)**: `classify_task` now includes a Pass 0 that injects learned signals from past retrospectives into the active classification logic.
688
691
 
692
+ ### Rule 0 Enforcement & Frontend Fallbacks (v1.0.50+)
693
+
694
+ As of version **1.0.50**, the MCP server strictly enforces **Rule 0** and adds intelligent fallbacks:
695
+ - **Rule 0 (DNA Load First)**: Agents are now strictly forbidden from reasoning, classifying, or planning until they have called `manage_project_spec` to load the project DNA.
696
+ - **Auto-Syncing AGENTS.md**: The package now automatically syncs the workspace rules before publishing, guaranteeing AI agents always run the latest constraints.
697
+ - **Frontend Service Resolution**: `get_service` now intelligently resolves frontend and extension repositories (like `sfn-web-ui`) even when they aren't explicitly keyed as backend microservices.
698
+ - **Explicit AC Recognition**: `classify_task` now overrides `VAGUE` completeness warnings if it detects explicit Acceptance Criteria in the task description.
699
+
689
700
  ---
690
701
 
691
702
  ## Talking to the AI — What You'll Ever Say
@@ -799,7 +810,7 @@ Proceeding to plan presentation. No developer confirmation needed.
799
810
  | **Phase 1 (Planning)** | `"Call search_tasks if relevant"` | `search_tasks` is **unconditional** — STEP 1 always, even if "sure" there's no prior work |
800
811
  | **Phase 2 (Execution)** | Bullet suggestions | MANDATORY code block for all 4 tool calls + `next_step` contract with explicit VIOLATION labels |
801
812
  | **Phase 3 (Correction)** | `"Immediately call log_rejected_pattern"` | Explicit STEP 1/2/3 + ❌ list — log immediately, not end of session |
802
- | **Phase 4 (PR Handoff)** | `"Call complete → run checks → fix if error"` | Explicit STEP 1-4 **fix → recheck loop** until ZERO errors |
813
+ | **Phase 4 (PR Handoff)** | `"Call complete → run checks → fix if error"` | Explicit STEP 1-3 **fix → recheck loop** until ZERO errors (Unified 3-tier check) |
803
814
  | **Guardrails** | Mixed soft/hard language | All `should` → `MUST`, all `avoid` → `FORBIDDEN`, linter errors explicitly blocking |
804
815
  | **Cross-Task Intelligence** | Prose bullets | MANDATORY STEP 1-4 sequence + ❌ list |
805
816