From b3beda7d0c02d09ab4c39e9010e4bdf29a35cf1b Mon Sep 17 00:00:00 2001 From: Boris Filipov Date: Thu, 26 Mar 2026 15:28:39 +0200 Subject: [PATCH 1/2] fix: enforce workspace scoping for chat fact citations Prevent chat responses from leaking cross-workspace fact content by validating every cited fact against the active workspace before returning it to the UI. Made-with: Cursor --- apps/webapp/server/trpc/routes/chat.ts | 6 +++++- docs/SPEC.md | 8 +++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/webapp/server/trpc/routes/chat.ts b/apps/webapp/server/trpc/routes/chat.ts index e6d1445..42378cb 100644 --- a/apps/webapp/server/trpc/routes/chat.ts +++ b/apps/webapp/server/trpc/routes/chat.ts @@ -200,7 +200,11 @@ Example response: usedFactIds.map(async (factId) => { try { const fact = await Fact.findById(factId); - if (fact && !fact.trashed) { + if ( + fact && + !fact.trashed && + fact.workspace_id === ctx.workspaceId + ) { return { id: fact.id, content: fact.content, diff --git a/docs/SPEC.md b/docs/SPEC.md index abdae48..917b5f1 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -1911,9 +1911,10 @@ KnowledgePlane includes an AI chat interface that combines OpenAI's language mod 7. AI generates a response using both its training and the knowledge base facts accessed via MCP tools 8. AI returns JSON response with `content` (the response text) and `usedFacts` (array of fact IDs actually used) 9. System parses the JSON response and fetches the actual fact objects by IDs -10. Assistant response content is stored in the thread -11. Response is displayed with information about which facts were actually used to construct the response -12. When the user switches workspaces, the chat automatically uses the new workspace's context for subsequent MCP operations +10. System enforces a workspace boundary check (`fact.workspace_id === current workspace`) before returning cited facts +11. Assistant response content is stored in the thread +12. Response is displayed with information about which facts were actually used to construct the response +13. When the user switches workspaces, the chat automatically uses the new workspace's context for subsequent MCP operations **Thread Management:** - Each user automatically gets a thread per workspace that persists across sessions @@ -1950,6 +1951,7 @@ The chat interface automatically: - Uses MCP tools to give the AI model direct access to the knowledge base - Tracks which facts were actually used by the AI model (not just searched) - Returns only the facts that were actually used to construct the response +- Enforces server-side workspace scoping for cited facts, even if the model returns arbitrary fact IDs **MCP Integration:** - The chat interface uses OpenAI's MCP (Model Context Protocol) tools feature From 76c58691e6557cc43ef18b9d43449945de8fedfe Mon Sep 17 00:00:00 2001 From: Boris Filipov Date: Thu, 26 Mar 2026 15:36:35 +0200 Subject: [PATCH 2/2] chore: ignore production env file locally Ignore `.env.production` in git to prevent accidental commits of production database credentials from local development environments. Made-with: Cursor --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3a05687..da46f92 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ node_modules .env .env.local .env.dev +.env.production packages/db/dist apps/mcp-server/dist coverage