<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MEHRAAN AMIN</title>
    <description>The latest articles on DEV Community by MEHRAAN AMIN (@codewithmehru).</description>
    <link>https://dev.to/codewithmehru</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3959500%2F665b6d1e-03b0-4f09-a167-b158bc528215.jpg</url>
      <title>DEV Community: MEHRAAN AMIN</title>
      <link>https://dev.to/codewithmehru</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codewithmehru"/>
    <language>en</language>
    <item>
      <title>How I Built Triage: Turning SigNoz into a Blue Team SOC (And the Deployment Nightmares I Survived)</title>
      <dc:creator>MEHRAAN AMIN</dc:creator>
      <pubDate>Sat, 25 Jul 2026 18:18:22 +0000</pubDate>
      <link>https://dev.to/codewithmehru/how-i-built-triage-turning-signoz-into-a-blue-team-soc-and-the-deployment-nightmares-i-survived-pni</link>
      <guid>https://dev.to/codewithmehru/how-i-built-triage-turning-signoz-into-a-blue-team-soc-and-the-deployment-nightmares-i-survived-pni</guid>
      <description>&lt;p&gt;Most people use OpenTelemetry and SigNoz to watch their CPU usage, find memory leaks, or figure out why their API is taking 400ms instead of 200ms. But for the Agents of SigNoz Hackathon (Track 3: Observe Anything Weird), I wanted to do something completely different.&lt;/p&gt;

&lt;p&gt;I didn't want to watch hardware. I wanted to watch hackers.&lt;/p&gt;

&lt;p&gt;That is how Triage was born. It is an OpenTelemetry-powered Blue Team SOC (Security Operations Center) that tracks active cyber attacks instead of just generic application performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Original Vision vs. The Reality
&lt;/h3&gt;

&lt;p&gt;Building this sounded straightforward on paper: catch bad traffic, wrap it in an OpenTelemetry span, send it to SigNoz, and show it on a custom dashboard. But actually deploying this beast before the deadline was a completely different story.&lt;/p&gt;

&lt;p&gt;If you have ever tried to deploy a full-stack Next.js app, a Python honeypot, and an OTel pipeline while the clock is ticking, you know exactly what kind of panic I am talking about. Here is what actually happened behind the scenes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Azure VM &amp;amp; Docker Crash&lt;/strong&gt;&lt;br&gt;
I started by spinning up an Azure virtual machine to self-host the SigNoz backend. I pulled the repo, ran docker compose up -d, and immediately watched my server completely freeze. Turns out, my free tier Azure instance (Standard_B2ats_v2) only had 1 GiB of RAM. You simply cannot run a massive ClickHouse database and a full OTel collector on 1GB of memory without it crashing instantly. I had to pivot fast and rely on the cloud endpoints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Vercel vs Localhost Trap&lt;/strong&gt;&lt;br&gt;
Once I got the backend running, I hit my next wall. My Vercel Next.js dashboard kept throwing 500 Internal Server Error on the threat simulation API, and the SigNoz connection kept reading OFFLINE (fetch failed). I was staring at my logs losing my mind until it clicked. My Vercel environment variables had SIGNOZ_API_URL set to &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt; and my Python script was looking for OTel on localhost:4318.&lt;/p&gt;

&lt;p&gt;Note to self (and everyone else): Vercel is a cloud server. It has no idea what your local Kali Linux machine or Azure VM is doing on localhost. I had to either use Ngrok to tunnel my local endpoints to the public internet or point everything strictly to public cloud URLs so Vercel could actually talk to the backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The Supabase Keys Nightmare&lt;/strong&gt;&lt;br&gt;
To persist the threat logs for the dashboard, I was connecting to Supabase. But nothing was writing to the database and the UI was stuck on "UNCONFIGURED".&lt;/p&gt;

&lt;p&gt;It turns out I had mistakenly treated my master database key like a public variable. In Next.js, if you prefix a secret key with NEXT_PUBLIC_, you expose it to the browser. But my API routes were strictly looking for the exact string SUPABASE_SERVICE_ROLE_KEY to securely insert data. A single prefix mismatch broke the entire flow. Once I stripped the prefix, passed the raw service key to the Vercel settings, and hit redeploy, the database finally connected and the traces started flowing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Features We Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Despite the deployment chaos, the final system works beautifully. Here is what Triage actually does:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-Powered Threat Analysis (Groq &amp;amp; Llama-3.1)&lt;/strong&gt;&lt;br&gt;
When a normal APM sees a 403 error, it just logs a generic spike on a graph. When Triage intercepts an SQL injection or a leaked API key, it captures the raw payload and immediately sends it to Groq. The LLM generates a clean, 3-sentence summary of the attack vector, which we attach directly to the OpenTelemetry trace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python TCP Honeypot Trap&lt;/strong&gt;&lt;br&gt;
I didn't just want to watch web traffic. I wrote an asyncio Python script that acts as a honeypot listening on port 2222 (mocking SSH) and 63790 (mocking Redis). When automated bots or tools like Nmap run a port scan against my server, the honeypot catches the IP, generates a custom OTel trace, and ships it to the collector via OTLP HTTP on port 4318.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SRE Sidekick (Auto-Ban)&lt;/strong&gt;&lt;br&gt;
We built an active defense mechanism. If the system tracks 5 attacks from the same IP within 60 seconds, it triggers a self-healing protocol. It drops an sre.auto_ban.triggered span and instantly enforces a firewall block on that attacker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cyberpunk SOC Command Center&lt;/strong&gt;&lt;br&gt;
I built the entire frontend in Next.js 16. It pulls live telemetry traces, shows real-time threat stats, and features a "Red Team Simulator". Judges and users can safely simulate SQL injections or data leaks directly in the browser with one click to see the telemetry populate live.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Actually Used SigNoz
&lt;/h2&gt;

&lt;p&gt;This is where it gets fun. I didn't use any of the standard HTTP auto-instrumentation for the security layer. I built custom OpenTelemetry spans tailored specifically for a Blue Team.&lt;/p&gt;

