AI-Powered Security Pull Request Reviewer

70291eb8-f8da-4019-8914-1280ef8bd045

Latency
4906ms
Cost
$0.0020
Tokens
1,313
Status
success
gemini-3-flash-preview

Workflow Graph

Trace

[
  {
    "data": {
      "nodeType": "manualTrigger"
    },
    "event": "node_start",
    "nodeId": "n0",
    "timestamp": 1783205632451
  },
  {
    "data": {
      "initialData": {
        "diff": "diff --git a/src/utils/auth.js b/src/utils/auth.js\nindex 1234567..abcdef0 100644\n--- a/src/utils/auth.js\n+++ b/src/utils/auth.js\n@@ -1,5 +1,6 @@\n import jwt from 'jsonwebtoken';\n \n+const JWT_SECRET = process.env.JWT_SECRET || 'supersecretkey'; // In production, use a strong, environment-specific secret\n const EXPIRATION_TIME = '1h';\n \n export const generateToken = (userId) => {\n@@ -10,7 +11,7 @@\n };\n \n export const verifyToken = (token) => {\n-  try {\n-    return jwt.verify(token, process.env.JWT_SECRET);\n+  if (!token) {\n+    throw new Error('No token provided');\n+  }\n+  try {\n+    return jwt.verify(token, JWT_SECRET);\n   } catch (error) {\n     console.error('Token verification failed:', error.message);\n     return null;\n@@ -20,3 +21,11 @@\n     return null;\n   }\n };\n+\n+export const decodeToken = (token) => {\n+  if (!token) {\n+    throw new Error('No token provided');\n+  }\n+  return jwt.decode(token);\n+};\n+\ndiff --git a/src/services/userService.js b/src/services/userService.js\nindex abcdef0..1234567 100644\n--- a/src/services/userService.js\n+++ b/src/services/userService.js\n@@ -1,5 +1,6 @@\n import User from '../models/User';\n import bcrypt from 'bcryptjs';\n+import { decodeToken } from '../utils/auth';\n \n export const createUser = async (userData) => {\n   const hashedPassword = await bcrypt.hash(userData.password, 10);\n@@ -18,3 +19,11 @@\n   return user;\n };\n \n+export const getUserFromToken = async (token) => {\n+  const decoded = decodeToken(token);\n+  if (!decoded || !decoded.userId) {\n+    throw new Error('Invalid token payload');\n+  }\n+  const user = await User.findById(decoded.userId);\n+  return user;\n+};\n+\n"
      }
    },
    "event": "triggered",
    "nodeId": "manualTrigger",
    "timestamp": 1783205632451
  },
  {
    "data": {
      "status": "ok",
      "nodeType": "manualTrigger"
    },
    "event": "node_end",
    "nodeId": "n0",
    "timestamp": 1783205632451
  },
  {
    "data": {
      "nodeType": "llm"
    },
    "event": "node_start",
    "nodeId": "n1",
    "timestamp": 1783205632454
  },
  {
    "data": {
      "messages": 2,
      "maxTokens": 250
    },
    "event": "calling openai/gpt-4o-mini",
    "nodeId": "llm",
    "timestamp": 1783205632454
  },
  {
    "data": {
      "model": "gpt-4o-mini",
      "provider": "openai"
    },
    "event": "llm_call",
    "nodeId": "_context",
    "timestamp": 1783205632454
  },
  {
    "data": {
      "model": "gemini-3-flash-preview",
      "costUsd": 0.0019735,
      "provider": "openai",
      "latencyMs": 4902,
      "promptTokens": 595,
      "completionTokens": 718
    },
    "event": "llm_result",
    "nodeId": "_context",
    "timestamp": 1783205637357
  },
  {
    "data": {
      "status": "ok",
      "nodeType": "llm"
    },
    "event": "node_end",
    "nodeId": "n1",
    "timestamp": 1783205637357
  }
]