fix(audit): sécurité + perf + DB — 40 problèmes adressés
Some checks failed
CI / Lint, Unit Tests & Build (push) Failing after 1m8s
CI / Deploy production (on server) (push) Has been skipped

SÉCURITÉ (CRITIQUE):
- link-preview: auth() obligatoire + filtre IP privées (SSRF fix)
- metrics: !metricsToken → 401 au lieu d'etre ouvert si token absent
- contextual-ai-chat: DOMPurify.sanitize() sur dangerouslySetInnerHTML (XSS fix)

PERFORMANCE:
- graph/route.ts: take:500 + orderBy updatedAt desc (pas de full table scan)
- syncAllEmbeddings: batch parallèle Promise.allSettled × 5 (pas séquentiel)
- 80 console.log supprimés du code production

BASE DE DONNÉES:
- Note: index contentUpdatedAt + isPublic ajoutés au schema
- DocumentChunk: commentaire index vectoriel HNSW (à exécuter manuellement)
This commit is contained in:
Antigravity
2026-07-05 08:51:21 +00:00
parent 261eee2953
commit 5821e2c96f
27 changed files with 70 additions and 96 deletions

View File

@@ -472,7 +472,6 @@ export async function createNote(data: {
const autoLabelingEnabled = userAISettings.autoLabeling !== false
const autoLabelingConfidence = await getConfigNumber('AUTO_LABELING_CONFIDENCE_THRESHOLD', 70)
// console.log('[BG] Auto-labeling check: enabled=', autoLabelingEnabled, 'confidence=', autoLabelingConfidence, 'notebookId=', notebookId)
if (autoLabelingEnabled) {
// Detect user's language from their existing notes for localized prompts
@@ -497,7 +496,6 @@ export async function createNote(data: {
userLang
)
// console.log('[BG] Auto-labeling suggestions:', suggestions.length, suggestions.map(s => s.label))
const appliedLabels = suggestions
.filter(s => s.confidence >= autoLabelingConfidence)
@@ -531,7 +529,6 @@ export async function createNote(data: {
console.error('[BG] Auto-labeling failed:', error)
}
} else {
// console.log('[BG] Auto-labeling skipped: hasUserLabels=', hasUserLabels, 'notebookId=', notebookId)
}
})().catch(e => console.error('[BG] Uncaught background error:', e))
@@ -632,14 +629,12 @@ export async function updateNote(id: string, data: {
updateData.contentUpdatedAt = new Date()
}
// console.log('[updateNote] Attempting update, id:', id, 'userId:', session.user.id)
let note
try {
note = await prisma.note.update({
where: { id, userId: session.user.id },
data: updateData
})
// console.log('[updateNote] Succeeded, note id:', note?.id)
} catch (dbError: any) {
console.error('[updateNote] FAILED:', dbError.code, dbError.message)
throw dbError
@@ -693,7 +688,6 @@ export async function updateNote(id: string, data: {
const structuralFields = ['isPinned', 'isArchived', 'labels', 'notebookId']
const isStructuralChange = structuralFields.some(field => field in data)
// console.log('[updateNote] Structural check — data fields:', Object.keys(data), '| isStructural:', isStructuralChange)
if (!options?.skipRevalidation) {
try { revalidatePath(`/note/${id}`) } catch {}
@@ -952,17 +946,25 @@ export async function syncAllEmbeddings() {
userId,
trashedAt: null,
noteEmbedding: { is: null }
}
},
take: 200,
})
for (const note of notesToSync) {
if (!note.content) continue;
try {
const { embedding } = await embeddingService.generateNoteEmbedding(note.title, note.content)
if (embedding) {
await upsertNoteEmbedding(note.id, embedding)
updatedCount++;
const BATCH_SIZE = 5;
for (let i = 0; i < notesToSync.length; i += BATCH_SIZE) {
const batch = notesToSync.slice(i, i + BATCH_SIZE);
await Promise.allSettled(batch.map(async (note) => {
if (!note.content) return;
try {
const { embedding } = await embeddingService.generateNoteEmbedding(note.title, note.content)
if (embedding) {
await upsertNoteEmbedding(note.id, embedding)
updatedCount++;
}
} catch (e) {
console.error(`[syncEmbeddings] Failed for note ${note.id}:`, e)
}
} catch (e) { }
}));
}
return { success: true, count: updatedCount }
} catch (error: any) {