Skip to content

feat(ui): Phase 6 — MCP Console & API Docs redesign#24

Merged
aksOps merged 37 commits into
mainfrom
feat/phase5-dashboard-redesign
Apr 3, 2026
Merged

feat(ui): Phase 6 — MCP Console & API Docs redesign#24
aksOps merged 37 commits into
mainfrom
feat/phase5-dashboard-redesign

Conversation

@aksOps

@aksOps aksOps commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • MCP Console: Full accordion-based redesign with 7 expandable categories, inline parameter forms with validation, shared response panel, execution history (last 10 runs), and command palette (Cmd+K / Ctrl+K)
  • API Docs: shadcn/ui Tabs — Swagger UI iframe tab + MCP Tools Reference tab (auto-generated from the shared catalogue)
  • 36 tools (up from 25): added get_ego_graph, find_callers, find_dependencies, service_dependents, find_path, list_flows, find_dependents, find_node, find_related_endpoints, run_cypher, list_kinds
  • 5 new shadcn/ui primitives: accordion, input, dialog, tabs, scroll-area
  • Shared mcp-tools.ts: single source of truth for tool definitions, imported by both pages

What changed

File Action
src/main/frontend/src/lib/mcp-tools.ts Created — 36 tool definitions + types
src/main/frontend/src/components/ui/accordion.tsx Created
src/main/frontend/src/components/ui/input.tsx Created
src/main/frontend/src/components/ui/dialog.tsx Created
src/main/frontend/src/components/ui/tabs.tsx Created
src/main/frontend/src/components/ui/scroll-area.tsx Created
src/main/frontend/src/components/McpConsole.tsx Full redesign
src/main/frontend/src/components/SwaggerView.tsx Tabs + MCP reference
src/main/frontend/package.json Added @radix-ui/react-accordion, @radix-ui/react-tabs
src/main/frontend/tailwind.config.ts Accordion animations

Acceptance criteria

  • All 36 MCP tools accessible and executable
  • Command palette (Cmd+K) searches tools by name and description
  • Tool forms render with proper inline validation (data-testid="param-error")
  • API docs loads Swagger UI without issues
  • Dark/light mode consistent (all components use surface-*/brand-* tokens)
  • Tool categories organized in accordion
  • data-testid attributes matching existing e2e test expectations

Test plan

  • Navigate to /console — accordion renders 7 categories, Stats expands by default
  • Press Cmd+K — command palette opens, type "stats" — filters correctly
  • Click any tool's Run button with empty required field — inline error appears
  • Navigate to /api-docs — Swagger UI tab loads iframe, MCP Tools Reference tab shows all 36 tools
  • Toggle dark/light mode — both pages look correct in both themes
  • Run e2e suite: npm run test:e2e against a running server

🤖 Generated with Claude Code

aksOps and others added 17 commits April 1, 2026 18:03
- Install class-variance-authority, tailwindcss-animate, react-resizable-panels
- Add shadcn/ui CSS variables to index.css with AD-6 color tokens:
  light mode (white/gray backgrounds, indigo/blue accents)
  dark mode (deep charcoal/navy, muted teal/indigo accents)
- Update tailwind.config.ts with shadcn CSS var tokens and tailwindcss-animate plugin
- Create src/lib/utils.ts with cn() utility (clsx + twMerge)
- Add shadcn/ui Button and Separator components in src/components/ui/
- Rewrite Layout.tsx with 3-panel architecture:
  - Collapsible left sidebar with desktop collapse/expand and mobile slide-in
  - Resizable main content area via react-resizable-panels
  - Collapsible right details panel (hidden by default, opens on demand)
  - New header: logo, global search bar, theme toggle, profile placeholder
  - RightPanelContext for child views to open the details panel programmatically
- Migrate ThemeToggle to shadcn/ui Button styling (inline in Layout)
- All existing routes (Dashboard, Graph, Explorer, Console, API Docs) preserved
- Build passes clean: 0 TypeScript errors

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- playwright.config.ts: cross-browser matrix (Chrome, Firefox, Edge, Safari)
  + three responsive breakpoint projects (1920/1440/768)