&lt;p&gt;Instead of tracking standard routes, I mapped out an adversary's footprint. Here is exactly what I sent to the SigNoz collector:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom Spans: I created custom span names like security.trap when a web exploit was caught, and honeypot.port_scan for TCP probes.&lt;/li&gt;
&lt;li&gt;    Security Attributes: Inside these spans, I injected attributes like security.severity = 'CRITICAL', security.threat_type = 'SQL_INJECTION', and security.source_ip.&lt;/li&gt;
&lt;li&gt;    AI Metrics: For every payload analyzed by Groq, the trace included llm.latency, llm.model, and threat.goal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By doing this, I could open the SigNoz Query Builder and run a simple query to see every critical SQL injection attempt across my entire infrastructure, mapped out in real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This hackathon pushed me to my absolute limits. Between fighting cloud networking rules, debugging Next.js server crashes, and forcing OpenTelemetry to act like a SIEM, I learned more in a few days than I have in months.&lt;/p&gt;

&lt;p&gt;SigNoz proved to be incredibly flexible. It isn't just for tracking uptime. If you structure your telemetry right, you can observe absolutely anything. Even the weird stuff.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>hackathon</category>
      <category>signoz</category>
    </item>
    <item>
      <title>Catching API Attacks in Real Time: A Penetration Tester's Guide to SigNoz</title>
      <dc:creator>MEHRAAN AMIN</dc:creator>
      <pubDate>Fri, 17 Jul 2026 06:46:09 +0000</pubDate>
      <link>https://dev.to/codewithmehru/catching-api-attacks-in-real-time-a-penetration-testers-guide-to-signoz-1973</link>
      <guid>https://dev.to/codewithmehru/catching-api-attacks-in-real-time-a-penetration-testers-guide-to-signoz-1973</guid>
      <description>&lt;p&gt;&lt;em&gt;When I saw the Agents of SigNoz challenge, my timeline was immediately flooded with basic uptime monitors and standard e-commerce tracing setups. But what if we flip the script and use observability as a Blue Team security tool to catch attackers in real time?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Most developers use OpenTelemetry to figure out why a database query is slow or why an API endpoint is failing. As someone who spends time on penetration testing and building custom security tools on Kali Linux, I see server latency entirely differently. A sudden CPU spike is not always bad code; sometimes it is an active attacker attempting resource exhaustion or a Denial of Service.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I wanted to see if I could build a trap. My goal was to create a vulnerable Express.js API that actively detects SQL injection payloads, deliberately stalls the server CPU, and alerts me instantly through the SigNoz dashboard using OpenTelemetry traces and metrics. Here is exactly how I built it, the errors I hit during the local deployment, and how I caught the attack.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Setup and The Foundry Curveball&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My environment of choice is Kali Linux, and I decided to self-host SigNoz using Docker. Like many developers starting out, I went straight to the GitHub repository and attempted to run the legacy bash installation script using a simple wget command.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My terminal immediately threw a &amp;lt;!DOCTYPE html&amp;gt; syntax error. It turned out I was downloading the HTML page of the script rather than the raw file, but even after fixing that, I realized the old install.sh script had been deprecated. SigNoz recently migrated to a much more robust CLI tool called Foundry for their deployments.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I pivoted to the new instructions and installed the Foundry CLI:_&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -fsSL https://signoz.io/foundry.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;To tell Foundry that I wanted a local Docker Compose setup rather than a Kubernetes deployment, I created a &lt;code&gt;quick casting.yaml&lt;/code&gt; configuration file:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1alpha1
kind: Installation
metadata:
  name: signoz
spec:
  deployment:
    flavor: compose
    mode: docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;I ran &lt;code&gt;foundryctl cast -f casting.yaml&lt;/code&gt; and the download process began. Everything was going smoothly until the process reached the massive ClickHouse telemetry store containers. Right at 233.1MB out of 246.3MB, my local internet connection dropped completely. The docker daemon threw a fatal context deadline exceeded (Client.Timeout exceeded while awaiting headers) error, and the entire installation crashed out with a signal: killed exception.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Usually, a broken docker pull means you have to clean up dangling images and start over. However, the Foundry CLI handled the interruption perfectly. Once my connection was restored, I ran docker compose down to clear the partial container states, re-ran the cast command, and it picked up the exact remaining 13 megabytes without missing a beat.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building the Trap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With the SigNoz backend up and running, I needed an application to monitor. I started by creating a new directory and initializing a blank Node.js project. To make sure SigNoz could automatically capture the traces without me writing hundreds of lines of custom spans, I needed to install the official OpenTelemetry auto-instrumentation packages. If you are following along, you can set up the exact same environment using this command:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
npm install express @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-grpc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The &lt;code&gt;auto-instrumentations-node package&lt;/code&gt; is the real hero here. It automatically intercepts HTTP requests and Express middleware out of the box, saving a massive amount of setup time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I wrote a specific login route to act as my trap. If the username field contained common SQL injection characters (like a single quote) or cross-site scripting tags, the server would log a local security alert.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But logging is not enough for true observability. To simulate how a real server reacts to a heavy malicious payload being mitigated by a Web Application Firewall, I added a heavy while loop that deliberately stalls the CPU for a split second before returning a 403 Forbidden error. This meant that an attack would not just cause a status code error, it would cause a highly visible, physical spike in latency.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Here is the exact code I used for &lt;code&gt;app.js&lt;/code&gt;:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const app = express();
app.use(express.json());

// Dummy login route serving as the trap
app.post('/api/login', (req, res) =&amp;gt; {
    const { username, password } = req.body;

    // Simulate detecting a malicious payload
    if (username.includes("'") || username.includes("&amp;lt;script&amp;gt;")) {
        console.warn(`[SECURITY ALERT] Malicious payload detected from IP: ${req.ip}`);

        // Simulate high CPU and Latency during attack mitigation
        let i = 0; while (i &amp;lt; 100000000) i++; 

        return res.status(403).json({ error: "Access Denied" });
    }

    if (username === 'admin' &amp;amp;&amp;amp; password === 'admin123') {
        res.status(200).json({ message: "Success" });
    } else {
        res.status(401).json({ error: "Invalid credentials" });
    }
});

