feat: add FalkorDB chatbot graph package#5116
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Confidence Score: 5/5Safe to merge as a prototype feature; no correctness defects on the happy path. The new package is well-tested with a mock client, the API endpoint uses auth guards and Zod validation, and the snapshot parsing is defensive throughout. The two findings are scoped to prototype scaffolding that won't break existing functionality. apps/chat/src/lib/graph/flow.ts — the getRootNode fallback on label 'finance' should be removed before non-Finance chatbot graphs are introduced.
|
| Filename | Overview |
|---|---|
| packages/falkordb/src/index.ts | Core FalkorDB package: UUID validation, client creation, graph lifecycle, and snapshot parsing. Well-structured with good test coverage. Some hardcoded behaviours flagged in previous threads. |
| apps/chat/src/app/api/chatbots/[chatbotId]/graph/route.ts | New GET endpoint for graph snapshots with auth guard, Zod input validation, and differentiated error handling for missing FalkorDB config. Clean implementation. |
| apps/chat/src/lib/graph/flow.ts | Converts FalkorDB snapshot to React Flow nodes/edges with radial layout. Contains a prototype-specific 'finance' label fallback in getRootNode that will produce incorrect layout for future non-Finance graphs. |
| apps/chat/src/components/chatbot-graph-drawer.tsx | Side-drawer UI with React Flow graph rendering, node selection, and detail panel. Two action buttons in the concept detail panel lack onClick handlers. |
| apps/chat/test/graph-flow.test.ts | Good unit tests covering hierarchy layout, edge filtering, selection dimming, and focus-edge reveal. |
| packages/falkordb/test/index.test.ts | Comprehensive unit tests with mock FalkorDB client covering config loading, graph lifecycle, snapshot normalisation, truncation, and seed logic. |
Sequence Diagram
sequenceDiagram
participant Browser as Browser (ChatbotGraphDrawer)
participant API as /api/chatbots/[id]/graph
participant Guard as withChatbotAuth
participant Pkg as @klicker-uzh/falkordb
participant FDB as FalkorDB (Redis protocol)
Browser->>API: "GET /api/chatbots/{chatbotId}/graph?nodeLimit=100&edgeLimit=150"
API->>Guard: withChatbotAuth(req, chatbotId)
Guard-->>API: auth context or 401/403
API->>Pkg: "getChatbotGraphSnapshot({ chatbotId, nodeLimit, edgeLimit })"
Pkg->>FDB: "GRAPH.RO_QUERY klickeruzh:chatbot:{id} MATCH (n) RETURN n LIMIT 101"
FDB-->>Pkg: raw node rows
Pkg->>FDB: "GRAPH.RO_QUERY klickeruzh:chatbot:{id} MATCH ()-[r]->() RETURN r LIMIT 151"
FDB-->>Pkg: raw edge rows
Pkg-->>API: "ChatbotGraphSnapshot { nodes, edges, truncated, limits }"
API-->>Browser: 200 JSON snapshot
Browser->>Browser: "mapGraphSnapshotToFlow(snapshot, { selectedNodeId })"
Browser->>Browser: render ReactFlow with radial layout
Reviews (2): Last reviewed commit: "chore: add sidebar component for the cha..." | Re-trigger Greptile
| export async function readChatbotGraph( | ||
| args: ChatbotGraphQueryArgs | ||
| ): Promise<unknown> { | ||
| const graphName = getChatbotGraphName(args.chatbotId) | ||
| const query = requireQuery(args.query) | ||
|
|
||
| return await withFalkorDBClient(args.client, async (client) => { | ||
| return await client.call('GRAPH.RO_QUERY', graphName, query) | ||
| }) | ||
| } | ||
|
|
||
| export async function writeChatbotGraph( | ||
| args: ChatbotGraphQueryArgs | ||
| ): Promise<unknown> { | ||
| const graphName = getChatbotGraphName(args.chatbotId) | ||
| const query = requireQuery(args.query) | ||
|
|
||
| return await withFalkorDBClient(args.client, async (client) => { | ||
| return await client.call('GRAPH.QUERY', graphName, query) | ||
| }) |
There was a problem hiding this comment.
No parameterized-query support exposes callers to Cypher injection
writeChatbotGraph and readChatbotGraph pass raw query strings straight to GRAPH.QUERY / GRAPH.RO_QUERY. The FalkorDB Redis protocol supports parameterized queries by appending PARAMS <count> <key> <value>… arguments after the query string, but the current API surface (query: string only) provides no way for callers to use them. Any future call site that builds the query string from user-provided data — e.g., a document title, username, or search term — will be vulnerable to Cypher injection without any mitigation path in this package. Consider adding a params?: Record<string, string> field to ChatbotGraphQueryArgs and serialising it into the PARAMS … arguments of the underlying client.call invocation.
| function createGraphMetadataQuery(chatbotId: string): string { | ||
| // TODO: Upload course/chatbot source data into this graph once the ingestion | ||
| // pipeline is available for chatbot-specific knowledge graphs. | ||
| return ( | ||
| 'MERGE (:GraphMetadata {' + | ||
| 'managedBy: "klickeruzh", ' + | ||
| 'resource: "chatbot", ' + | ||
| `chatbotId: "${chatbotId}"` + | ||
| '}) RETURN 1' | ||
| ) | ||
| } |
There was a problem hiding this comment.
createGraphMetadataQuery embeds chatbotId directly into a Cypher string literal. It is only safe because getChatbotGraphName happens to validate the UUID first, but that upstream guard is not enforced at the call site. A future refactor that calls it independently, or reorders the steps, silently removes the protection.
| function createGraphMetadataQuery(chatbotId: string): string { | |
| // TODO: Upload course/chatbot source data into this graph once the ingestion | |
| // pipeline is available for chatbot-specific knowledge graphs. | |
| return ( | |
| 'MERGE (:GraphMetadata {' + | |
| 'managedBy: "klickeruzh", ' + | |
| 'resource: "chatbot", ' + | |
| `chatbotId: "${chatbotId}"` + | |
| '}) RETURN 1' | |
| ) | |
| } | |
| function createGraphMetadataQuery(chatbotId: string): string { | |
| if (!UUID_PATTERN.test(chatbotId)) { | |
| throw new Error('chatbotId must be a valid UUID') | |
| } | |
| // TODO: Upload course/chatbot source data into this graph once the ingestion | |
| // pipeline is available for chatbot-specific knowledge graphs. | |
| return ( | |
| 'MERGE (:GraphMetadata {' + | |
| 'managedBy: "klickeruzh", ' + | |
| 'resource: "chatbot", ' + | |
| `chatbotId: "${chatbotId}"` + | |
| '}) RETURN 1' | |
| ) | |
| } |
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 33932487 | Triggered | Generic Password | df80713 | apps/chat/.env.local.example | View secret |
| 33932487 | Triggered | Generic Password | df80713 | packages/falkordb/src/seed-prototype-finance.ts | View secret |
| 33932487 | Triggered | Generic Password | df80713 | apps/chat/.env.development | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secrets safely. Learn here the best practices.
- Revoke and rotate these secrets.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
Summary
Adds a FalkorDB-backed prototype knowledge graph for chatbots, including local Docker Compose support, a new
@klicker-uzh/falkordbpackage, graph lifecycle helpers, Benibot finance seed data, and a guarded chat API route for reading graph snapshots.The chat UI now includes an optional knowledge graph drawer using React Flow, with hierarchy layout, node details, relation highlighting, legends, and corrected layering above the message composer. The prototype graph data was refined to include meaningful finance-topic relations, and selection behavior now only highlights visibly connected relationships.
Screenshots
ClickUp Links