Close 12 audit-driven platform-compliance gaps on a single branch. - D4 dispatch: app/integrations/dispatch_client.py participant `legacyhub`, emits LegacyhubDocumentIndexed + AssetDerivativeReady after the indexing commit (idempotent uuid5), http_inbox route (reindex/tombstone) with audit-based dedupe; docs/dispatch-contract.md. Celery+Redis stays intra-module. - D2 SSO: app/integrations/identity.py validates X-TeamHub-* + role/scope mapper; security.py adds trusted-header enforcement (AUTH_REQUIRE_IDENTITY) and a scope check on /search; docker-compose.teamhub.yml (external teamhub_net + internal db net, api not host-published); RUNBOOK network/firewall section. - Asset standard: SearchHit/Citation carry asset_id/owner_module; buckets renamed teamhub-legacyhub-* (+quarantine/tmp/exports); purge-by-asset_id with legal-hold guard (app/indexing/projection.py); OCR-markdown derivative event. - audit_log model + Alembic 0003 + record_audit on writes (same transaction). - Secret masking: app/common/json_logger.py recursive mask wired into structlog (+ensure_ascii=False); event payloads redacted before persistence. - Service X-API-Key mandatory on ingest endpoints (defence-in-depth). - Port: host API 8000->8050 (collision with SalesHUB/MailHUB resolved), container still listens on 8000. - Config: no plaintext secret defaults; fail-loud in non-dev (no value leak). - Docs drift: README PG 5440, layered-auth note, 5173 removed from CORS; ingest/folder gated by ENABLE_FOLDER_INGEST (410 by default). - ADRs: layers mapping, shared-core extraction, UI locale (RU-first). Tests: 78 passing (ruff, compileall, pytest, tsc, vite build, compose config). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LegacyHUB · Frontend
React + TypeScript + Vite frontend for LegacyHUB, the legacy-document indexing and AI search module of the TeamHUB Suite.
This package ships:
- the application shell (collapsible sidebar, top toolbar, breadcrumb nav, global ⌘K command palette, light/dark theme, notification center, user/profile menu);
- nine pages: Dashboard, Documents, Ingestion Jobs, Search, Document Viewer, Tables & Figures, Quality Control, System Health, Settings;
- a hybrid AI search workspace with semantic / lexical / hybrid modes, live suggestions, expandable filters, highlighted matches, reranker score visualization and side-by-side chunk preview;
- typed service layer (
src/services/*) with Axios + TanStack Query and a mock data backend you can toggle off when the backend is reachable.
Stack
| Concern | Library |
|---|---|
| Bundler | Vite 5 |
| Language | TypeScript 5.6 |
| UI | React 18 |
| Styling | TailwindCSS 3 + custom design tokens |
| Components | shadcn/ui primitives (Radix + cva) |
| Animation | Framer Motion |
| Charts | Recharts |
| Server state | TanStack Query |
| Client state | Zustand |
| Routing | React Router v6 |
| HTTP | Axios |
| Icons | lucide-react |
| Toasts | sonner |
| Virtualization | @tanstack/react-virtual |
Quick start
cd frontend
cp .env.example .env # VITE_USE_MOCK=true for offline UI development
npm install
npm run dev # http://localhost:5273
When the FastAPI backend is running, set VITE_USE_MOCK=false (or simply
VITE_API_BASE_URL=/api/v1 and let the Vite dev proxy at port 8050 handle
routing). All API calls are isolated through src/services/*.ts.
Architecture
frontend/src/
app/ RouterProvider, QueryClient, TooltipProvider, theme bootstrap
pages/ One file per route — composed of widgets + primitives
layouts/ AppShell, Sidebar (collapsible), Topbar, Breadcrumbs, ⌘K palette
widgets/ Domain-specific composite components (KpiCard, Charts, Result cards,
PdfPreviewPane, ChunkPreview, ServiceHealthCard, Timeline)
components/
ui/ shadcn-style primitives — Button, Card, Tabs, Dialog, Select,
Tooltip, Popover, ScrollArea, Command, Skeleton, Progress, …
common/ Domain primitives — Logo, StatusChip, ConfidenceMeter,
QualityFlag, BlockTypeIcon, Highlight, EmptyState, PageHeader,
ThemeToggle
services/ Typed API layer (Axios) + TanStack hooks (one file per resource)
mock/ Deterministic mock data + simulated latency
hooks/ Wrappers around services exposing TanStack Query hooks
stores/ Zustand stores: uiStore (theme, sidebar, palette), searchStore
styles/ Tailwind layer + design tokens (HSL CSS variables)
lib/ cn(), formatBytes/Number/Percent/Duration, relativeTime, etc.
Design system
- Palette — white / light-gray surfaces with a single restrained green
accent (
--primary: 158 64% 32%) matching QMS Hub. - Surfaces — three tiers: sunken (page background), default card, raised
(popovers / dialogs). Glass surfaces via
backdrop-blurfor the topbar. - Corners —
--radius: 14pxproduces soft, premium edges across every component. - Shadows —
shadow-softandshadow-elevatedonly. No harsh drop shadows. - Typography — Inter variable, optical sizes, tabular numbers for data cells, JetBrains Mono for IDs / paths / hashes.
- Motion — Framer Motion
layoutIdfor the active sidebar pill,fade-in-upfor KPI cards, animated tabs and result expansion. - States — skeleton shimmer instead of spinners wherever possible.
Key flows
- Hybrid search (
/search) — Debounced query → TanStack hook hits the backend (or mock). Results are virtualized, scored, optionally reranked. Picking a result hydrates a side-by-side ChunkPreview with the highlighted excerpt, a page thumbnail, citation metadata, and quality flags. - Documents (
/documents) — Virtualized table (TanStack Virtual) supports thousands of rows. Filters: status, OCR threshold, "needs review", free-text search. Clicking a row opens the viewer. - Document Viewer (
/viewer/:id) — Split layout. Left pane: PDF page thumbnails + synchronized large page preview with highlighted OCR blocks. Right pane: extracted chunks / tables / figures / metadata, kept in lock-step with the active page. Below: full pipeline timeline. - Ingestion (
/ingestion) — Submit a folder path withrecursive/forcetoggles → optimistic queue, run history table with live progress bars. - Quality control (
/quality) — Three review queues (low confidence, handwriting, failed extraction) with reviewer actions and an audit log.
Mock vs real backend
src/services/apiClient.ts exports a constant USE_MOCK. When true, every
service module short-circuits to src/services/mock/mockData.ts which
generates deterministic, seeded data: 280 documents, dashboards, ingestion
runs, search results, health and queue snapshots, and per-document detail
(pages, chunks, tables, figures, timeline events).
This lets the frontend be developed and demoed without the Python services running.
Accessibility
- All interactive elements use
ring-focus(visible 2px primary ring). - Sidebar nav exposes tooltips when collapsed.
- Keyboard:
Ctrl/Cmd + Kopens the global command palette.
Responsive layout
- ≥ 1280 px (xl, ultrawide) — three-column dashboards, side-by-side search.
- 1024–1280 px (laptop) — two-column dashboards, stacked search.
- < 1024 px — single column; sidebar collapses to icons only.
Scripts
npm run dev # Vite dev server with /api proxy → :8050
npm run build # type-check + production bundle
npm run preview # preview build
npm run lint
npm run format