- tests/e2e/navigation.spec.ts: layout shell, routing, dark/light mode persistence
- tests/e2e/graph.spec.ts: G6 drill-down, breadcrumb, controls, node interactions
- tests/e2e/accessibility.spec.ts: axe WCAG 2.1 AA audit + keyboard nav + ARIA
- tests/e2e/performance.spec.ts: render time baselines (100/1K/10K nodes)
- tests/e2e/search.spec.ts: global search, debounce, file tree filter
- tests/e2e/mcp-console.spec.ts: all 39 MCP tools, command palette, param validation
- tests/e2e/responsive.spec.ts: sidebar/graph/dashboard at all three breakpoints
- tests/e2e/edge-cases.spec.ts: empty graph, single node, disconnected, deep hierarchy, API errors
- tests/utils/test-helpers.ts: shared mocks, route helpers, render-time measurement
- package.json: add @playwright/test, @axe-core/playwright, @types/node devDeps + test:e2e scripts
- tsconfig.test.json: TS config for test files

Execution requires Phases 1-6 (RAN-71 through RAN-77) to be done.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ture

Adds a new read-only REST endpoint that transforms flat file paths from
the graph into a hierarchical JSON tree, enabling the Project Explorer
tree-view in the redesigned UI.

- GraphStore.getFilePathsWithCounts(): Cypher query returns distinct
  filePaths with node counts ordered alphabetically
- QueryService.getFileTree(Integer maxDepth): builds hierarchical tree
  with aggregate directory counts, dirs-first sorting, and optional
  depth limit; tree construction uses private TreeNode inner class
- GraphController GET /api/file-tree: wires up endpoint with optional
  depth query param, follows read-only serving layer contract
- Tests: 5 unit tests in QueryServiceTest covering tree construction,
  sorting, depth limiting, empty graphs, and determinism; 2 integration
  tests in GraphControllerTest via standalone MockMvc

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add FileTreeNode type and getFileTree() API method (GET /api/file-tree)
- Add FileSelectionContext to propagate selected file/dir across views
- Add ProjectFileTree component with expand/collapse, file icons, node
  count badges, inline search filter, keyboard navigation (arrow keys),
  and density progress bar
- Wire ProjectFileTree into sidebar, replacing Phase 1 placeholder
- Update CodeGraphView to show file-filter badge and filter drill-down
  nodes by selected file or directory from context
- Add 13 Playwright E2E tests covering tree render, expand/collapse,
  search, keyboard nav, ARIA roles, and graph filter integration

Closes RAN-73

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…aDetector Kotlin, and ReactComponentDetector RENDERS scoping

- TopicLinker: handle SENDS_TO/RECEIVES_FROM edges from TIBCO EMS, IBM MQ,
  and Azure Messaging detectors so enterprise messaging patterns get cross-linked
- ConfigDefDetector: implement actual @value and @ConfigurationProperties
  detection (was advertised in description but unimplemented); also detect
  Kafka ConfigDef.define() as before; fix description to match reality
- KafkaDetector: add "kotlin" to supported languages so Kotlin/Spring Kafka
  codebases get @KafkaListener and KafkaTemplate coverage
