Add Blackhorse K-Graph cybersecurity dashboard frontend#20
Add Blackhorse K-Graph cybersecurity dashboard frontend#20Igor Holt (igor-holt) wants to merge 1 commit into
Conversation
Summary of ChangesHello Igor Holt (@igor-holt), I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request delivers a new, modern React and TypeScript-based frontend dashboard designed to provide real-time visualization and interactive control for the Blackhorse threat intelligence platform. It integrates various data streams, including threat events, knowledge graph extractions, and AI model telemetry, to offer a comprehensive operational view for cybersecurity incident response and management. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
The pull request introduces a new React and TypeScript frontend for the Blackhorse K-Graph cybersecurity dashboard, along with its associated CSS module. The dashboard visualizes threat streams, knowledge graph extractions, and modality telemetry. While the implementation provides a functional UI, several areas could be improved for maintainability, robustness, and clarity, particularly regarding hardcoded values, logging practices for critical events, and data representation logic.
|
|
||
| // Initialize WebSocket connection to Blackhorse/ʞGraph bridge | ||
| useEffect(() => { | ||
| const newSocket = io('ws://localhost:8080', { |
There was a problem hiding this comment.
The WebSocket URL ws://localhost:8080 is hardcoded. This makes the component difficult to deploy in different environments (e.g., development, staging, production) without code changes. It should be configurable, perhaps via environment variables or a configuration file.
| const newSocket = io('ws://localhost:8080', { | |
| const newSocket = io(process.env.REACT_APP_WEBSOCKET_URL || 'ws://localhost:8080', { |
| if (status.status !== 'SELF_DETERMINING') { | ||
| console.warn('[GLASS_BREAK] Sovereignty compromised'); | ||
| } |
There was a problem hiding this comment.
Using console.warn for a "Sovereignty compromised" event is not sufficient for a critical security alert. In a production system, such an event should trigger a more robust alerting mechanism (e.g., sending to a dedicated logging service, triggering an incident response workflow, or displaying a prominent, persistent warning in the UI) rather than just a console message.
| font-weight: 600; | ||
| } | ||
|
|
||
| .statusIndicator.normal { |
There was a problem hiding this comment.
Hardcoded color values like #22c55e are used throughout the CSS. For better maintainability and easier theme management, consider defining these colors as CSS variables (custom properties) at a global or component level. This allows for centralized changes and promotes consistency.
background: var(--color-success-light-alpha); /* Example: using a CSS variable */| }); | ||
|
|
||
| newSocket.on('threat_event', (event: ThreatEvent) => { | ||
| setThreats(prev => [event, ...prev].slice(0, 100)); |
There was a problem hiding this comment.
The threats array is limited to the latest 100 events using .slice(0, 100). While this might be an intentional performance optimization for a real-time dashboard, it's an arbitrary limit. Consider making this limit configurable or clearly documenting its purpose, especially if a more extensive history might be needed in the future. The same applies to knowledgeNodes on line 86.
| setThreats(prev => [event, ...prev].slice(0, 100)); | |
| setThreats(prev => [event, ...prev].slice(0, MAX_THREAT_HISTORY)); |
| for (let j = i + 1; j < Math.min(i + 5, knowledgeNodes.length); j++) { | ||
| const timeDiff = Math.abs(knowledgeNodes[i].timestamp - knowledgeNodes[j].timestamp); | ||
| if (timeDiff < 60000) { |
There was a problem hiding this comment.
The values 5 (for Math.min(i + 5, knowledgeNodes.length)) and 60000 (for timeDiff < 60000) are magic numbers. These represent arbitrary thresholds for edge generation based on array index proximity and temporal difference. Extracting these into named constants would significantly improve readability and make the logic easier to understand and modify.
const MAX_NODE_PROXIMITY = 5;
const MAX_TIME_DIFF_MS = 60000; // 1 minute
for (let i = 0; i < knowledgeNodes.length - 1; i++) {
for (let j = i + 1; j < Math.min(i + MAX_NODE_PROXIMITY, knowledgeNodes.length); j++) {
const timeDiff = Math.abs(knowledgeNodes[i].timestamp - knowledgeNodes[j].timestamp);
if (timeDiff < MAX_TIME_DIFF_MS) {
| time: new Date(t.timestamp).toLocaleTimeString(), | ||
| cost: (modality.cost_this_session * (i + 1)) / 20, |
There was a problem hiding this comment.
The calculation (modality.cost_this_session * (i + 1)) / 20 for the cost in costData appears to be an arbitrary scaling of the current session cost. If the intention is to show a historical cost trajectory, this calculation might be misleading as it doesn't reflect actual past costs. Consider if there's a more accurate way to derive or simulate historical cost data for the chart, or clarify the intent of this calculation.
| modality.current_model === 'Haiku' | ||
| ? 'Sonnet' | ||
| : modality.current_model === 'Sonnet' | ||
| ? 'Opus' | ||
| : 'Haiku', |
There was a problem hiding this comment.
The nested ternary operator for determining the target model in requestModalityEscalation is difficult to read and maintain. For better clarity and extensibility, consider using a switch statement or a lookup map to define the escalation logic.
socket.emit('modality_request', {
target: (() => {
switch (modality.current_model) {
case 'Haiku': return 'Sonnet';
case 'Sonnet': return 'Opus';
case 'Opus': return 'Haiku';
default: return 'Haiku'; // Fallback
}
})(),
reason: 'Manual override from dashboard'
});
| <div className={styles.titleSection}> | ||
| <Shield className={styles.logoIcon} size={32} /> | ||
| <h1>BLACKHORSE // ʞ GRAPH</h1> | ||
| <span className={styles.version}>v4.20-DELTA</span> |
There was a problem hiding this comment.
The version string v4.20-DELTA is hardcoded directly in the component. For better release management and consistency, this version should ideally be dynamically loaded from a package.json file or an environment variable during the build process.
<span className={styles.version}>{process.env.REACT_APP_VERSION || 'N/A'}</span>
| <div className={`${styles.statusLarge} ${styles[sovereignty.status.toLowerCase()]}`}> | ||
| <Shield size={64} /> | ||
| <h2>{sovereignty.status}</h2> | ||
| <p>Last Verified: {new Date(sovereignty.last_check).toLocaleString()}</p> |
There was a problem hiding this comment.
Using toLocaleString() without specifying a locale or options can lead to inconsistent date and time formatting across different user environments. For a dashboard, it's generally better to enforce a consistent format. Consider providing specific locale and options (e.g., new Date(sovereignty.last_check).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' })) to ensure uniform display.
<p>Last Verified: {new Date(sovereignty.last_check).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' })}</p>
Motivation
Description
frontend/BlackhorseKGraph.tsx, a React 19 + TypeScript component that defines typed models, opens a Socket.IO connection tows://localhost:8080, subscribes tothreat_stream,kg_extractions, andmodality_telemetry, renders Cytoscape knowledge-graph elements, and draws Recharts time-series for cost/threat trends.frontend/BlackhorseKGraph.module.css, a CSS module implementing the cyber-ops theme, layout, responsive rules, animations, and styles for all dashboard panels and controls.emergencyandmodality_requestevents back to the mesh.Testing
git diff --checkand repository status checks with no reported issues.http://127.0.0.1:5173, which failed withERR_EMPTY_RESPONSEbecause no frontend dev server was running in this environment.Codex Task