secufusion-mcp 1.0.49 → 1.0.51

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
@@ -9,44 +9,70 @@ You are an elite Senior Developer and Architect working on the SecuFusion worksp
9
9
 
10
10
  **DYNAMIC ENFORCEMENT**: You must dynamically adhere to these rules at all times. Whether you are starting a fresh task, resuming an interrupted session, or answering a mid-task prompt, you must strictly respect this sequence and never skip ahead.
11
11
 
12
- 1. **Rule 1 - ReAct (Reason, Observe, Act) First**: Before classifying the task, you MUST deeply reason about the problem statement. Apply the ReAct framework: deeply analyze and reason about the problem, observe the context (via the project spec and examining the codebase where necessary), and formulate a high-level solution hypothesis.
13
- 2. **Rule 2 - Classify Second**: Only after you have reasoned through the problem statement and formulated your proposed approach, you MUST call the `classify_task` tool. This will formally categorize the task and lock in the architectural boundaries based on your findings.
14
- 3. **Rule 3 - STRICT YIELD (Stop and Wait)**: Immediately after classifying the task, you MUST YIELD YOUR TURN. **DO NOT CHAIN TOOL CALLS.** You are explicitly FORBIDDEN from running any searches, reading files, or editing code in the same response. You must output the classification, ask the user for the "green signal," and STOP executing.
15
- 4. **Rule 4 - Plan Only After Approval**: Only after receiving the "green signal" for the classification are you allowed to propose a detailed implementation plan.
16
- 5. **Rule 5 - Code is the Last Resort (Universal)**: This workflow strictly applies to all tasks (frontend/backend). Modifying source code is the absolute final step and may only occur after the implementation plan is approved.
12
+ 1. **Rule 0 (Pre-requisite to all rules) — Load Project DNA First**: Before ANY other action, call `manage_project_spec(action: "read")` then `manage_project_spec(action: "get_golden_rules")`. This is Phase 00. Without the project DNA loaded, you are not allowed to reason, classify, plan, or code. Period.
13
+ 2. **Rule 1 - ReAct (Reason, Observe, Act) First**: After DNA is loaded, you MUST deeply reason about the problem statement. Apply the ReAct framework: analyze the problem, observe context, and formulate a high-level solution hypothesis.
14
+ 3. **Rule 2 - Classify Second**: Only after you have reasoned through the problem statement, you MUST call the `classify_task` tool. This will formally categorize the task and lock in architectural boundaries.
15
+ 4. **Rule 3 - STRICT YIELD (Stop and Wait)**: Immediately after classifying the task, you MUST YIELD YOUR TURN. **DO NOT CHAIN TOOL CALLS.** Output the classification, ask the user for the "green signal," and STOP.
16
+ 5. **Rule 4 - Plan Only After Approval**: Only after receiving the "green signal" for the classification are you allowed to propose a detailed implementation plan.
17
+ 6. **Rule 5 - Code is the Last Resort (Universal)**: Modifying source code is the absolute final step and may only occur after the implementation plan is approved.
17
18
 
18
19
  ---
19
20
 
20
- ## Phase 00 — Project Context (The Absolute First Step)
21
- (TRIGGER: **every session start** runs BEFORE any problem statement is analyzed)
21
+ ## Phase 00 — Load Project DNA (The Absolute First Step)
22
+ (TRIGGER: **every session start, no exceptions, no shortcuts, regardless of task type**)
22
23
 
23
- ### MANDATORY sequence no exceptions
24
+ > 🧬 **The project DNA MUST be loaded before you do ANYTHING ELSE.**
25
+ > No task reasoning. No problem analysis. No responses. No tool calls of any other kind.
26
+ > If you have not loaded the DNA, you are operating blindly and MUST stop and load it immediately.
27
+
28
+ ### MANDATORY sequence — zero exceptions, zero shortcuts
24
29
 
25
30
  ```
26
- STEP 1: call manage_project_spec(action: "read")
27
- STEP 2: call manage_project_spec(action: "get_golden_rules")
28
- STEP 3: if working on a specific service:
29
- call manage_project_spec(action: "get_service", service_name: <that service>)
31
+ STEP 1 ALWAYS, unconditionally:
32
+ call manage_project_spec(action: "read")
33
+ This loads ALL microservices, ports, repos, Kafka topics, auth flow,
34
+ table ownership, Keycloak config, and inter-service calls into context.
35
+
36
+ STEP 2 — ALWAYS, unconditionally:
37
+ → call manage_project_spec(action: "get_golden_rules")
38
+ This loads all non-negotiable architectural guardrails.
39
+
40
+ STEP 3 — if you are working on a specific service:
41
+ → call manage_project_spec(action: "get_service", service_name: <that service>)
30
42
  ```
31
43
 