app.listen(8081, () =&amp;gt; console.log('Vulnerable API running on port 8081'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;You might notice the application is set to listen on port 8081 instead of the standard Node.js port 8080. This was another hard lesson learned during the build. The new Foundry architecture maps the SigNoz frontend dashboard directly to port 8080. When I initially tried to run my API, I hit an EADDRINUSE error. I used a quick sed -i 's/8080/8081/g' app.js command to swap my application port and avoid the conflict.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To instrument the application without manually rewriting all my HTTP handlers, I used OpenTelemetry's auto-instrumentation package. I exported my local SigNoz endpoint and started the server:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317"
export OTEL_RESOURCE_ATTRIBUTES="service.name=sec-target-api"
node --require @opentelemetry/auto-instrumentations-node/register app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Executing the Attack&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With the API listening and sending telemetry data via gRPC to the local collector, I opened a second terminal window to act as the attacker machine.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I wrote a quick bash script to bombard my new API with fifty consecutive requests. I mixed standard failed logins with blatant SQL injection payloads to see if SigNoz could differentiate the traffic noise from the actual attacks.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for i in {1..50}; do
  # Normal failed login attempt
  curl -s -X POST http://localhost:8081/api/login -H "Content-Type: application/json" -d '{"username":"test","password":"123"}' &amp;gt; /dev/null

  # Attack payload featuring SQLi
  curl -s -X POST http://localhost:8081/api/login -H "Content-Type: application/json" -d '{"username":"admin'\'' OR 1=1--","password":"123"}' &amp;gt; /dev/null
done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The moment I executed the loop, my server terminal lit up with warnings. The custom security logic was catching the payloads perfectly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8n6itr2e92mlslp3xjf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8n6itr2e92mlslp3xjf9.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Catching the Attacker in SigNoz&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Local terminal logs are great, but in a production environment, you cannot sit and watch a server console all day. I opened the SigNoz dashboard on localhost:8080 and navigated to the Traces Explorer to see what the telemetry data captured.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkw6qrx6n9z1ndk8mc5ay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkw6qrx6n9z1ndk8mc5ay.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Traces list painted a perfect picture of the attack. Every single malicious request was captured, categorized, and flagged with a red 403 status code. The normal failed logins were also logged, allowing me to easily filter and separate standard user error from malicious intent.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But the most critical piece of observability came from the service metrics. Because I had specifically coded the API to stall the CPU during payload detection, I navigated to the Latency graphs expecting to see the impact.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0vrt9oiuzd9unwyzwvdv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0vrt9oiuzd9unwyzwvdv.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The P99 latency graph showed an immediate, massive spike pushing past 200ms at the exact timestamp the bash loop was executed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This visualizes a major concept in cybersecurity. Attackers frequently attempt to exhaust server resources by sending heavy, complex payloads that force the database or backend logic to work overtime. Without a dedicated observability platform like SigNoz, a developer might look at a sluggish server and assume they need to optimize their code or upgrade their hardware. By looking at this dashboard, I could immediately correlate the massive latency spike directly with the influx of 403 errors. The code wasn't slow; it was under attack.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To get even more granular, I clicked into one of the specific red traces from the explorer. SigNoz generated a highly detailed flamegraph representing the exact lifecycle of the HTTP POST request.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdr2ymipehzzexeg68ha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdr2ymipehzzexeg68ha.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The flamegraph visually broke down exactly where the delay was happening. I could see the exact microsecond the request hit the Express middleware, passed through the JSON parser, and finally hit the patched request handler where the CPU stall occurred. If this had been a real application, this trace would tell me exactly which function was vulnerable to resource exhaustion.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned and Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building this project taught me several practical lessons that reading documentation simply cannot cover:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Foundry is Resilient:&lt;/strong&gt; Dealing with massive Docker image pulls on an unstable internet connection is usually a nightmare. The Foundry CLI proved incredibly resilient, allowing me to resume a broken ClickHouse installation seamlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mind Your Ports:&lt;/strong&gt; When self-hosting complex microservice architectures, port collisions are inevitable. Knowing that SigNoz claims port 8080 by default saved me a lot of debugging time when setting up my own Node.js backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics Tell a Story:&lt;/strong&gt; Security is not just about error logs. Monitoring P90 and P99 latency metrics provides a physical representation of how your server reacts to hostile traffic. A sudden latency spike combined with an unusual HTTP status code is often the first indicator of an active breach attempt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Open-source tools like SigNoz give you total, uncompromised visibility into your system, proving that by combining full-stack development with deep observability, you can catch anomalies before they become full-scale breaches.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>signoz</category>
      <category>tutorial</category>
      <category>security</category>
      <category>observability</category>
    </item>
    <item>
      <title>HackDesk: My Passion for Hackathons, Powered by Google AI</title>
      <dc:creator>MEHRAAN AMIN</dc:creator>
      <pubDate>Fri, 10 Jul 2026 09:55:53 +0000</pubDate>
      <link>https://dev.to/codewithmehru/hackdesk-my-passion-for-hackathons-powered-by-google-ai-2cg1</link>
      <guid>https://dev.to/codewithmehru/hackdesk-my-passion-for-hackathons-powered-by-google-ai-2cg1</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-07-09"&gt;Weekend Challenge: Passion Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;My biggest &lt;strong&gt;passion&lt;/strong&gt; is the developer community and hackathons. I love seeing students build amazing things, but I’ve also seen the struggles: organizers stress over check-ins, and beginners freeze when they can't think of a good project idea. &lt;/p&gt;

&lt;p&gt;Fueled by this passion to help my community, I built &lt;strong&gt;HackDesk - Passion Edition&lt;/strong&gt;. It is an intelligent, high-performance event management system designed for large-scale hackathons. It features a robust attendee registration system and an &lt;strong&gt;AI-powered Hackathon Idea Generator&lt;/strong&gt; that instantly provides customized, beginner-friendly project ideas to students so they can start building immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Live Vercel Deployment: &lt;a href="https://hackdesk-passion.vercel.app" rel="noopener noreferrer"&gt;HackDesk Passion Edition&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Feel free to try the Idea Generator to see the Google AI fallback in action!)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/CodeWithMehru" rel="noopener noreferrer"&gt;
        CodeWithMehru
      &lt;/a&gt; / &lt;a href="https://github.com/CodeWithMehru/HackDesk-Passion-Edition" rel="noopener noreferrer"&gt;
        HackDesk-Passion-Edition
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
  &lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🚀 HackDesk - Passion Edition&lt;/h1&gt;
&lt;/div&gt;
  &lt;p&gt;&lt;strong&gt;An Intelligent, Concurrency-Proof Hackathon Management Platform&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/3446fd60224519c6d63061b3f6481c9fbd6523d87bf97f7d48bdf23199b74f3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6578742e6a732d626c61636b3f7374796c653d666f722d7468652d6261646765266c6f676f3d6e6578742e6a73266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/3446fd60224519c6d63061b3f6481c9fbd6523d87bf97f7d48bdf23199b74f3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6578742e6a732d626c61636b3f7374796c653d666f722d7468652d6261646765266c6f676f3d6e6578742e6a73266c6f676f436f6c6f723d7768697465" alt="Next JS"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b308ff9a6de632b94c933c0f27975188080f8cf88a115ae10338540f8d9ab8ab/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f547970655363726970742d3030374143433f7374796c653d666f722d7468652d6261646765266c6f676f3d74797065736372697074266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/b308ff9a6de632b94c933c0f27975188080f8cf88a115ae10338540f8d9ab8ab/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f547970655363726970742d3030374143433f7374796c653d666f722d7468652d6261646765266c6f676f3d74797065736372697074266c6f676f436f6c6f723d7768697465" alt="TypeScript"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/84af53087957d441ad085a426371a789f1a45cd082080cb9cf63e7dd38ac082d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5461696c77696e645f4353532d3338423241433f7374796c653d666f722d7468652d6261646765266c6f676f3d7461696c77696e642d637373266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/84af53087957d441ad085a426371a789f1a45cd082080cb9cf63e7dd38ac082d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5461696c77696e645f4353532d3338423241433f7374796c653d666f722d7468652d6261646765266c6f676f3d7461696c77696e642d637373266c6f676f436f6c6f723d7768697465" alt="Tailwind CSS"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/157fb250a4c850de1caa4a9112da44de759352a114486112a7176f8f9712e65f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53757061626173652d3345434638453f7374796c653d666f722d7468652d6261646765266c6f676f3d7375706162617365266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/157fb250a4c850de1caa4a9112da44de759352a114486112a7176f8f9712e65f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53757061626173652d3345434638453f7374796c653d666f722d7468652d6261646765266c6f676f3d7375706162617365266c6f676f436f6c6f723d7768697465" alt="Supabase"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;HackDesk&lt;/strong&gt; is a high-performance event management system designed to seamlessly handle large-scale hackathons. It features a robust registration and check-in system, alongside a unique &lt;strong&gt;AI-powered Hackathon Idea Generator&lt;/strong&gt; equipped with &lt;strong&gt;atomic locking&lt;/strong&gt; to prevent race conditions during high-traffic claim events.&lt;/p&gt;
&lt;p&gt;Built with modern web technologies to ensure low latency, high availability, and a premium user experience.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ Key Features&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;👥 Smart Registration &amp;amp; Attendance:&lt;/strong&gt;
Bulk-import participants via CSV parsing
Manually add late or on-the-spot attendees seamlessly.
Active Session tracking (e.g., "Day 1", "Day 2") for accurate multi-day check-ins.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🧠 AI-Powered Idea Pool (Pre-generation &amp;amp; Smart Fallback Architecture):&lt;/strong&gt;
Organizers can generate batches of beginner-friendly project ideas based on specific themes using the Google Gemini AI API
Pre-generating ideas prevents API rate limits and keeps the end-user experience lightning fast. If the pool runs empty, the system uses Google AI as…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/CodeWithMehru/HackDesk-Passion-Edition" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;I built HackDesk using &lt;strong&gt;Next.js 16 (App Router)&lt;/strong&gt;, &lt;strong&gt;TypeScript&lt;/strong&gt;, &lt;strong&gt;Tailwind CSS&lt;/strong&gt;, and &lt;strong&gt;Supabase (PostgreSQL)&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Managing a hackathon means dealing with high traffic (e.g., 200 students clicking "Generate Idea" at the exact same millisecond). To solve this, I engineered a &lt;strong&gt;Concurrency-Proof Idea Claiming system&lt;/strong&gt;. The backend uses strict isolation and atomic row-level locking in PostgreSQL so that no two students ever get the same idea.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Smart Fallback Architecture:&lt;/strong&gt;&lt;br&gt;
To ensure the system never crashes or runs out of ideas, I implemented a two-tier architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It first tries to fetch a pre-generated idea from the Supabase pool.&lt;/li&gt;
&lt;li&gt;If the pool is completely empty, instead of throwing an error, the system seamlessly falls back to &lt;strong&gt;Google Gemini AI 1.5 Flash&lt;/strong&gt;. The AI generates a fresh, structured JSON idea on the spot, saves it to the database, and assigns it to the student instantly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;I am submitting this project for the &lt;strong&gt;Best use of Google AI&lt;/strong&gt; prize category. &lt;/p&gt;

&lt;p&gt;I utilized the &lt;code&gt;@google/generative-ai&lt;/code&gt; SDK (Gemini 1.5 Flash model) to create the live fallback mechanism. This ensures that the hackathon's idea generation never hits a dead end, combining database reliability with the dynamic generative power of Google AI.&lt;/p&gt;

</description>
      <category>weekendchallenge</category>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>api</category>
    </item>
    <item>
      <title>How we built KoshurLock Holmes: an AI detective for cyber attacks, and the night it almost broke me</title>
      <dc:creator>MEHRAAN AMIN</dc:creator>
      <pubDate>Sun, 05 Jul 2026 06:54:50 +0000</pubDate>
      <link>https://dev.to/codewithmehru/how-we-built-koshurlock-holmes-an-ai-detective-for-cyber-attacks-and-the-night-it-almost-broke-me-509k</link>
      <guid>https://dev.to/codewithmehru/how-we-built-koshurlock-holmes-an-ai-detective-for-cyber-attacks-and-the-night-it-almost-broke-me-509k</guid>
      <description>&lt;p&gt;The problem with a data breach is not finding evidence. It is connecting it.&lt;/p&gt;

&lt;p&gt;But let me start where I actually was: 4 AM, last day of the hackathon, staring at this in my terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RateLimitError: GroqException - Rate limit reached for model
`llama-3.3-70b-versatile` on tokens per day (TPD):
Limit 100000, Used 99787, Requested 1616.
Please try again in 20m12s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used 99,787 out of 100,000. My deployment was half done, my demo graph was empty on the server, and the free tier had 213 tokens left. The submission deadline was hours away. I had not slept. I had not eaten. My friends were asleep and I was swapping API keys like a gambler swapping chips.&lt;/p&gt;

&lt;p&gt;This post is the story of how we got there, and how it ended at 7 in the morning with the best sigh of relief I have ever taken.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, some honesty about how I got here
&lt;/h2&gt;

&lt;p&gt;When I joined my first WeMakeDevs hackathon, I did not believe in it. I thought it was one of those ordinary online events. Fake prizes, no follow-through, what would I even get out of it. I joined anyway, mostly out of boredom, got into the Discord, talked to people, made a few connections.&lt;/p&gt;

&lt;p&gt;I landed in the top 50. A few days later an email showed up: a free Claude Max subscription as a gift. I read it twice. I genuinely could not believe a hackathon had actually delivered something.&lt;/p&gt;

&lt;p&gt;So when this hackathon opened, I did not hesitate. I messaged my friends and said we are joining as a team this time. Three of us: me (Mehraan), Aqib, and Ubaid.&lt;/p&gt;

&lt;h2&gt;
  
  
  The spark
&lt;/h2&gt;

&lt;p&gt;We spent the first evening in our group chat throwing ideas around and shooting most of them down. Then one of my friends dropped a thought that stuck: what happens after a company gets hacked?&lt;/p&gt;

&lt;p&gt;I started digging into it. The answer is honestly depressing. After a breach, the evidence is everywhere. VPN records. File access logs. The email gateway. Badge readers at the office doors. CCTV. HR notes. Anonymous tips. Each system tells one small piece of the story, and a human analyst has to stitch all of it together by hand.&lt;/p&gt;

&lt;p&gt;That stitching takes days. Sometimes weeks. It is exactly the kind of digital forensics work that companies like Palantir charge enormous money for. And here is the ugly part: read each log alone and the logs will lie to you. If an attacker steals an employee's password, every log points at the employee. The truth only appears when you connect the same person, account, device, IP, and file across every source at once.&lt;/p&gt;

&lt;p&gt;So that became the project. An AI investigator that reads all the scattered logs, builds one connected knowledge graph out of them, and answers plain English questions with cited, multi-hop reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the name KoshurLock Holmes
&lt;/h2&gt;

&lt;p&gt;Koshur is what we call the Kashmiri language back home. So the name is exactly what it sounds like: Sherlock Holmes, but ours. A detective from Kashmir.&lt;/p&gt;

&lt;p&gt;And the Holmes part is not decoration. The whole product behaves like a detective. It remembers evidence. It recalls answers with citations. You can teach it a confirmed finding. And, this is the part I am most proud of, you can make it forget a planted false clue, and watch the wrong conclusion collapse.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually does
&lt;/h2&gt;

&lt;p&gt;You upload evidence files (CSV, TXT, PDF, DOCX). The backend parses each one, wraps it with a provenance header, and feeds it through Cognee, which extracts entities and relationships and builds a typed knowledge graph. The same person appearing in the VPN log and the badge log resolves to one shared node.&lt;/p&gt;

&lt;p&gt;On top of that graph sit four operations that map to Cognee's memory lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remember&lt;/strong&gt;: ingest each source and build the graph&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recall&lt;/strong&gt;: ask a question in plain English, get a cited multi-hop answer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve&lt;/strong&gt;: teach it a confirmed analyst finding so the graph reweights&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forget&lt;/strong&gt;: surgically remove a discredited source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The UI is a security operations console: a full interactive Cytoscape knowledge graph where entity types have their own shapes and colors, a dense filterable timeline built from the log timestamps, an investigation console with expandable raw log citations, and a before-and-after view we call The Turn.&lt;/p&gt;

&lt;h2&gt;
  
  
  The demo case: a man who was framed
&lt;/h2&gt;

&lt;p&gt;To show what the system can do, we wrote a full fictional incident: the Northgate Financial case.&lt;/p&gt;

&lt;p&gt;An employee named Rahul Sharma is framed. On the night of 30 June, someone logs into his account from a foreign IP, 41.220.13.7, out of Lagos. That session downloads the customer database and a PII export and emails them to an external Gmail address. An anonymous tip lands the same week, accusing Rahul directly.&lt;/p&gt;

&lt;p&gt;Every log says Rahul did it. Except two: the badge reader and the CCTV both place him physically inside the office at the exact time of the 2 AM foreign login. And a few days earlier, his credentials were phished.&lt;/p&gt;

&lt;p&gt;Here is The Turn, live in the app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask "who is responsible?" With all evidence present, including the planted tip, the answer implicates Rahul.&lt;/li&gt;
&lt;li&gt;Teach the confirmed SOC finding: the foreign IP is a known attacker, the credentials were phished, this was an account takeover.&lt;/li&gt;
&lt;li&gt;Forget the anonymous tip.&lt;/li&gt;
&lt;li&gt;Ask again. The conclusion re-derives. Rahul is exonerated, and the system names the external attacker at 41.220.13.7, because the takeover explanation plus the physical alibi make his guilt impossible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Watching a wrong verdict flip to the right one in front of you never gets old. We also validated the same pipeline on a separate uploaded case, where it correctly identified the true insider and cleared a wrongly accused employee who was on leave.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture decision that shaped everything
&lt;/h2&gt;

&lt;p&gt;Before writing application code we faced a fork in the road.&lt;/p&gt;

&lt;p&gt;Option A: the default AI stack. OpenAI for the LLM, a hosted vector database, a separate graph database, paid embeddings. Three or four services, three or four bills, and your evidence leaves your machine.&lt;/p&gt;

&lt;p&gt;Option B: make the entire thing free and self-hosted. Groq's free tier for the LLM, embeddings computed locally with FastEmbed, and every kind of storage crammed into one PostgreSQL instance.&lt;/p&gt;

&lt;p&gt;We picked B, and it turned out Cognee has a mode built for exactly this. One env var:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;USE_UNIFIED_PROVIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pghybrid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That puts the relational data, the pgvector index, and the knowledge graph in the same Postgres. One service to run. One &lt;code&gt;pg_dump&lt;/code&gt; backs up the entire memory of the investigator. This single decision saved us later in a way I could not have predicted (more on that in the deployment war story).&lt;/p&gt;

&lt;p&gt;We were so serious about the no-OpenAI promise that the backend refuses to boot if it detects any path that could route there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY is present in the environment - unset it so &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cognee cannot fall back to OpenAI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A hard fail at startup. Paranoid? Yes. Justified? Also yes, as you are about to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  The quirks that ate my nights
&lt;/h2&gt;

&lt;p&gt;Every tool has sharp edges you only find at 1 AM. Here are the ones that got me, written down so they do not get you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The silent OpenAI fallback.&lt;/strong&gt; If you use local FastEmbed embeddings with Cognee, you must set the dimensions explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;EMBEDDING_PROVIDER&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;fastembed&lt;/span&gt;
&lt;span class="py"&gt;EMBEDDING_MODEL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sentence-transformers/all-MiniLM-L6-v2&lt;/span&gt;
&lt;span class="py"&gt;EMBEDDING_DIMENSIONS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;384&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave &lt;code&gt;EMBEDDING_DIMENSIONS&lt;/code&gt; unset and Cognee quietly defaults to 3072, which is an OpenAI dimension, and quietly tries to go there. No error. Just wrong behavior you discover much later. This one line is why our startup guard exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;json_mode, not json_schema.&lt;/strong&gt; Groq's Llama models mangle the structured tool-call path, and cognify aborts halfway with confusing errors. Plain &lt;code&gt;LLM_INSTRUCTOR_MODE=json_mode&lt;/code&gt; works. Hours of my life are in that one setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access control that empties your graph.&lt;/strong&gt; Cognee's multi-user access control partitions the graph per tenant. Sounds fine, until your node counts read zero and cross-source reasoning falls apart because everything landed in different partitions. For a single-analyst tool: &lt;code&gt;ENABLE_BACKEND_ACCESS_CONTROL=false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 100,000 token wall.&lt;/strong&gt; Groq's free tier gives you 100k tokens per day, and a full ingest of our eight evidence files eats almost exactly that. Run the seed twice in a day and the second run dies mid-graph. Our fix became a core feature: seed once, then &lt;code&gt;pg_dump&lt;/code&gt; the whole built graph into a snapshot. Every boot after that restores warm, with zero LLM calls. The demo never spends tokens again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment day, or, the longest night of my life
&lt;/h2&gt;

&lt;p&gt;Everything worked locally. Then I tried to put it on the internet, and the internet fought back.&lt;/p&gt;

&lt;p&gt;Railway does not run a docker-compose file, so the one-command stack became three separate services wired together by hand. The frontend crashed on arrival:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;nginx:&lt;/span&gt; &lt;span class="s"&gt;[emerg]&lt;/span&gt; &lt;span class="s"&gt;host&lt;/span&gt; &lt;span class="s"&gt;not&lt;/span&gt; &lt;span class="s"&gt;found&lt;/span&gt; &lt;span class="s"&gt;in&lt;/span&gt; &lt;span class="s"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;"backend"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Locally, nginx proxies to a container literally named &lt;code&gt;backend&lt;/code&gt;. On Railway there is no such name. And here is the trap: hardcode the Railway internal hostname and your local setup breaks instead. The same config file cannot serve both. The fix was turning nginx.conf into a template that reads the upstream from an environment variable at container start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; $&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;BACKEND_ORIGIN&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Locally it defaults to &lt;code&gt;http://backend:8000&lt;/code&gt;. On Railway a service variable points it at the internal address. One image, both worlds.&lt;/p&gt;

&lt;p&gt;Then came the domain confusion that nearly finished me. Railway generated &lt;code&gt;koshurlockholmes.up.railway.app&lt;/code&gt; for the backend and &lt;code&gt;koshurlock-holmes.up.railway.app&lt;/code&gt; for the frontend. One hyphen apart. At 5 AM, running on no sleep, I pointed the frontend at itself and spent an hour debugging a loop of my own making. If you take one thing from this post: name your services something you cannot confuse at 5 AM.&lt;/p&gt;

&lt;p&gt;And the best trick of the night, the one that saved the demo: the server graph was empty and I had no quota left to re-seed it. But remember, the entire memory lives in one Postgres. So I took the snapshot from my laptop and restored it straight into Railway's database over the public connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pg_restore &lt;span class="nt"&gt;--clean&lt;/span&gt; &lt;span class="nt"&gt;--if-exists&lt;/span&gt; &lt;span class="nt"&gt;--no-owner&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RAILWAY_DATABASE_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  scripts/snapshots/cognee_db.dump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ninety five nodes and 279 edges appeared on the server in about ten seconds. Zero tokens spent. That is the one-Postgres decision from day one paying for itself at the worst possible hour. I nearly cried.&lt;/p&gt;

&lt;p&gt;One last bug: every backend restart reset the demo state, so the case kept showing "snapshot not found" after each redeploy. The fix was making the backend restore the snapshot on every startup instead of only on a cold, empty graph. A few lines in the FastAPI lifespan, and restarts stopped being scary.&lt;/p&gt;

&lt;p&gt;At 7 AM the full flow finally ran clean on the live link. Demo case loads warm. The Turn flips the verdict. Uploads ingest. I sat back in my chair and just breathed. I had not eaten since the previous afternoon. I did not care.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually learned
&lt;/h2&gt;

&lt;p&gt;I keep coming back to one thought.&lt;/p&gt;

&lt;p&gt;A project like this, at this scope, should take three to six months. A knowledge graph engine, a live investigation console, a forensics timeline, a retraction system, self-hosted deployment. Months. We built it in hackathon hours, and I finally understand why people keep doing these things to themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hackathon effect is real. The pressure, the curiosity, the excitement compress months of work into days, and you come out the other side a different engineer than you went in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I learned more about Postgres, nginx, LLM rate limits, and my own stubbornness in one sleepless night than in weeks of normal work.&lt;/p&gt;

&lt;p&gt;Huge thanks to WeMakeDevs for running this. After two of their hackathons, one skeptical entry and one free Claude Max subscription later, I can say it plainly: these are the best hackathons I have taken part in, and they actually deliver.&lt;/p&gt;

&lt;p&gt;KoshurLock Holmes is open source under MIT. The repo has the full docs, the Northgate case spec, and everything you need to run it with one docker compose command and a free Groq key. If you try it, break it, or want to talk about the architecture, find me on GitHub.&lt;/p&gt;

&lt;p&gt;The evidence was always there. We just built the detective.&lt;/p&gt;

&lt;p&gt;Team: Mehraan Amin (Mehru), Aqib Javid Bhat, Ubaid Mushtaq. Built with Cognee, Groq, FastEmbed, PostgreSQL + pgvector, FastAPI, React, and Cytoscape.js.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>database</category>
      <category>cybersecurity</category>
      <category>startup</category>
    </item>
    <item>
      <title>How I Built CoralSec Copilot: A Unified Enterprise SOC with Coral &amp; Next.js in 4 Days</title>
      <dc:creator>MEHRAAN AMIN</dc:creator>
      <pubDate>Sat, 30 May 2026 06:10:46 +0000</pubDate>
      <link>https://dev.to/codewithmehru/how-i-built-coralsec-copilot-a-unified-enterprise-soc-with-coral-nextjs-in-4-days-235o</link>
      <guid>https://dev.to/codewithmehru/how-i-built-coralsec-copilot-a-unified-enterprise-soc-with-coral-nextjs-in-4-days-235o</guid>
      <description>&lt;p&gt;&lt;strong&gt;The tech industry is currently in a frenzy. Everyone is rushing to build the next big AI application, slapping a chatbot interface onto a database and calling it a day. But in this gold rush, we are leaving something critical behind: Enterprise Security.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Living in a Kali Linux environment and spending time hunting vulnerabilities teaches you one fundamental truth: security is entirely about context. Hardcoded API keys, undocumented access escalations, and compliance blind spots remain the number one cause of major data breaches. Security teams don’t just need a chatbot that can answer questions; they need a single pane of glass. They need a Security Operations Center (SOC).&lt;/p&gt;

&lt;p&gt;For the Pirates of the Coral-Bean Hackathon (hosted by Coral and WeMakeDevs), I decided to tackle this massive industry problem. Over the course of 4 sleepless nights, I built CoralSec Copilot—an AI-powered, unified Enterprise SOC platform.&lt;/p&gt;

&lt;p&gt;Here is the complete Captain's Log of my entire journey, the architecture, the roadblocks, and a reproducible guide so you can build and run it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 1: The Brainstorm, Grok, and Cursor AI
&lt;/h2&gt;

&lt;p&gt;When the hackathon was announced, my initial thought was basic: "I'll build a CLI agent that scans code." I fired up my IDE, opened Cursor, and started bouncing ideas around. I even looked into some AI models like Grok to understand how they process vast amounts of real-time data.&lt;/p&gt;

&lt;p&gt;But while brainstorming the architecture, I hit a wall. Scanning a GitHub commit for a leaked AWS key is great, but what if the AI also knew whether the developer who pushed that commit had recently escalated their admin privileges? What if it knew the exact SOC2 compliance policy from our company’s Notion workspace?&lt;/p&gt;

&lt;p&gt;To do this traditionally, I would have to write dozens of messy REST API integrations. I'd have to handle rate limits, write custom Python scripts for GitHub, another set for Slack, another for Notion, and then build fragile ETL (Extract, Transform, Load) pipelines to bring all that data together.&lt;/p&gt;

&lt;p&gt;It sounded like an absolute nightmare for a 4-day sprint. I needed a way to unify data without writing thousands of lines of glue code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 2: The Magic of Coral MCP &amp;amp; Cross-Source SQL
&lt;/h2&gt;

&lt;p&gt;This is where the Coral Protocol stepped in and completely changed my development trajectory.&lt;/p&gt;

&lt;p&gt;Coral Protocol is not just a database wrapper; it is a unified data intelligence hub. It allowed me to replace all that custom glue code with read-only, cross-source SQL. By integrating the Coral Model Context Protocol (MCP), I gave my AI agent the ability to write a single query with LEFT JOIN semantics across entirely different platforms.&lt;/p&gt;

&lt;p&gt;Instead of writing five different Python scripts to fetch data, my agent can now execute something conceptually like this under the hood:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[[Note for Mehru: Use the code block button in Dev.to for the SQL below]&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="nv"&gt;`SELECT
github.cve_id,
slack.incident_channel,
notion.compliance_policy
FROM github_dependabot AS github
LEFT JOIN slack_channels AS slack ON slack.topic = github.cve_id
LEFT JOIN notion_pages AS notion ON notion.tags = 'SOC2'
WHERE github.state = 'open';`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;[End Note]]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a first-time Coral user, shifting my mindset from writing complex backend logic to simply leveraging Coral’s SQL interface for cross-platform joins was mind-blowing. It completely eliminated the data silos. My AI agent could now correlate a GitHub Dependabot vulnerability, an active Slack security channel, and an internal Notion compliance policy in a single execution path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 3: Giving the AI Brain a Body (Next.js Dashboard)
&lt;/h2&gt;

&lt;p&gt;An AI brain is incredibly powerful, but IT admins and security operators need a visual dashboard to monitor threats continuously. They can't just type prompts all day. I spent the third day wrapping my Coral-powered engine into a persistent Enterprise UI.&lt;/p&gt;

&lt;p&gt;Using Next.js 15, Tailwind CSS, and shadcn/ui, I built a 4-module dashboard to act as a single pane of glass:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Global Risk Dashboard&lt;br&gt;
This isn't just a static page. It calculates a dynamic risk score based on aggregated posture signals pulled live from the APIs. It gives security teams a bird's-eye view of their infrastructure's health.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secret Scanner&lt;br&gt;
Visualizes leaked Personal Access Tokens (PATs) and AWS keys from commit pipelines. It flags critical misconfigurations the moment they happen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vulnerability Intelligence&lt;br&gt;
An interactive tracker for OSV and CVE data aligned with Dependabot. It breaks down threats by severity, highlighting things like OpenSSL buffer over-reads or prototype pollution in lodash.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compliance Monitor&lt;br&gt;
A live ledger that directly compares GitHub admin access against Notion SOC2 policy pages. If someone gets unauthorized admin access on GitHub, the dashboard flags it against the company policy instantly.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Day 4: Resiliency, Python Fallbacks, and The Cybersecurity Mindset
&lt;/h2&gt;

&lt;p&gt;What happens if the cloud alert tables are entirely empty? A security tool cannot just fail silently. I needed this platform to be bulletproof.&lt;/p&gt;

&lt;p&gt;To achieve this, I built a resilient Python and LangChain scanner as a fallback. If the primary cloud scans return empty, the system triggers zero-day commit parsing. It uses structured tool calls to parse local commit diffs and surface historical leak patterns before they hit production.&lt;/p&gt;

&lt;p&gt;I also engineered bulletproof API pushdowns. I structured the SQL so that queries like Dependabot use exact states (e.g., state = 'open' OR state IS NULL). This ensures that if a third-party API returns a null severity, my dashboard doesn't accidentally drop a valid open alert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Sandbox Deployment Decision&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When it came time to deploy, I faced a serious dilemma. I wanted the hackathon judges and the community to experience the beautiful Next.js UI. However, as a cybersecurity researcher, I strictly follow security best practices.&lt;/p&gt;

&lt;p&gt;Exposing my active Personal Access Tokens (GitHub, Slack, Notion) on a public Vercel domain was an absolute no-go. It defeats the entire purpose of building a security tool.&lt;/p&gt;

&lt;p&gt;So, I deployed the live link as an interactive Sandbox / Demo Mode. By adding a simple environment variable, the app renders a safe UI where anyone can explore the UX and the AI agent's frontend flow safely without exposing real company data. But to experience the real-time scanning engine, developers must clone the repo and run it locally with their own keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Charting the Course: Build Your Own CoralSec Copilot
&lt;/h2&gt;

&lt;p&gt;If you want to run this Enterprise SOC on your own company's repositories, here is the exact reproducible route to get the real-time scanning engine fired up on your local machine.&lt;/p&gt;

&lt;p&gt;Prerequisites:&lt;br&gt;
You will need two terminal windows to run the Next.js UI and the Coral MCP Engine simultaneously.&lt;/p&gt;

&lt;p&gt;Step 1: Setup Environment&lt;br&gt;
Clone the repository and set up your environment variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;Note &lt;span class="k"&gt;for &lt;/span&gt;Mehru: Use the code block button &lt;span class="k"&gt;in &lt;/span&gt;Dev.to &lt;span class="k"&gt;for &lt;/span&gt;the bash commands below]
git clone https://github.com/CodeWithMehru/coral-security-copilot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;coral-security-copilot
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;span class="o"&gt;[&lt;/span&gt;End Note]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the .env file and insert your GitHub, Notion, and Slack tokens. Make sure to set CORALSEC_USE_DEMO=false so you exit the Sandbox and run the live engine!&lt;/p&gt;