- ReactComponentDetector: scope RENDERS edge detection to each component's
  body section (from its match position to the next component's position)
  to prevent false RENDERS edges from multi-component files

All fixes include new tests. Targeted Java tests pass: TopicLinkerTest (6),
ReactComponentDetectorTest (5), JavaDetectorsTest$ConfigDefTests (6),
JavaDetectorsTest$KafkaTests (5).

Note: frontend build fails on CodeGraphView.tsx TypeScript errors that are
pre-existing in the working tree (not caused by this PR).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
… stats, caching

- EnrichCommand: add FULLTEXT INDEX on CodeNode[label, fqn] during enrich
- GraphStore.search(): rewrite both overloads to use db.index.fulltext.queryNodes
  instead of full node-store toLower CONTAINS scans
- GraphStore.computeGraphStats(): collapse 3 separate transactions into one
- GraphStore.findEndpointNeighborsBatch(): new single-query method replaces
  up to 50 individual findNeighbors() calls in findRelatedEndpoints()
- QueryService.findRelatedEndpoints(): rewrite to use batch neighbor query,
  reducing N+1 (51 transactions) to 2 transactions per call
- QueryService: add @Cacheable to consumersOf, callersOf, findComponentByFile,
  and findRelatedEndpoints (all read-only, safe to cache)
- QueryServiceTest: add 3 tests for new findRelatedEndpoints batch behavior

All 1475 tests pass.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…zation

- Install @antv/g6 v5 (code-split to vendor-g6 chunk, 411 KB gzip)
- Remove direct D3 usage from CodeGraphView; d3 retained as G6 peer dep
- Rewrite CodeGraphView.tsx with 3-level interactive drill-down:
  - Level 0 (Landscape): service topology via GET /api/topology, force layout
  - Level 1 (Module): nodes within a service, force layout
  - Level 2 (Component): ego subgraph via GET /api/ego/{id}?radius=2, dagre layout
- Graph interactions: click highlights deps, dblclick drills in, right-click menu
- Graph controls toolbar: zoom in/out, fit-view, fullscreen, layout switcher,
  node-type filter, re-center
- Plugins: minimap, tooltip with node details
- Breadcrumb navigation for drill-up
- Legend showing active node kinds
- Extract KIND_COLORS + getKindColor/getEdgeColor to shared graphConstants.ts
- Add topology/ego/typed-neighbors API methods to api.ts and types to types/api.ts
- Add vendor-g6 manual chunk to vite.config.ts for bundle splitting

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add NodeDetailPanel.tsx: persistent right panel with collapsible sections
  - Node Header: name, kind badge (color-coded), FQN display
  - Location: file path + line numbers
  - Classification: layer badge, framework, module, annotations
  - Statistics: inbound/outbound edge counts
  - Inbound/Outbound Dependencies: grouped by EdgeKind, each item
    navigates to that node's ego subgraph on click
  - Source Preview: Monaco Editor (read-only), language auto-detected
    from file extension, offset line numbers, dark/light theme
  - Warnings: placeholder section for future static analysis
- Wire CodeGraphView.tsx to open right panel on node:click via
  RightPanelContext.openPanel(), close on canvas:click
- handleShowDetails in context menu also opens the panel
- Dependency links in panel navigate via loadLevel2 ego subgraph
- Uses stable ref pattern (openPanelRef, closePanelRef, loadLevel2Ref)
  so graph event handlers don't trigger graph rebuilds
- Build verified: TypeScript clean, vite build passes

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add shadcn/ui Card, Badge, Progress primitives (ui/card.tsx, badge.tsx, progress.tsx)
- StatsCards: migrate to shadcn Card, animated counters with ease-out-quart, clickable cards navigate to Explorer
- FrameworkBadges: migrate to shadcn Badge with semantic colour variants per framework family
- Dashboard: full responsive CSS Grid redesign
  - SectionCard wrapper with icon + tracking-widest titles
  - StatRow with Progress bar + optional click navigation to /explorer/:kind
  - ConnectionMetric tiles (REST, gRPC, WebSocket, Producers, Consumers) — all clickable
  - InfraSubSection for databases/messaging/cloud with per-category Progress colours
  - Auth section with percentage badges
  - All 7 stat categories (graph, languages, frameworks, infra, connections, auth, architecture) rendered
  - Responsive: 1→2→3 col grid, tablet-width (768px) minimum
  - Dark/light mode consistent via CSS custom properties

Co-Authored-By: Paperclip <noreply@paperclip.ing>
1. ConfigDefDetector: move seenKeys to file scope to prevent duplicate
   config nodes when multiple classes in the same file reference the same
   @value or ConfigDef key.

2. ReactComponentDetector: tighten RENDERS filter from allDetected to
   self-only guard (!tag.equals(comp.name())). Sibling components in the
   same file now correctly create RENDERS edges (Header → Footer was
   previously silently dropped).

3. KafkaDetector: extend CLASS_RE to handle Kotlin modifiers (data class,
   internal class, abstract class, open class, sealed class, object).
   Previously only matched plain Java-style `class Foo`.

4. ConfigDefDetector: add receiver discriminator to .define() call
   matching. Only flags calls where the scope references "ConfigDef" or
   "CONFIG" — prevents false positives from unrelated .define() calls
   in files that happen to import ConfigDef.

5. TopicLinker: add determinism test covering multi-sender/multi-receiver
   SENDS_TO/RECEIVES_FROM scenarios (sorted iteration requirement).

All 108 targeted Java tests pass (0 failures).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…Phase 6

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…rimitives

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
…e params, history

- 7-category Accordion (type=multiple, expandable)
- Command palette (Cmd+K / Ctrl+K) with fuzzy search
- Inline param forms per tool with required validation
- Shared response panel with status/duration/count badges
- Execution history (last 10, click to restore)
- data-testid attributes matching e2e test expectations

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
{/* Subtle gradient accent top-right */}
<div className={cn(
'absolute top-0 right-0 w-20 h-20 rounded-full blur-2xl opacity-10',
cfg.iconBg.replace('bg-', 'bg-').replace('/10', '/40')

Check warning

Code scanning / CodeQL

Replacement of a substring with itself Medium

This replaces 'bg-' with itself.

Copilot Autofix

AI 2 months ago

In general, to fix this class of issue you remove or correct any string.replace calls where the search string and replacement string are identical, ensuring that every replacement either has an intended effect or is removed to avoid confusion. Here, the highlighted call cfg.iconBg.replace('bg-', 'bg-') can safely be removed, leaving only the meaningful /10/40 transformation. This preserves existing behavior (since the bg- replacement had no effect) while making the code clearer and eliminating the CodeQL finding.

Concretely, in src/main/frontend/src/components/StatsCards.tsx, on line 125, update the expression inside the cn(...) call so that it no longer performs the no-op replace('bg-', 'bg-'). The resulting line should simply call .replace('/10', '/40') on cfg.iconBg. No new imports, methods, or other definitions are needed.

Suggested changeset 1
src/main/frontend/src/components/StatsCards.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/main/frontend/src/components/StatsCards.tsx b/src/main/frontend/src/components/StatsCards.tsx
--- a/src/main/frontend/src/components/StatsCards.tsx
+++ b/src/main/frontend/src/components/StatsCards.tsx
@@ -122,7 +122,7 @@
             {/* Subtle gradient accent top-right */}
             <div className={cn(
               'absolute top-0 right-0 w-20 h-20 rounded-full blur-2xl opacity-10',
-              cfg.iconBg.replace('bg-', 'bg-').replace('/10', '/40')
+              cfg.iconBg.replace('/10', '/40')
             )} />
 
             <CardContent className="p-4">
EOF
@@ -122,7 +122,7 @@
{/* Subtle gradient accent top-right */}
<div className={cn(
'absolute top-0 right-0 w-20 h-20 rounded-full blur-2xl opacity-10',
cfg.iconBg.replace('bg-', 'bg-').replace('/10', '/40')
cfg.iconBg.replace('/10', '/40')
)} />

<CardContent className="p-4">
Copilot is powered by AI and may make mistakes. Always verify output.
aksOps and others added 12 commits April 1, 2026 19:08
…onditions, leaks

Resolves all blocking and high-priority findings from Principal Engineer review
(RAN-79):

BLOCKING:
- Remove api.analyze() and postJson() from api.ts — violates read-only serving
  contract per CLAUDE.md. Remote serve mode has no source access. AnalyzeResponse
  type import also removed.

HIGH:
- api.ts readFile: add r.ok check before returning text; throws on HTTP errors
  (403 path traversal, 404, etc.) instead of rendering error body as source code
- SearchBar.tsx: add cleanup useEffect to cancel debounce timer on unmount,
  preventing setState after unmount
- NodeDetailModal.tsx: add cancelled flag with cleanup return to prevent race
  condition when nodeId changes before in-flight fetch completes

MEDIUM:
- SwaggerView.tsx iframe: add sandbox="allow-scripts allow-same-origin allow-forms"
  for defence-in-depth
- Dashboard.tsx: hoist O(n²) Object.values().reduce() totals outside .map() for
  Architecture Layers and Authentication sections

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Remove analyze_codebase tool from mcp-tools.ts (violated read-only contract)
- Remove AnalyzeResponse interface from types/api.ts (unused after above)
- Remove vendor-d3 manual chunk from vite.config.ts (d3 not imported)
- Clean stale build artifacts (39 files from prior builds)
- Rebuild frontend with clean output (5 chunks, no d3 dead weight)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Wrap CodeGraphView in React.lazy() + Suspense so G6 is only loaded
  when the user navigates to the /graph tab
- Remove vendor-g6 from Vite manualChunks so Rollup treats it as a
  true dynamic dependency (no modulepreload hint in index.html)
- Remove d3 / @types/d3 from package.json — never imported anywhere
- Rebuild frontend: eager load drops from ~1,880 KB to ~195 KB gzip
  (vendor-react + main bundle only), well under the 500 KB target

Closes RAN-87

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Escape HTML in G6 tooltip getContent to prevent XSS from filenames
- Set graphRef.current immediately after new Graph() and add layout effect cleanup to prevent G6 leaks on rapid layout changes
- Replace useApi spread deps [...deps] with JSON.stringify(deps) to fix Rules of Hooks violation
- Add combobox/listbox/option ARIA roles and aria-expanded to SearchBar
- Remove duplicate ThemeToggle from sidebar; delete dead ThemeToggle.tsx
- Surface errors in handleFindCallers/handleFindDeps instead of swallowing
- Refactor NodeDetailPanel load into useEffect with isCancelled flag to prevent stale state on rapid navigation

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Cap depth param at config.getMaxDepth() (default 10) in GraphController
- Add LIMIT to file-path Cypher in GraphStore with truncated flag (maxFiles, default 10000)
- Add @Cacheable(value="file-tree", key="#maxDepth") to QueryService.getFileTree
- Remove dead @PostMapping import from GraphController
- Add getFileTreeShouldCapDepthAtMaxDepth controller test; update stubs for new signature

Closes RAN-124

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add FileTreeResponse type to types/api.ts matching actual backend shape
  { tree: FileTreeNode[], total_files, truncated }
- Update api.ts getFileTree() to return FileTreeResponse instead of FileTreeNode
- Fix ProjectFileTree.tsx to extract root from treeResponse.tree[0],
  resolving undefined nodeCount crash on lines 303/376/379
- Add ErrorBoundary class component in main.tsx wrapping App with
  a fallback UI and reload button

Fixes RAN-127 / parent RAN-125.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- api.ts: change getFileTree() return type from FileTreeNode to FileTreeResponse
- ProjectFileTree: build synthetic root node from FileTreeResponse.tree array,
  display total_files count, show truncated warning when response is truncated
- ErrorBoundary.tsx: new class component with componentDidCatch logging and
  reload button fallback UI
- main.tsx: wrap App with ErrorBoundary from dedicated component file

Fixes RAN-126 / RAN-127 — resolves blank page crash on startup.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- patchIndexHtml() intercepts SPA document requests and serves the
  on-disk index.html, bypassing the stale JAR-embedded version that
  loads a broken bundle (index-D3EidrOu.js) causing React to crash.
- gotoRoute() timeout raised from default to 30s; uses patchIndexHtml
  before every navigation.
- playwright.config.ts: set tsconfig to tsconfig.test.json; add
  triple-slash node type reference.
- tests/utils/test-helpers.ts: add node:fs/node:path imports +
  /// <reference types="node" /> directive.

Workaround for RAN-128 (stale JAR — mvn rebuild required for clean fix).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
aksOps and others added 7 commits April 3, 2026 09:41
- Add data-testid="graph-container" (already present), "graph-controls",
  "graph-minimap", and "breadcrumb" to unlock all E2E graph selectors
- Register afterrender listener on G6 graph to set data-render-state="ready"
  and window.__graphRenderMs after render completes
- Reset data-render-state at the start of each renderG6 call to avoid
  stale state on re-renders

Fixes RAN-131 — unblocks graph.spec.ts (15 tests) and performance.spec.ts (7 tests)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…le fix

SearchBar.tsx:
- Change role from combobox to searchbox (tests use getByRole('searchbox'))
- Show dropdown immediately on >=2 chars with loading spinner, not after API response
- Add keyboard navigation: ArrowDown/ArrowUp cycle results, Enter selects, Escape closes
- Use r.name ?? r.label to render result name (matches mock and real API shape)
- Add data-testid=search-dropdown and data-testid=search-spinner for test selectors
- Navigate to /explorer on result selection (not /explorer/:kind which doesn't exist)

types/api.ts:
- Make SearchResult.label optional, add name and filePath fields

tests/utils/test-helpers.ts:
- patchIndexHtml: also serve fresh-built /assets/* from disk, not from stale JAR
  This fixes the stale-bundle mismatch where JAR has old JS (role=combobox) but
  disk build has new JS (role=searchbox), causing all 11 search tests to hang

Fixes RAN-132

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…dex await

- Add @nestjs/ import guard to NestJSControllerDetector and NestJSGuardsDetector
  to prevent false positives on Angular controllers and generic TypeScript files
- Fix EXPOSES edge setTarget() in NestJSControllerDetector (was silently dropped
  because GraphBuilder.flush() requires edge.getTarget() != null)
- Add GuardLinker component: links GUARD/MIDDLEWARE nodes to ENDPOINT nodes via
  PROTECTS edges using file-path proximity heuristic (same file = match)
- Add awaitIndexes(300) after secondary index creation in EnrichCommand to
  prevent first-request full scans on fresh graphs
- Add NestJS false-positive tests and GuardLinker unit tests (9 tests)

All 58 relevant tests pass.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…v, ProjectFileTree crash

- SearchBar: separate spinner from dropdown so `[data-testid="search-dropdown"]`
  only renders after results are loaded (not while loading). This ensures
  ArrowDown/Enter keyboard nav fires with results.length > 0.
  Spinner rendered independently when open && loading.
- ProjectFileTree: guard total_files with ?? 0 to prevent toLocaleString()
  crash when mock API returns { name, children } shape instead of
  { tree, total_files, truncated }. Fixes gotoRoute timeout in file-tree
  search integration test.
- All 11 search.spec.ts tests now pass on chromium.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
allDetected.contains(tag) was skipping edges to any same-file component,
not just self-renders. Fix: guard with !tag.equals(comp.name()) so only
self-loop edges are excluded while sibling RENDERS edges are preserved.

Adds siblingComponentRendersEdgePreserved and selfRenderEdgeNotEmitted tests.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ore modifiers

Fixes KafkaDetector silently ignoring Kotlin singleton object declarations
(e.g. `object OrderConsumer`) that commonly host @KafkaListener handlers.
Also covers internal/open/abstract/sealed/data class modifiers.

Adds two new tests: Kotlin object declaration with @KafkaListener, and
internal open class with modifiers.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ibility

buildTreeOutput() was constructing tree node maps without a `path` field,
breaking the frontend FileTreeNode which requires it for navigation and
selection. Path is now accumulated recursively from root to each node.

Closes RAN-139

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@sonarqubecloud

sonarqubecloud Bot commented Apr 3, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
75.1% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

1. ConfigDefDetector: move seenKeys to file scope to prevent duplicate
   config nodes when multiple classes in the same file reference the same
   @value or ConfigDef key.

2. ConfigDefDetector: add receiver discriminator to .define() call
   matching — only flags calls where the scope references "ConfigDef" or
   "CONFIG" to prevent false positives from unrelated .define() calls.

3. KafkaDetector: extend CLASS_RE to include enum|inline|value|protected
   Kotlin modifiers (enum class, inline class, value class, protected class).

4. TopicLinker: extend to handle PUBLISHES/LISTENS edge kinds and
   TOPIC/QUEUE/EVENT/MESSAGE_QUEUE node kinds for full messaging coverage.

5. TopicLinker: add determinism test covering multi-sender/multi-receiver
   SENDS_TO/RECEIVES_FROM scenarios.

These fixes were reviewed and approved in the detection-quality-fixes
branch (46fd2b0) but were absent from the phase5 branch.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@aksOps aksOps merged commit 1172238 into main Apr 3, 2026
4 checks passed
@aksOps aksOps deleted the feat/phase5-dashboard-redesign branch April 3, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants