* Resolve chunk access within a document/knowledge base, gated by read or write * permission on the KB. The document must exist and be fully processed * (`processingStatus === 'completed'`) before its chunks are accessible.
( knowledgeBaseId: string, documentId: string, chunkId: string, userId: string, requireWrite: boolean )
| 297 | * (`processingStatus === 'completed'`) before its chunks are accessible. |
| 298 | */ |
| 299 | async function resolveChunkAccess( |
| 300 | knowledgeBaseId: string, |
| 301 | documentId: string, |
| 302 | chunkId: string, |
| 303 | userId: string, |
| 304 | requireWrite: boolean |
| 305 | ): Promise<ChunkAccessCheck> { |
| 306 | const kbAccess = await resolveKnowledgeBaseAccess(knowledgeBaseId, userId, requireWrite) |
| 307 | |
| 308 | if (!kbAccess.hasAccess) { |
| 309 | return { |
| 310 | hasAccess: false, |
| 311 | notFound: kbAccess.notFound, |
| 312 | reason: kbAccess.notFound ? 'Knowledge base not found' : 'Unauthorized knowledge base access', |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | const doc = await db |
| 317 | .select() |
| 318 | .from(document) |
| 319 | .where( |
| 320 | and( |
| 321 | eq(document.id, documentId), |
| 322 | eq(document.knowledgeBaseId, knowledgeBaseId), |
| 323 | eq(document.userExcluded, false), |
| 324 | isNull(document.archivedAt), |
| 325 | isNull(document.deletedAt) |
| 326 | ) |
| 327 | ) |
| 328 | .limit(1) |
| 329 | |
| 330 | if (doc.length === 0) { |
| 331 | return { hasAccess: false, notFound: true, reason: 'Document not found' } |
| 332 | } |
| 333 | |
| 334 | const docData = doc[0] as DocumentData |
| 335 | |
| 336 | // Chunks are only accessible once the document has finished processing. |
| 337 | if (docData.processingStatus !== 'completed') { |
| 338 | return { |
| 339 | hasAccess: false, |
| 340 | reason: `Document is not ready for access (status: ${docData.processingStatus})`, |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | const chunk = await db |
| 345 | .select() |
| 346 | .from(embedding) |
| 347 | .where(and(eq(embedding.id, chunkId), eq(embedding.documentId, documentId))) |
| 348 | .limit(1) |
| 349 | |
| 350 | if (chunk.length === 0) { |
| 351 | return { hasAccess: false, notFound: true, reason: 'Chunk not found' } |
| 352 | } |
| 353 | |
| 354 | return { |
| 355 | hasAccess: true, |
| 356 | chunk: chunk[0] as EmbeddingData, |
no test coverage detected