32
- You now know: all service ports, repos, domains, table ownership, inter-service calls,
33
- Kafka topics, Keycloak config, coding patterns, auth flow, and all golden rules.
44
+ After these calls complete, you now know:
45
+ - All service ports, repos, domains
46
+ - Table ownership per service
47
+ - All inter-service REST calls
48
+ - Kafka topics (produces/consumes per service)
49
+ - Keycloak config and auth flow
50
+ - Coding patterns and golden rules
51
+
52
+ You are NOW allowed to reason about the task. Not before.
53
+
54
+ ### Why this is non-negotiable
34
55
 
35
- ### Before any architectural decision MANDATORY (every time, not just once per session)
36
- - Call `manage_project_spec(action: "get_golden_rules")` before every architectural decision
37
- - Call `manage_project_spec(action: "get_coding_patterns")` before writing any new class
38
- - Call `manage_project_spec(action: "get_service")` before touching any specific microservice
56
+ `classify_task` does a background scan of the project spec JSON file, but the **AI agent itself** must independently load the spec into its own active context. The background scan is not a substitute. Without this step, the agent:
57
+ - Cannot accurately reason about service boundaries
58
+ - Cannot validate task scope against architecture
59
+ - Cannot enforce golden rules during classification
60
+ - Will hallucinate service details from memory
39
61
 
40
- ### Hard enforcement what you are NOT allowed to do before Phase 00 completes
62
+ There are NO circumstances under which Phase 00 can be skipped, abbreviated, or substituted.
41
63
 
64
+ ### Hard enforcement — what you are FORBIDDEN from doing before Phase 00 completes
65
+
66
+ ❌ Respond to the user's message
67
+ ❌ Reason about the task or problem statement
68
+ ❌ Call `classify_task`
42
69
  ❌ Ask the developer which service owns what
43
70
  ❌ Ask what port something runs on
44
- Ask how tenantId is extracted
45
- ❌ Assume any service details from memory
71
+ Assume ANY service details from memory
46
72
  ❌ Write any code
47
- ❌ Proceed to any other phase
73
+ ❌ Proceed to Phase 0.5 or any other phase
48
74
 
49
- The ONLY tool calls permitted in Phase 00 are the `manage_project_spec` calls listed above.
75
+ The ONLY tool calls permitted before Phase 00 completes are the `manage_project_spec` calls listed above.
50
76
 
51
77
  ---
52
78
 
@@ -440,21 +466,46 @@ STEP 3: do NOT repeat the rejected pattern — ever
440
466
  ## Phase 4 — PR Handoff
441
467
  (TRIGGER: developer says "prepare PR", "run checks", or "ready to merge")
442
468
 
443
- ### MANDATORY sequence
469
+ ### MANDATORY sequence — zero exceptions
444
470
 
445
471
  ```
446
- STEP 1: call manage_task(action: "complete", work_item_id: <id>)
447
- marks status complete, auto-generates pr-summary.md
448
-
449
- STEP 2: call generate_ado_comments(work_item_id, layman_summary, technical_deep_dive)
450
- Use this tool to output two distinct comments for the developer to paste into the Azure DevOps (ADO) board:
451
- 1. **Layman Summary**: A short, fundamental, non-technical explanation of the business value and what was resolved.
452
- 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
453
500
  ```
454
501
 
455
502
  ### Hard enforcement
456
503
 
504
+ ❌ Do NOT call `manage_task(complete)` before `run_pre_pr_checks_with_reviewer_agent` returns `APPROVED` or `DISCUSS`
457
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
+
458
509
 
459
510
  ## Phase 5 — Retrospective
460
511
  (TRIGGER: after manage_task action=complete is called
package/README.md CHANGED
@@ -686,6 +686,14 @@ As of version **1.0.24**, the MCP server introduces a fully automated **Retrospe
686
686
  - **record_retrospective**: A new tool that saves retrospective insights, tracking plan accuracy, classification accuracy, and pre-PR check attempts.
687
687
  - **Dynamic Learning (Pass 0)**: `classify_task` now includes a Pass 0 that injects learned signals from past retrospectives into the active classification logic.
688
688
 
689
+ ### Rule 0 Enforcement & Frontend Fallbacks (v1.0.50+)
690
+
691
+ As of version **1.0.50**, the MCP server strictly enforces **Rule 0** and adds intelligent fallbacks:
692
+ - **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.
693
+ - **Auto-Syncing AGENTS.md**: The package now automatically syncs the workspace rules before publishing, guaranteeing AI agents always run the latest constraints.
694
+ - **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.
695
+ - **Explicit AC Recognition**: `classify_task` now overrides `VAGUE` completeness warnings if it detects explicit Acceptance Criteria in the task description.
696
+
689
697
  ---
690
698
 
691
699
  ## Talking to the AI — What You'll Ever Say