Files
LegacyHUB/frontend
Vadim Malanov 24282d1279 feat(api): optional API-key auth middleware
Adds defence-in-depth shared-secret auth that activates when API_KEY
is set. Behaviour:

- empty API_KEY (dev default): every request allowed, middleware is
  not even installed;
- non-empty API_KEY: every request under APP_API_PREFIX except
  /health must carry X-API-Key: <value> or
  Authorization: Bearer <value>. /, /docs, /redoc, /openapi.json and
  CORS preflight stay open. hmac.compare_digest is used for the
  constant-time comparison.

The middleware resolves settings lazily so test fixtures can reload
app.config and have the new API_KEY take effect on the next install.

Tests (tests/test_api_security.py, 5 cases):
- /health remains open;
- protected route rejects missing key (401);
- protected route accepts X-API-Key header;
- protected route accepts Authorization: Bearer header;
- protected route rejects a wrong key.

Frontend:
- VITE_API_KEY env reads the key and Axios injects it on every
  request, falling back to no header when empty so SSO/reverse-proxy
  deployments stay unchanged.
- vite-env.d.ts adds the new env entry.

Docs/ops:
- .env.example documents the dev-default empty key;
- .env.prod.example marks API_KEY as a required rotation point;
- docker-compose.yml forwards API_KEY (defaults to empty);
- docker-compose.prod.yml fails the stack with ?:required when API_KEY
  is missing;
- RUNBOOK gains an API authentication section with header examples
  and the reverse-proxy + key layering recommendation.

pytest -q: 33 passed (5 new security + 28 prior).
npx tsc --noEmit: clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 17:17:27 +03:00
..

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:5173

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 8000 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-blur for the topbar.
  • Corners--radius: 14px produces soft, premium edges across every component.
  • Shadowsshadow-soft and shadow-elevated only. No harsh drop shadows.
  • Typography — Inter variable, optical sizes, tabular numbers for data cells, JetBrains Mono for IDs / paths / hashes.
  • Motion — Framer Motion layoutId for the active sidebar pill, fade-in-up for 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 with recursive / force toggles → 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 + K opens the global command palette.

Responsive layout

  • ≥ 1280 px (xl, ultrawide) — three-column dashboards, side-by-side search.
  • 10241280 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 → :8000
npm run build      # type-check + production bundle
npm run preview    # preview build
npm run lint
npm run format