import { describe, expect, it, vi } from 'vitest'; import type { RegulatoryChunk } from '../../src/domain/regulatory-rag'; import { createQdrantRegulatoryIndexFromEnvironment, QdrantClientError, QdrantRegulatoryIndex, REGULATORY_QDRANT_COLLECTION } from '../../server/regulatory/qdrant-regulatory-index'; const chunk: RegulatoryChunk = { schemaVersion: 1, corpusId: 'iso-27001', corpusVersion: '2022-de-1', documentId: 'a-5-1-de', framework: 'ISO/IEC 27001', frameworkVersion: '2022', controlId: 'A.5.1', chunkId: 'a-5-1-de:0:abcdef', chunkIndex: 0, language: 'de', title: 'Policies', text: 'Synthetic regulatory text.', textSha256: 'a'.repeat(64) }; function json(value: unknown, status = 200): Response { return new Response(JSON.stringify(value), { status, headers: { 'Content-Type': 'application/json' } }); } describe('Qdrant regulatory index', () => { it('creates the versioned dense/sparse collection and payload indexes', async () => { const fetcher = vi.fn(async (urlValue: string | URL | Request, init?: RequestInit) => { const url = String(urlValue); if (init?.method === 'GET' && url.endsWith(`/collections/${REGULATORY_QDRANT_COLLECTION}`)) { const getCount = fetcher.mock.calls.filter(call => call[1]?.method === 'GET').length; if (getCount === 1) return json({}, 404); return json({ result: { config: { params: { vectors: { dense: { size: 2, distance: 'Cosine' } }, sparse_vectors: { sparse: {} } } }, payload_schema: {} } }); } return json({ result: true, status: 'ok' }); }); const index = new QdrantRegulatoryIndex({ baseUrl: new URL('http://127.0.0.1:6333'), apiKey: 'secret', dimensions: 2, embeddingModel: 'multilingual-model', timeoutMs: 1_000, fetcher }); await index.ensureCollection(); const bodies = fetcher.mock.calls.map(call => call[1]?.body && JSON.parse(String(call[1]?.body))).filter(Boolean); expect(bodies[0]).toMatchObject({ vectors: { dense: { size: 2, distance: 'Cosine' } }, sparse_vectors: { sparse: {} } }); expect(bodies.filter(body => body.field_name)).toHaveLength(9); expect(fetcher.mock.calls.every(call => new Headers(call[1]?.headers).get('api-key') === 'secret')).toBe(true); }); it('replaces document points and performs filtered dense retrieval', async () => { const requests: Array<{ url: string; body?: any }> = []; const fetcher = vi.fn(async (urlValue: string | URL | Request, init?: RequestInit) => { const body = init?.body ? JSON.parse(String(init.body)) : undefined; requests.push({ url: String(urlValue), body }); if (String(urlValue).endsWith('/points/query')) return json({ result: { points: [{ score: 0.91, payload: { schema_version: 1, corpus_id: chunk.corpusId, corpus_version: chunk.corpusVersion, document_id: chunk.documentId, framework: chunk.framework, framework_version: chunk.frameworkVersion, control_id: chunk.controlId, chunk_id: chunk.chunkId, chunk_index: chunk.chunkIndex, language: chunk.language, title: chunk.title, text: chunk.text, text_sha256: chunk.textSha256 } }] } }); return json({ result: true, status: 'ok' }); }); const index = new QdrantRegulatoryIndex({ baseUrl: new URL('http://127.0.0.1:6333'), apiKey: 'secret', dimensions: 2, embeddingModel: 'multilingual-model', timeoutMs: 1_000, fetcher }); await index.replaceDocuments([{ chunk, embedding: [0.2, 0.8] }]); await expect(index.searchDense([0.4, 0.6], 5, { framework: 'ISO/IEC 27001', language: 'DE' })) .resolves.toEqual([{ score: 0.91, chunk }]); expect(requests[0].body.filter.must).toEqual([ { key: 'corpus_id', match: { value: 'iso-27001' } }, { key: 'document_id', match: { value: 'a-5-1-de' } } ]); expect(requests[1].body.points[0]).toMatchObject({ vector: { dense: [0.2, 0.8] }, payload: { framework: 'ISO/IEC 27001', control_id: 'A.5.1', language: 'de', embedding_model: 'multilingual-model' } }); expect(requests[2].body.filter.must).toEqual(expect.arrayContaining([ { key: 'embedding_model', match: { value: 'multilingual-model' } }, { key: 'framework', match: { value: 'ISO/IEC 27001' } }, { key: 'language', match: { value: 'de' } } ])); }); it('fails closed for an incompatible collection and unsafe remote HTTP', async () => { const index = new QdrantRegulatoryIndex({ baseUrl: new URL('http://127.0.0.1:6333'), apiKey: 'secret', dimensions: 2, embeddingModel: 'model', timeoutMs: 1_000, fetcher: async () => json({ result: { config: { params: { vectors: { dense: { size: 3, distance: 'Cosine' } }, sparse_vectors: { sparse: {} } } }, payload_schema: {} } }) }); await expect(index.ensureCollection()).rejects.toMatchObject({ code: 'qdrant_collection_incompatible' } satisfies Partial); expect(() => createQdrantRegulatoryIndexFromEnvironment(2, 'model', { ASSESSOR_QDRANT_URL: 'http://qdrant.example', ASSESSOR_QDRANT_API_KEY: 'secret' })).toThrow(/must use HTTPS/); }); });