|
| 1 | +# Knowledge Base Catalog v1 (Native-First, Pipeline-Integrated) |
| 2 | + |
| 3 | +## Summary |
| 4 | +Build a native Klicker knowledge-base catalog in the existing stack, with owner-only access in v1, manual ingestion triggers, pipeline-owned refresh execution, and many-to-many KB-chatbot schema while enforcing one active KB per chatbot at runtime. |
| 5 | + |
| 6 | +Also include a documented "adapt external tool" track, but not as the primary v1 path. |
| 7 | + |
| 8 | +## Locked Decisions |
| 9 | +1. Build strategy: native-first in Klicker, while documenting external-tool variants. |
| 10 | +2. Access control v1: owner-only. |
| 11 | +3. Entry input v1: URL entries (website URL, PDF/blob URL) plus inline text entries; no direct PDF upload yet. |
| 12 | +4. Ingestion trigger v1: manual only. |
| 13 | +5. Monitoring model: entry-level refresh policy only; websites support `DAILY|WEEKLY|MONTHLY|YEARLY`, PDF/text use `NONE`. |
| 14 | +6. KB-chatbot data model: many-to-many. |
| 15 | +7. Runtime behavior v1: max one active KB per chatbot. |
| 16 | +8. Milvus collection ID ownership: Klicker defines immutable UUID per KB. |
| 17 | +9. Ingestion status tracking: pipeline callback webhook to Klicker. |
| 18 | + |
| 19 | +## Implementation Plan |
| 20 | + |
| 21 | +### 1. Data Model (Prisma) |
| 22 | +1. Add `KnowledgeBase` model in `packages/prisma/src/prisma/schema/`. |
| 23 | +2. Add `KnowledgeBaseEntry` model. |
| 24 | +3. Add join model `ChatbotKnowledgeBase`. |
| 25 | +4. Add `KnowledgeBaseSyncJob` model. |
| 26 | +5. Extend `User` and `Chatbot` relations in: |
| 27 | + - `packages/prisma/src/prisma/schema/user.prisma` |
| 28 | + - `packages/prisma/src/prisma/schema/chat.prisma` |
| 29 | + |
| 30 | +### 2. GraphQL API (Backend) |
| 31 | +1. Add new GraphQL resource types in `packages/graphql/src/schema/resource.ts`: |
| 32 | + - `KnowledgeBase`, `KnowledgeBaseEntry`, `KnowledgeBaseSyncJob`, related enums. |
| 33 | +2. Add query fields in `packages/graphql/src/schema/query.ts`: |
| 34 | + - `getKnowledgeBases` |
| 35 | + - `getKnowledgeBase(id)` |
| 36 | + - `getKnowledgeBaseEntries(knowledgeBaseId)` |
| 37 | + - `getKnowledgeBaseSyncJobs(knowledgeBaseId, limit, cursor?)` |
| 38 | +3. Add mutation fields in `packages/graphql/src/schema/mutation.ts`: |
| 39 | + - `createKnowledgeBase`, `updateKnowledgeBase`, `deleteKnowledgeBase` |
| 40 | + - `createKnowledgeBaseEntry`, `updateKnowledgeBaseEntry`, `deleteKnowledgeBaseEntry` |
| 41 | + - `attachKnowledgeBaseToChatbot`, `detachKnowledgeBaseFromChatbot`, `setActiveKnowledgeBaseForChatbot` |
| 42 | + - `triggerKnowledgeBaseSync(knowledgeBaseId, entryId?)` |
| 43 | +4. Add service layer in `packages/graphql/src/services/knowledgeBases.ts`: |
| 44 | + - owner-only guards. |
| 45 | + - entry validation rules. |
| 46 | + - manual trigger only; create sync job row then call pipeline webhook. |
| 47 | +5. Add GraphQL ops files in `packages/graphql/src/graphql/ops/` and regenerate artifacts in implementation phase. |
| 48 | + |
| 49 | +### 3. Pipeline Integration Contract |
| 50 | +1. Outbound trigger from GraphQL service: |
| 51 | + - `POST ${KB_PIPELINE_TRIGGER_URL}`. |
| 52 | + - Payload includes `eventId`, `jobId`, `knowledgeBaseId`, `collectionId`, `entryId`, `entryType`, `source`, `refreshInterval`, `requestedBy`. |
| 53 | + - Signed header `X-Klicker-Signature` using HMAC SHA-256 and `KB_PIPELINE_TRIGGER_SECRET`. |
| 54 | +2. Inbound callback endpoint in backend app: |
| 55 | + - Add express route in `apps/backend-docker/src/app.ts`: |
| 56 | + - `POST /api/webhooks/knowledge-base-sync`. |
| 57 | + - Verify HMAC via `KB_PIPELINE_CALLBACK_SECRET`. |
| 58 | + - Idempotent upsert by `eventId`. |
| 59 | + - Update `KnowledgeBaseSyncJob` and denormalized entry sync state. |
| 60 | +3. Callback payload (required fields): |
| 61 | + - `eventId`, `jobId`, `status`, `knowledgeBaseId`, optional `entryId`, optional `error`, optional `stats`. |
| 62 | +4. Failure handling: |
| 63 | + - Invalid signature: `401`. |
| 64 | + - Unknown `jobId` with known `eventId`: idempotent `200`. |
| 65 | + - Unknown `jobId` and unknown `eventId`: `404` + structured error log. |
| 66 | + |
| 67 | +### 4. Chat Runtime Integration |
| 68 | +1. Keep MCP/RAG architecture intact; only add active KB context. |
| 69 | +2. In `apps/chat/src/app/api/chatbots/[chatbotId]/chat/route.ts`: |
| 70 | + - Load active KB attachment and collection ID. |
| 71 | + - Pass collection ID as additional request header for MCP calls. |
| 72 | +3. In `apps/chat/src/services/mcpClients.ts`: |
| 73 | + - Extend header builder to accept optional dynamic header `X-KB-Collection-Id`. |
| 74 | +4. Runtime constraint: |
| 75 | + - API rejects chat requests when multiple active KB attachments exist (defensive check), even though DB/index should prevent it. |
| 76 | + |
| 77 | +### 5. Manage UI |
| 78 | +1. Add resources page: |
| 79 | + - `apps/frontend-manage/src/pages/resources/knowledgeBases.tsx`. |
| 80 | +2. Add resources components: |
| 81 | + - `apps/frontend-manage/src/components/resources/KnowledgeBases.tsx` |
| 82 | + - subcomponents for list, details, entry form, attachment management, sync jobs. |
| 83 | +3. Add header menu item (privatePreview-gated like chatbots): |
| 84 | + - `apps/frontend-manage/src/components/common/Header.tsx`. |
| 85 | +4. UX flow: |
| 86 | + - create KB. |
| 87 | + - add entries (Website URL / PDF URL / Text). |
| 88 | + - configure entry refresh interval. |
| 89 | + - attach KB to chatbot. |
| 90 | + - manually trigger sync and monitor status timeline. |
| 91 | +5. i18n: |
| 92 | + - add keys in `packages/i18n/messages/en.ts` and `packages/i18n/messages/de.ts`. |
| 93 | + |
| 94 | +### 6. Deferred v1.1+ Items |
| 95 | +1. Direct PDF upload in KB UI by extending existing SAS flow. |
| 96 | +2. Sharing support by integrating KB into permission/object-sharing framework. |
| 97 | +3. Multi-active KB retrieval for chatbot once RAG supports querying multiple collections. |
| 98 | + |
| 99 | +## Public API and Interface Changes |
| 100 | +1. New Prisma models and enums: `KnowledgeBase`, `KnowledgeBaseEntry`, `ChatbotKnowledgeBase`, `KnowledgeBaseSyncJob`, plus related enums. |
| 101 | +2. New GraphQL types, queries, and mutations for KB CRUD, entry CRUD, attachments, and manual sync. |
| 102 | +3. New HTTP webhook endpoint: |
| 103 | + - `POST /api/webhooks/knowledge-base-sync`. |
| 104 | +4. New environment variables: |
| 105 | + - `KB_PIPELINE_TRIGGER_URL` |
| 106 | + - `KB_PIPELINE_TRIGGER_SECRET` |
| 107 | + - `KB_PIPELINE_CALLBACK_SECRET` |
| 108 | + - `KB_PIPELINE_REQUEST_TIMEOUT_MS` (defaulted in code) |
| 109 | + |
| 110 | +## External Tool Variant Track (Documented, Not Primary) |
| 111 | +1. OpenMetadata |
| 112 | + - Fit: strong metadata/catalog platform, broad connectors. |
| 113 | + - Tradeoff: likely broader and heavier than v1 needs. |
| 114 | +2. Backstage Catalog |
| 115 | + - Fit: extensible entity model and plugin ecosystem. |
| 116 | + - Tradeoff: strong for internal developer portals; higher setup overhead for this use case. |
| 117 | +3. CKAN |
| 118 | + - Fit: mature open-data catalog. |
| 119 | + - Tradeoff: oriented to dataset publishing, less aligned with chatbot KB attachment workflows. |
| 120 | +4. Dify |
| 121 | + - Fit: built-in knowledge-base and RAG workflows. |
| 122 | + - Tradeoff: overlaps heavily with your dedicated ingestion pipeline and existing chatbot architecture. |
| 123 | +5. Directus |
| 124 | + - Fit: fast admin UI on custom tables. |
| 125 | + - Tradeoff: core domain logic still must be implemented in Klicker. |
| 126 | + |
| 127 | +## Test Cases and Scenarios |
| 128 | +1. Prisma/data integrity: |
| 129 | + - create/update/delete KB and entries. |
| 130 | + - enforce one active KB per chatbot. |
| 131 | + - immutable `collectionId`. |
| 132 | +2. GraphQL auth/validation: |
| 133 | + - owner-only access to KBs and entries. |
| 134 | + - reject invalid entry payload combinations. |
| 135 | + - reject non-`NONE` refresh intervals for PDF/TEXT. |
| 136 | +3. Manual sync trigger: |
| 137 | + - mutation creates sync job and sends webhook payload. |
| 138 | + - network failure transitions job to failed state with error. |
| 139 | +4. Callback webhook: |
| 140 | + - valid signature updates job/entry status. |
| 141 | + - duplicate callback `eventId` is idempotent. |
| 142 | + - invalid signature returns `401` and no mutation. |
| 143 | +5. Chat runtime: |
| 144 | + - when KB attached, MCP request includes `X-KB-Collection-Id`. |
| 145 | + - when no active KB attached, header omitted and request still works. |
| 146 | +6. Frontend: |
| 147 | + - create/edit/delete KB and entry flows. |
| 148 | + - attach/detach and active-assignment behavior on chatbot. |
| 149 | + - sync status timeline refresh and error rendering. |
| 150 | +7. End-to-end: |
| 151 | + - KB created, entry added, manual sync triggered, callback marks success, chatbot asks question with attached KB context. |
| 152 | +8. Regression: |
| 153 | + - existing chatbots, catalog, answer collections, and media library workflows remain unaffected. |
| 154 | + |
| 155 | +## Assumptions and Defaults |
| 156 | +1. Pipeline supports callback webhook with stable `jobId` and `eventId`. |
| 157 | +2. Pipeline accepts Klicker-owned `collectionId` UUID as target collection key. |
| 158 | +3. URL reachability/content parsing are pipeline responsibilities, not validated deeply by Klicker. |
| 159 | +4. Owner-only v1 intentionally excludes sharing flows. |
| 160 | +5. Refresh scheduling execution is fully pipeline-owned; Klicker stores policy metadata only. |
| 161 | +6. Direct PDF upload is explicitly out of v1 and planned as follow-up. |
| 162 | + |
| 163 | +## Next Steps |
| 164 | +1. Create Prisma schema plus migration for `KnowledgeBase`, `KnowledgeBaseEntry`, `ChatbotKnowledgeBase`, and `KnowledgeBaseSyncJob`. |
| 165 | +2. Add GraphQL queries/mutations and service layer for KB CRUD, attachments, and manual sync trigger. |
| 166 | +3. Implement pipeline trigger and callback webhook endpoint with HMAC verification and idempotency. |
| 167 | +4. Build the Manage UI under `/resources/knowledgeBases` and wire chatbot attachment controls. |
0 commit comments