Full DMS: folders + ACLs, versioning, trash, bulk ops, preview, smart folders

Rebuild the dashboard as a Drive-style document management system on top of
the existing CaveauAI hybrid RAG pipeline.

Backend:
- 5 migrations (versions, trash soft-delete, saved searches, categories, audit)
- DMS helpers (folder ACL walker, disk storage, audit, version snapshot,
  XLSX/PPTX/HTML/CSV/MD extractors)
- New APIs: folders, document-versions, trash, bulk, preview, saved-searches,
  categories, diagnostics
- Extended APIs: documents (folder_id, soft-delete, ACL filter, sort),
  upload (9 file types, version-collision detection with replace/new/keep-both,
  disk persistence), chat-stream (folder scoping + graph related-documents)
- 30-day trash purge cron with Qdrant + disk + graph cleanup

Frontend:
- Drive-style two-pane browser with folder tree, drag-drop, bulk-action bar,
  right-click context menu, multi-select
- New pages: folders (tree + per-folder ACL editor), trash (restore/purge)
- Extended pages: upload (folder picker, version-collision modal, 9 file
  type chips), document (Preview/Versions/Permissions tabs with PDF.js +
  mammoth.js + audio), index (DMS KPIs + activity feed), settings (live
  diagnostics ping MariaDB/Qdrant/LiteLLM/FalkorDB/disk), chat (folder
  scope chips + related-authorities chips)
- New CSS (dms.css) + JS bundle (dms.js) exposing window.DBN_DMS
- Sidebar nav adds Folders + Trash items

All routes return HTTP 200 in local smoke test; all 32 files lint clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 22:24:56 +02:00
parent b84827ecea
commit 2e2b0b45fa
30 changed files with 5438 additions and 335 deletions
+15 -5
View File
@@ -891,7 +891,9 @@ function dbnToolsExcerpt(string $text, int $limit = 520): string
const DBN_TOOLS_EXTRACT_MAX_BYTES = 8 * 1024 * 1024;
const DBN_TOOLS_EXTRACT_TEXT_LIMIT = 128000;
const DBN_TOOLS_TIMELINE_EXTRACT_TEXT_LIMIT = 600000;
const DBN_TOOLS_EXTRACT_ALLOWED_EXTS = ['txt', 'pdf', 'docx'];
const DBN_TOOLS_EXTRACT_ALLOWED_EXTS = ['txt', 'pdf', 'docx', 'xlsx', 'pptx', 'html', 'htm', 'csv', 'md', 'json'];
const DBN_TOOLS_EXTRACT_AUDIO_EXTS = ['mp3', 'wav', 'm4a', 'ogg', 'flac', 'webm'];
const DBN_TOOLS_EXTRACT_IMAGE_EXTS = ['png', 'jpg', 'jpeg', 'webp'];
function dbnToolsExtractUploadedFile(array $file, int $textLimit = DBN_TOOLS_EXTRACT_TEXT_LIMIT): array
{
@@ -922,13 +924,19 @@ function dbnToolsExtractUploadedFile(array $file, int $textLimit = DBN_TOOLS_EXT
$ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
if (!in_array($ext, DBN_TOOLS_EXTRACT_ALLOWED_EXTS, true)) {
dbnToolsAbort('Unsupported file type. Upload a .pdf, .docx, or .txt file.', 422, 'unsupported_type');
$allowed = strtoupper(implode(', .', DBN_TOOLS_EXTRACT_ALLOWED_EXTS));
dbnToolsAbort("Unsupported file type. Allowed: .{$allowed}.", 422, 'unsupported_type');
}
$text = match ($ext) {
'txt' => dbnToolsExtractTxt($tmpPath),
'pdf' => dbnToolsExtractPdf($tmpPath),
'docx' => dbnToolsExtractDocx($tmpPath),
'txt', 'md', 'json' => dbnToolsExtractTxt($tmpPath),
'pdf' => dbnToolsExtractPdf($tmpPath),
'docx' => dbnToolsExtractDocx($tmpPath),
'html', 'htm' => dbnDmsExtractHtml($tmpPath),
'csv' => dbnDmsExtractCsv($tmpPath),
'xlsx' => dbnDmsExtractXlsx($tmpPath),
'pptx' => dbnDmsExtractPptx($tmpPath),
default => dbnToolsExtractTxt($tmpPath),
};
$text = trim($text);
@@ -1370,3 +1378,5 @@ function dbnToolsInjectDocContent(array $input, string $text): string
}
return $docText . ($text !== '' ? "\n\n---\n\n" . $text : '');
}
require_once __DIR__ . '/dms_helpers.php';