&lt;p&gt;Step 2: Start Coral Engine&lt;br&gt;
Open your first terminal in the root directory and start the Coral Studio:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[Note for Mehru: Use the code block button in Dev.to for the bash command below]&lt;br&gt;
coral mcp studio&lt;br&gt;
[End Note]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Step 3: Start the Next.js Frontend&lt;br&gt;
Open a second terminal, install the dependencies, and start the development server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;Note &lt;span class="k"&gt;for &lt;/span&gt;Mehru: Use the code block button &lt;span class="k"&gt;in &lt;/span&gt;Dev.to &lt;span class="k"&gt;for &lt;/span&gt;the bash &lt;span class="nb"&gt;command &lt;/span&gt;below]
&lt;span class="nb"&gt;cd &lt;/span&gt;frontend
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;span class="o"&gt;[&lt;/span&gt;End Note]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open localhost:3000 in your browser to view the live dashboard. You now have a fully functional, AI-powered Enterprise Security Operations Center running on your local machine!&lt;br&gt;
Final Thoughts&lt;/p&gt;

&lt;p&gt;Building CoralSec Copilot was an absolute masterclass in data correlation. Coral eliminated the most painful parts of API integration and allowed me to focus entirely on building a robust, intelligent security product.&lt;/p&gt;

&lt;p&gt;A massive thank you to Coral and WeMakeDevs for hosting this hackathon. It challenged me to push my boundaries as a full-stack developer and a security researcher. The voyage was long, the code was complex, but the final plunder was absolutely worth it!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
