From 1ea644b11f8d615a10aaa65d1adc89baf8542ceb Mon Sep 17 00:00:00 2001 From: Moinuddin Shaik Date: Tue, 14 Jul 2026 15:32:41 +0530 Subject: [PATCH] Build production-ready DocuLens showcase --- .dockerignore | 18 + .env.example | 28 + .env.showcase.example | 29 + .github/workflows/backend-ci.yml | 37 +- .gitignore | 8 +- .pre-commit-config.yaml | 16 + Makefile | 49 + README.md | 337 ++++--- app/alembic.ini | 2 +- app/api/dependencies.py | 16 + app/api/endpoint.py | 26 +- app/api/event_schema.py | 32 +- app/api/router.py | 6 +- app/config/celery_config.py | 7 + app/config/database_config.py | 7 +- app/config/llm_config.py | 8 +- app/config/settings.py | 85 +- app/core/observability.py | 33 + app/doc_utils/chunking.py | 11 +- app/doc_utils/embedding.py | 157 ++- app/evaluation/__init__.py | 1 + app/evaluation/retrieval.py | 42 + app/main.py | 147 ++- app/pyproject.toml | 20 - app/requirements.txt | 23 - app/services/demo_workspace.py | 437 ++++++++ app/services/vector_store.py | 63 +- app/start.sh | 10 +- docker/Caddyfile.showcase | 26 + docker/Dockerfile.api | 14 +- docker/Dockerfile.celery | 14 +- docker/Dockerfile.frontend | 12 + docker/docker-compose.showcase.yml | 72 ++ docker/docker-compose.yml | 63 +- docker/nginx.conf | 16 + docs/deploy-showcase.md | 82 ++ docs/design-system.md | 37 + docs/engineering-notes.md | 43 + docs/images/landing.jpg | Bin 0 -> 106225 bytes docs/images/login.jpg | Bin 0 -> 63180 bytes docs/images/qa-studio.jpg | Bin 0 -> 96346 bytes docs/images/work-queues.jpg | Bin 0 -> 75414 bytes docs/images/workspace-overview.jpg | Bin 0 -> 111481 bytes frontend/README.md | 87 +- frontend/index.html | 6 +- frontend/public/vite.svg | 1 - frontend/src/App.tsx | 52 +- frontend/src/api/client.ts | 12 +- frontend/src/api/types.ts | 9 + frontend/src/assets/react.svg | 1 - frontend/src/auth/ProtectedRoute.tsx | 8 +- frontend/src/components/DocumentDetail.tsx | 55 +- frontend/src/components/DocumentList.tsx | 35 +- .../src/components/DocumentUploadForm.tsx | 6 +- frontend/src/components/brand/Logo.tsx | 19 + .../dashboard/PersonaQuickstart.tsx | 2 +- .../src/components/dashboard/personaConfig.ts | 18 +- frontend/src/components/layout/AppShell.tsx | 383 ++++--- .../components/notifications/ActivityFeed.tsx | 109 +- frontend/src/components/ui/button.tsx | 14 +- frontend/src/components/ui/card.tsx | 2 +- frontend/src/components/ui/input.tsx | 2 +- frontend/src/components/ui/theme-toggle.tsx | 25 + frontend/src/hooks/useEventNotifications.ts | 4 +- frontend/src/lib/pipeline.ts | 47 + frontend/src/lib/queryClient.ts | 12 + frontend/src/lib/routing.ts | 50 + frontend/src/lib/utils.ts | 6 + frontend/src/main.tsx | 68 +- frontend/src/pages/IntakePage.tsx | 943 ++++-------------- frontend/src/pages/LandingPage.tsx | 291 ++++++ frontend/src/pages/LoginPage.tsx | 141 +-- frontend/src/pages/PipelinePage.tsx | 24 +- frontend/src/pages/QaPage.tsx | 294 ++---- frontend/src/pages/SettingsPage.tsx | 13 +- frontend/src/pages/WorkQueuesPage.tsx | 64 +- frontend/src/settings/SettingsProvider.tsx | 5 +- frontend/src/stores/uiStore.ts | 5 + frontend/src/styles/globals.css | 170 ++-- frontend/tailwind.config.ts | 2 + pyproject.toml | 65 ++ pyrightconfig.json | 14 +- scripts/dev_stack.sh | 2 +- tests/test_api_endpoints.py | 14 + tests/test_retrieval_evaluation.py | 8 + tests/test_settings.py | 43 + 86 files changed, 3087 insertions(+), 2078 deletions(-) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 .env.showcase.example create mode 100644 .pre-commit-config.yaml create mode 100644 Makefile create mode 100644 app/core/observability.py create mode 100644 app/evaluation/__init__.py create mode 100644 app/evaluation/retrieval.py delete mode 100644 app/pyproject.toml delete mode 100644 app/requirements.txt create mode 100644 app/services/demo_workspace.py create mode 100644 docker/Caddyfile.showcase create mode 100644 docker/Dockerfile.frontend create mode 100644 docker/docker-compose.showcase.yml create mode 100644 docker/nginx.conf create mode 100644 docs/deploy-showcase.md create mode 100644 docs/design-system.md create mode 100644 docs/engineering-notes.md create mode 100644 docs/images/landing.jpg create mode 100644 docs/images/login.jpg create mode 100644 docs/images/qa-studio.jpg create mode 100644 docs/images/work-queues.jpg create mode 100644 docs/images/workspace-overview.jpg delete mode 100644 frontend/public/vite.svg delete mode 100644 frontend/src/assets/react.svg create mode 100644 frontend/src/components/brand/Logo.tsx create mode 100644 frontend/src/components/ui/theme-toggle.tsx create mode 100644 frontend/src/lib/pipeline.ts create mode 100644 frontend/src/lib/queryClient.ts create mode 100644 frontend/src/lib/routing.ts create mode 100644 frontend/src/lib/utils.ts create mode 100644 frontend/src/pages/LandingPage.tsx create mode 100644 pyproject.toml create mode 100644 tests/test_retrieval_evaluation.py create mode 100644 tests/test_settings.py diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a27f7a6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,18 @@ +.git +.github +.env +.env.* +!.env.example +!.env.showcase.example +.venv +.venv312 +.pytest_cache +.ruff_cache +.coverage +**/__pycache__ +**/*.py[cod] +frontend/node_modules +frontend/dist +data/ingestion +*.png +*.log diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..df52d7c --- /dev/null +++ b/.env.example @@ -0,0 +1,28 @@ +# Runtime +DOCULENS_ENVIRONMENT=development +DOCULENS_LOG_LEVEL=INFO +DOCULENS_CORS_ORIGINS=["http://localhost:5173"] +DOCULENS_INITIALIZE_DATABASE=true +DOCULENS_SEED_DEMO_USERS=false +DOCULENS_SEED_DEMO_WORKSPACE=false +DOCULENS_SHOWCASE_READ_ONLY=false +DOCULENS_AUTH_SECRET=replace-with-a-long-random-value +DOCULENS_API_KEY= + +# AI providers +OPENAI_API_KEY= +ANTHROPIC_API_KEY= +OPEN_ROUTER_API_KEY= +DOCULENS_PROVIDER_TIMEOUT_SECONDS=30 +DOCULENS_CHUNK_MAX_TOKENS=800 +DOCULENS_EMBEDDING_BATCH_SIZE=64 +DOCULENS_EMBEDDING_CACHE_SIZE=1024 + +# Infrastructure +PROJECT_NAME=doculens +DATABASE_HOST=doculens_database +DATABASE_PORT=5432 +DATABASE_NAME=doculens +DATABASE_USER=postgres +DATABASE_PASSWORD=doculens-local-only +REDIS_URL=redis://doculens_redis:6379/0 diff --git a/.env.showcase.example b/.env.showcase.example new file mode 100644 index 0000000..a541b69 --- /dev/null +++ b/.env.showcase.example @@ -0,0 +1,29 @@ +# Copy to .env.showcase and replace every value marked "replace-me". +PROJECT_NAME=doculens_showcase +CADDY_DOMAIN=demo.example.com + +# Public showcase behavior +DOCULENS_ENVIRONMENT=production +DOCULENS_LOG_LEVEL=INFO +DOCULENS_CORS_ORIGINS=["https://demo.example.com"] +DOCULENS_RUN_MIGRATIONS=true +DOCULENS_INITIALIZE_DATABASE=true +DOCULENS_SEED_DEMO_USERS=false +DOCULENS_SEED_DEMO_WORKSPACE=true +DOCULENS_SHOWCASE_READ_ONLY=true +DOCULENS_AUTH_SECRET=replace-me-with-openssl-rand-hex-32 +DOCULENS_API_KEY= + +# No provider call is reachable while showcase mode is enabled. These values +# only let provider clients initialize during creation of the vector table. +OPENAI_API_KEY=showcase-no-provider-calls +ANTHROPIC_API_KEY=showcase-no-provider-calls +OPEN_ROUTER_API_KEY=showcase-no-provider-calls + +# Private Compose network +DATABASE_HOST=database +DATABASE_PORT=5432 +DATABASE_NAME=doculens +DATABASE_USER=postgres +DATABASE_PASSWORD=replace-me-with-a-long-random-password +REDIS_URL=redis://redis:6379/0 diff --git a/.github/workflows/backend-ci.yml b/.github/workflows/backend-ci.yml index cfcce90..9081b67 100644 --- a/.github/workflows/backend-ci.yml +++ b/.github/workflows/backend-ci.yml @@ -1,4 +1,4 @@ -name: Backend CI +name: Quality on: push: @@ -23,11 +23,40 @@ jobs: uses: actions/setup-python@v5 with: python-version: "3.11" + cache: pip - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r app/requirements.txt + pip install -e '.[dev]' - - name: Run tests - run: pytest + - name: Lint + run: ruff check . + + - name: Type-check + run: pyright + + - name: Run tests with coverage + run: pytest --cov=app --cov-report=term-missing + + frontend: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: npm + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + run: npm --prefix frontend ci + + - name: Lint + run: npm --prefix frontend run lint + + - name: Build and type-check + run: npm --prefix frontend run build diff --git a/.gitignore b/.gitignore index b46498b..d3e8366 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,8 @@ eggs/ .eggs/ lib/ lib64/ +!frontend/src/lib/ +!frontend/src/lib/** parts/ sdist/ var/ @@ -58,7 +60,7 @@ target/ # DotEnv configuration .env -.env.example +!.env.example # Database *.db @@ -89,9 +91,7 @@ target/ # Virtual environment .venv/ - -# docs -/docs/ +.venv312/ # Local ingestion uploads data/ingestion/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0f2e477 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,16 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.3 + hooks: + - id: ruff-check + args: [--fix] + - id: ruff-format + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - id: check-added-large-files + args: [--maxkb=2000] + - id: detect-private-key diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..46b5c42 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +SHELL := /bin/bash +.DEFAULT_GOAL := help + +.PHONY: help install dev up down showcase-up showcase-down showcase-logs test lint format typecheck check sample + +help: ## Show available commands + @awk 'BEGIN {FS = ":.*## "; printf "DocuLens developer commands\n\n"} /^[a-zA-Z_-]+:.*## / {printf " %-12s %s\n", $$1, $$2}' $(MAKEFILE_LIST) + +install: ## Install backend and frontend development dependencies + python3 -m pip install -e '.[dev]' + npm --prefix frontend ci + +dev: ## Run API with hot reload + uvicorn app.main:app --reload --port 8080 + +up: ## Start the complete Docker development stack + docker compose --env-file .env -f docker/docker-compose.yml up --build -d + +down: ## Stop the Docker development stack + docker compose --env-file .env -f docker/docker-compose.yml down + +showcase-up: ## Build and start the read-only portfolio showcase + docker compose --env-file .env.showcase -f docker/docker-compose.showcase.yml up --build -d + +showcase-down: ## Stop the read-only portfolio showcase + docker compose --env-file .env.showcase -f docker/docker-compose.showcase.yml down + +showcase-logs: ## Follow portfolio showcase logs + docker compose --env-file .env.showcase -f docker/docker-compose.showcase.yml logs -f --tail=200 + +test: ## Run backend tests + pytest + +lint: ## Run backend and frontend lint checks + ruff check . + npm --prefix frontend run lint + +format: ## Format backend code + ruff format . + ruff check --fix . + +typecheck: ## Type-check backend and build/type-check frontend + pyright + npm --prefix frontend run build + +check: lint typecheck test ## Run the full local quality gate + +sample: ## Submit the sample search event to a running API + python3 requests/send_event.py requests/events/search_query.json diff --git a/README.md b/README.md index bf30fb4..9697c9a 100644 --- a/README.md +++ b/README.md @@ -1,206 +1,235 @@ -# DocuLens AI Console - -DocuLens AI is a full-stack document intelligence workstation. The FastAPI/Celery -backend ingests files, runs summarisation and retrieval pipelines, and exposes a -task-driven event API. The React (Vite + TypeScript) console gives analysts, -operations teams, and integrators a control room for uploads, work queues, QA, -and governance. - -This repository contains the entire stack used in local development and CI: -pipelines, Timescale/pgvector integration, a modern UI, and supporting scripts. - ---- - -## Highlights - -- **Event-driven pipelines** – Queue `document_upload`, `document_summary`, - `qa_query`, and related events. Celery orchestrates extraction, chunking, - embedding, and persistence to Timescale Vector. -- **Operator-first console** – Intake dashboards, role-aware work queues - (Finance, Compliance, Operations, Legal, HR, Integrator), and the dedicated QA - Studio keep reviewers in flow. -- **Retrieval-augmented QA** – QA Studio streams pending questions, polling for - answers without requiring A page reload. Pending states surface inline with - animated typing indicators and citations. -- **Insights & notifications** – Uploads, QA completions, and routing actions - raise toasts and persist in the activity feed. Polling keeps stakeholders - informed when answers or summaries finish processing. -- **Governance-ready settings** – Persona selection, API key management, and - configurable limits (chunk preview, QA `top_k`, search result counts) are - exposed in the console with local persistence. -- **Comprehensive automation** – Docker Compose environments, smoke-test - scripts, pytest coverage, and GitHub Actions ensure the pipelines remain - reliable as the product evolves. - ---- - -## Architecture at a Glance +# DocuLens AI -```text -┌──────────────────┐ ┌──────────────────────┐ ┌──────────────────┐ -│ React Console │ ─────▶ │ FastAPI Gateway │ ─────▶ │ PostgreSQL/ │ -│ (Vite + TS) │ │ /events endpoints │ │ Timescale + pgvec│ -└──────────────────┘ │ └ Celery dispatcher│ └──────────────────┘ - ▲ │ │ ▲ - │ └──────────────┬──────┘ │ - │ │ │ - │ ┌──────────────▼───────────────┐ │ - └──────────────────┤ Celery Worker (pipelines) │ ◀──────┘ - │ • chunking & embedding │ - │ • summarisation & QA │ - │ • semantic search │ - └──────────────────────────────┘ -``` +**Turn unstructured business documents into searchable, cited, operational knowledge.** -**Backend**: FastAPI, SQLAlchemy, Celery, TimescaleDB + pgvector, Redis -**LLM/Retrieval**: OpenAI/Anthropic (configurable), in-house chunker/tokeniser -**Frontend**: React 18, TypeScript, Vite, Tailwind, shadcn/ui components -**Tooling**: Docker Compose, pytest, GitHub Actions, scripts for smoke testing +DocuLens is an open-source document intelligence system for teams that need more than a chat-with-PDF demo. It accepts documents asynchronously, extracts layout-aware content, creates citation-ready embeddings, and exposes classification, summarization, semantic search, and grounded question answering through a versioned API and an operator console. ---- +[![Backend CI](https://github.com/codewithmoin/doculens-ai/actions/workflows/backend-ci.yml/badge.svg)](https://github.com/codewithmoin/doculens-ai/actions/workflows/backend-ci.yml) +[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776AB)](https://www.python.org/) +[![FastAPI](https://img.shields.io/badge/FastAPI-API-009688)](https://fastapi.tiangolo.com/) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -## Repository Layout +## Why it is technically interesting -```text -app/ FastAPI application, pipelines, Celery tasks -frontend/ React console (Vite + TypeScript) -docker/ Container definitions and compose files -requests/ Sample payloads and helper scripts -scripts/ Developer utilities and smoke tests -tests/ Pytest suite covering API & pipelines -.github/workflows/ Continuous integration pipelines +- **Layout-aware ingestion:** Docling preserves headings, tables, provenance, and page numbers instead of flattening a document into one string. +- **Asynchronous AI workflows:** FastAPI accepts work quickly; Celery executes extraction and model calls with bounded task time, late acknowledgement, and worker-loss recovery. +- **Citation-first RAG:** every vector carries document, chunk, page, title, and token metadata; QA prompts use stable references and require grounded answers. +- **Measurable retrieval:** dependency-free Recall@K and MRR utilities make retrieval changes testable against labelled fixtures. +- **Operational product surface:** the React console covers intake, work queues, QA history, labels, lifecycle actions, and dashboard insights. + +## Product tour + +![DocuLens AI landing experience](docs/images/landing.jpg) + +The redesigned experience separates the public product story from a focused authenticated workspace. Inside the app, teams get global `⌘K` search, drag-and-drop ingestion, collection-aware document navigation, work queues, processing visibility, and an evidence-first AI chat with source references. + +![DocuLens AI workspace overview](docs/images/workspace-overview.jpg) + +
+View the evidence-first QA studio and work queues + +![DocuLens AI QA studio](docs/images/qa-studio.jpg) + +![DocuLens AI work queues](docs/images/work-queues.jpg) + +
+ +
+View the workspace sign-in experience + +![DocuLens AI sign-in](docs/images/login.jpg) + +
+ +## Architecture + +```mermaid +flowchart LR + UI["React operator console"] -->|REST /api/v1| API["FastAPI gateway"] + Client["API clients"] --> API + API -->|persist event| DB[("TimescaleDB + PostgreSQL")] + API -->|enqueue id| Redis[("Redis broker")] + Redis --> Worker["Celery worker"] + Worker --> Extract["Docling extraction"] + Extract --> Chunk["Layout-aware chunking"] + Chunk --> Embed["Batched embeddings"] + Embed --> Vector[("pgvector / DiskANN")] + Worker --> LLM["Structured LLM calls"] + LLM --> DB + Vector --> Retrieve["Filtered retrieval"] + Retrieve --> LLM ``` ---- +The event record is the durable boundary between HTTP and AI work. A worker validates the stored event, selects a typed pipeline from the registry, runs its nodes, and stores a serializable task context. This design keeps slow or retryable model work away from request threads while retaining an auditable input/output trail. -## Getting Started +## Capabilities -### Prerequisites +- PDF and text ingestion with layout-aware extraction +- document classification and configurable label hierarchies +- structured information extraction +- document summaries with source chunk provenance +- metadata-filtered semantic and keyword search +- retrieval-augmented QA with stable citations and confidence +- archive, restore, and soft-delete lifecycle operations +- JWT personas plus optional API-key protection +- work queues, notifications, dashboards, and request history +- OpenAI, Anthropic, OpenRouter, and local OpenAI-compatible model adapters -- Python 3.12+ -- Node.js 18+ -- Docker Desktop (Postgres/Timescale, Redis, ancillary services) -- OpenAI or Anthropic credentials (configure in `.env`) +## Stack -### 1. Clone & configure environment +| Layer | Technology | Responsibility | +| --- | --- | --- | +| API | FastAPI, Pydantic, SQLAlchemy | contracts, validation, authentication, persistence | +| Jobs | Celery, Redis | resilient long-running document and AI processing | +| Retrieval | Docling, tiktoken, OpenAI embeddings | extraction, bounded chunks, batched embeddings | +| Data | PostgreSQL, Timescale Vector, pgvector | events, metadata, keyword and vector search | +| Models | Instructor, OpenAI, Anthropic | provider-neutral structured outputs | +| Web | React 19, TypeScript, Vite, TanStack Query | operator workflows and evidence review | +| Quality | pytest, Ruff, Pyright, pre-commit, GitHub Actions | repeatable engineering checks | + +## Quick start + +### Prerequisites + +- Docker with Compose v2 +- an OpenAI API key (required for embeddings; model providers are configurable) +- Python 3.11+ and Node 20+ only when running services outside Docker ```bash -git clone -cd "Doculens AI" +git clone https://github.com/codewithmoin/doculens-ai.git +cd doculens-ai cp .env.example .env -# edit .env with provider keys, database overrides, and doculens settings +# Set OPENAI_API_KEY and replace DOCULENS_AUTH_SECRET in .env +make up ``` -Key variables: +Open: -| Variable | Purpose | -| --- | --- | -| `DOCULENS_SUMMARY_CHUNK_LIMIT` | Max chunks fed into the summariser | -| `DOCULENS_QA_TOP_K` | Retrieval breadth for QA Studio | -| `DOCULENS_SEARCH_RESULT_LIMIT` | Default search pagination | -| `DATABASE_*` | Optional overrides when not using Docker Postgres | -| `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` | LLM provider credentials | +- console: `http://localhost:5173` +- OpenAPI: `http://localhost:8080/docs` +- liveness: `http://localhost:8080/health/live` -### 2. Start the stack +Schema migrations should be applied with Alembic for deployments. Automatic table initialization is a local-development convenience and can be disabled with `DOCULENS_INITIALIZE_DATABASE=false`. Demo users are opt-in via `DOCULENS_SEED_DEMO_USERS=true` and are explicitly rejected in production. -```bash -docker network create doculens_network # safe to rerun; ensures required network exists -./scripts/dev_stack.sh # boots Postgres, Redis, API, worker, UI -``` +### Publish the portfolio showcase -If Celery exits with a `libpq.5.dylib` import error on macOS, reinstall the bundled driver via: +DocuLens includes a separate single-node deployment for a public, read-only product tour. It serves the frontend and API from one HTTPS domain, seeds synthetic documents idempotently, skips the worker, and blocks every state-changing workspace request in the API. ```bash -.venv/bin/pip install --force-reinstall psycopg2-binary +cp .env.showcase.example .env.showcase +# Set the domain and generated secrets, then: +make showcase-up ``` -Backends start on `http://localhost:8080`, the console on `http://localhost:5173`. +See the [showcase deployment runbook](docs/deploy-showcase.md) for DNS, TLS, verification, backups, and rollback. This mode demonstrates the finished AI workflow without accepting public uploads or spending money on visitor model calls. + +## API examples -### 3. Frontend in development mode +All stable endpoints are under `/api/v1`. Legacy `/events` routes remain available for existing clients. + +Upload a document: ```bash -cd frontend -npm install -npm run dev +curl --fail-with-body http://localhost:8080/api/v1/events/documents/upload \ + -H "X-API-Key: $DOCULENS_API_KEY" \ + -F "file=@data/sample/example.txt" \ + -F "doc_type=invoice" \ + -F 'metadata={"source":"quickstart","department":"finance"}' ``` -### 4. Run tests +Ask a grounded question: ```bash -.venv/bin/python -m pytest # backend + pipeline coverage +curl --fail-with-body http://localhost:8080/api/v1/events/ \ + -H 'Content-Type: application/json' \ + -H "X-API-Key: $DOCULENS_API_KEY" \ + -d '{"event_type":"qa_query","query":"What is the invoice total?","top_k":5}' ``` ---- +The API returns `202 Accepted` with an event id. Poll the event resource until its task context contains the answer and `chunk_references` used to construct it. Ready-made payloads live in [`requests/events`](requests/events). -## Everyday Workflows +## Configuration -1. **Upload documents** – use the Intake page or POST to `/events/documents/upload`. - Uploaded files appear in the Intake dashboard and work queues with automatic - status tags. -2. **Process & route** – Work Queues group documents by inferred or assigned - role (Finance, Compliance, Operations, Legal, HR, Integrator). HR-specific - labels (Resume/CV, Offer Letter, Training Certificate, etc.) now stay within - the HR lane. -3. **Summarise** – Document detail pages expose “Summarise again”. If no - summary exists, placeholders prompt operators to run one (and the processing - timeline remains visible). -4. **Ask questions** – QA Studio stores per-document chat history, keeps pending - messages visible with typing indicators, and pulls in completed answers - automatically—no page refresh needed. -5. **Stay informed** – Notification toasts and the bell keep track of uploads, - QA completions, routing changes, and summary jobs. +Configuration is validated once at startup. See [`.env.example`](.env.example) for the full local template. ---- +| Variable | Default | Purpose | +| --- | ---: | --- | +| `DOCULENS_ENVIRONMENT` | `development` | enables production safety checks | +| `DOCULENS_CORS_ORIGINS` | localhost console | JSON list of allowed browser origins | +| `DOCULENS_MAX_UPLOAD_BYTES` | 25 MiB | streamed upload limit | +| `DOCULENS_CHUNK_MAX_TOKENS` | 800 | retrieval chunk size | +| `DOCULENS_EMBEDDING_BATCH_SIZE` | 64 | provider request batch bound | +| `DOCULENS_EMBEDDING_CACHE_SIZE` | 1024 | process-local repeated-text cache | +| `DOCULENS_PROVIDER_TIMEOUT_SECONDS` | 30 | AI provider network timeout | +| `DOCULENS_QA_TOP_K` | 5 | default QA retrieval breadth | +| `DOCULENS_SHOWCASE_READ_ONLY` | false | blocks workspace mutations and enables the public product-tour UX | -## API Quick Reference +## Development -All routes live under `/events`. Authentication is controlled via the header -defined by `DOCULENS_API_KEY_HEADER` when `DOCULENS_API_KEY` is set. +```bash +make install # backend editable install + npm ci +make check # lint, types, frontend build, tests +pre-commit install # run fast checks before each commit +``` -| Method | Route | Description | -| --- | --- | --- | -| `POST` | `/events/documents/upload` | Multipart upload (`file`, `doc_type`, `metadata`) | -| `POST` | `/events` | Generic event ingestion (summary, QA, search, routing) | -| `GET` | `/events/documents` | Latest documents + metadata | -| `GET` | `/events/qa/history` | Historical QA answers, citations, reasoning | -| `GET` | `/events/search/history` | Semantic search history with snippets | -| `GET` | `/events/insights/dashboard` | Throughput, SLA risk, ROI metrics | +Useful commands are discoverable with `make help`. CI runs the same Ruff, Pyright, pytest, and coverage checks used locally. -Example upload: +### Retrieval evaluation -```bash -curl -X POST "http://localhost:8080/events/documents/upload" \ - -H "X-API-Key: ${DOCULENS_API_KEY:-local-dev}" \ - -F "file=@/path/to/document.pdf" \ - -F 'doc_type=resume' \ - -F 'metadata={"role":"HR","source":"careers-portal"}' +Create labelled `RetrievalExample` cases with known relevant chunk ids and run `evaluate(examples, k=5)`. Track Recall@5 and MRR before changing chunk size, embedding model, filters, or ranking. The utility is intentionally offline and deterministic: it belongs in CI; live provider quality and latency belong in a separate scheduled benchmark. + +## Project structure + +```text +app/ +├── api/ HTTP contracts, auth, dependencies, versioned routers +├── config/ validated runtime and infrastructure settings +├── core/ pipeline primitives and observability +├── database/ SQLAlchemy models, repositories, migrations +├── doc_utils/ extraction, chunking, embedding, retrieval +├── evaluation/ offline RAG quality metrics +├── pipelines/ typed document and QA workflows +├── prompts/ reviewed, versionable Jinja prompt assets +├── services/ domain and external-provider adapters +└── tasks/ durable Celery task entrypoints +frontend/ React/TypeScript operator console +docker/ API, worker, proxy, database, and Redis stack +tests/ API, pipeline, dashboard, and evaluation tests +requests/ executable example payloads ``` ---- +## Engineering decisions and tradeoffs + +- **Modular monolith:** one deployable backend keeps contribution and operations simple. Service boundaries are internal and can be extracted only if scaling evidence demands it. +- **Async jobs, synchronous pipeline nodes:** document work is asynchronous at the system boundary; node code stays easy to reason about because most provider SDKs and extraction libraries are synchronous. Worker concurrency supplies parallelism. +- **Process-local embedding cache:** avoids repeated provider calls without introducing another consistency-sensitive cache. It resets on deploy and is not intended as durable storage. +- **Provider-neutral structured outputs:** improves validation and portability, but provider behavior still differs and must be evaluated per model. +- **Compatibility versioning:** `/api/v1` is canonical while legacy routes remain during migration. Removing aliases is a future breaking release. +- **Product hierarchy over dashboard density:** the public landing page explains the problem and architecture; `/app` is reserved for focused document work. The UI uses route-level code splitting, a paper-and-ink system with cobalt focus and amber evidence, persistent dark mode, and reduced-motion fallbacks instead of a large animation runtime. + +More detail is recorded in [`docs/engineering-notes.md`](docs/engineering-notes.md) and the [`design system specification`](docs/design-system.md). -## Testing & Automation +## Limitations -- **Unit & integration tests:** `pytest` targets FastAPI endpoints, pipeline - orchestration, and dashboard metrics. -- **Smoke tests:** `scripts/backend_smoke.sh` replays sample events. Use - `requests/send_event.py` to post custom payloads. -- **Continuous integration:** `.github/workflows/backend-ci.yml` runs linting - and pytest on every push/PR. -- **Frontend builds:** `npm run build && npm run preview` produce a static Vite - bundle for deployment. +- OCR/model accuracy depends on document quality, language, and provider. +- The current retrieval path is dense-first; hybrid ranking exists but needs a labelled corpus before tuning. +- The included deployment manifest is deliberately scoped to a single-node, read-only portfolio showcase—not a multi-tenant customer environment. +- Authentication is suitable for a single workspace; multi-tenant authorization is not implemented. +- Retrieval metrics are utilities, not a bundled benchmark dataset—the project does not claim quality without domain-labelled examples. ---- +## Roadmap -## Roadmap & Ideas +- persist event lifecycle states and retry diagnostics as first-class columns +- add a small, redistributable labelled retrieval benchmark +- evaluate reciprocal-rank fusion for dense + keyword retrieval +- add OpenTelemetry traces and provider latency/cost dashboards +- split the large legacy event endpoint module by resource as routes stabilize +- publish signed, multi-stage container images and a deployment runbook -- Harden production deployment (container images + helm charts). -- Add role-based access controls inside the console. -- Expand analytics with richer HR/Finance KPIs and Prometheus scraping. -- Extend extraction pipelines with structured field capture. +## Security ---- +Never commit provider keys or production documents. Configure explicit CORS origins, API authentication, a strong `DOCULENS_AUTH_SECRET`, database TLS, and object storage for uploads in deployed environments. Report vulnerabilities privately through GitHub security advisories. ## License -DocuLens AI is released under the CodeWithMoin license. Refer to -[`LICENSE`](LICENSE) for terms. +DocuLens AI is available under the [MIT License](LICENSE). diff --git a/app/alembic.ini b/app/alembic.ini index a2bfc1e..d7c28d7 100644 --- a/app/alembic.ini +++ b/app/alembic.ini @@ -2,7 +2,7 @@ [alembic] # path to migration scripts -script_location = alembic/ +script_location = %(here)s/alembic/ # template used to generate migration file names; The default value is %%(rev)s_%%(slug)s # Uncomment the line below if you want the files to be prepended with date and time diff --git a/app/api/dependencies.py b/app/api/dependencies.py index 042f8cd..b04d7bf 100644 --- a/app/api/dependencies.py +++ b/app/api/dependencies.py @@ -45,3 +45,19 @@ def require_api_key(request: Request) -> None: status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid API key.", ) + + +def require_showcase_writable(request: Request) -> None: + """Reject state-changing workspace requests in public showcase mode. + + This guard lives in the API rather than relying on disabled frontend controls, + so direct requests cannot mutate the seeded portfolio workspace. + """ + settings = get_settings() + if not settings.showcase_read_only or request.method in {"GET", "HEAD", "OPTIONS"}: + return + + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail="This public showcase is read-only.", + ) diff --git a/app/api/endpoint.py b/app/api/endpoint.py index fab2788..60f7d94 100644 --- a/app/api/endpoint.py +++ b/app/api/endpoint.py @@ -2,17 +2,15 @@ import string from datetime import datetime, timedelta, timezone from http import HTTPStatus -from pathlib import Path import uuid -from datetime import datetime - +from pathlib import Path from typing import Any, Dict, Iterable, List, Literal, Optional, Sequence, Tuple from uuid import UUID, uuid4 from fastapi import APIRouter, Body, Depends, File, Form, HTTPException, Query, Response, UploadFile from sqlalchemy import select, text from sqlalchemy.orm import Session -from pydantic import BaseModel +from pydantic import BaseModel, Field from app.api.dependencies import db_session from app.api.event_schema import EventSchema @@ -121,7 +119,7 @@ class LabelTreeNode(BaseModel): description: Optional[str] = None parent_id: Optional[str] = None workspace_id: Optional[str] = None - children: List["LabelTreeNode"] = [] + children: List["LabelTreeNode"] = Field(default_factory=list) LabelTreeNode.model_rebuild() @@ -295,6 +293,7 @@ def get_runtime_config() -> Dict[str, Any]: "search_preview_limit": settings.search_preview_limit, "chunk_preview_limit": settings.chunk_preview_limit, "auth_required": bool(settings.api_key), + "showcase_read_only": settings.showcase_read_only, "api_key_header": settings.api_key_header, "persona_options": PERSONA_OPTIONS, "role_definitions": ROLE_DEFINITIONS, @@ -403,8 +402,6 @@ def get_dashboard_insights( now = datetime.now(timezone.utc) fourteen_days_ago = now - timedelta(days=13) - thirty_days_ago = now - timedelta(days=30) - uploads_rows = session.execute( text( """ @@ -653,8 +650,7 @@ def list_events( session: Session = Depends(db_session), ): """Return the most recent events and their processing context.""" - repository = GenericRepository(session=session, model=Event) - events = repository.get_latest(limit) + events = session.query(Event).order_by(Event.created_at.desc()).limit(limit).all() return [ { "id": str(event.id), @@ -1060,13 +1056,24 @@ async def upload_document( stored_filename = f"{uuid4().hex}_{original_name}" stored_path = ingestion_dir / stored_filename + bytes_written = 0 + max_upload_bytes = get_settings().max_upload_bytes try: with stored_path.open("wb") as buffer: while True: chunk = await file.read(1 << 20) if not chunk: break + bytes_written += len(chunk) + if bytes_written > max_upload_bytes: + raise HTTPException( + status_code=HTTPStatus.REQUEST_ENTITY_TOO_LARGE, + detail=f"Upload exceeds the {max_upload_bytes}-byte limit.", + ) buffer.write(chunk) + except Exception: + stored_path.unlink(missing_ok=True) + raise finally: await file.close() @@ -1107,6 +1114,7 @@ async def upload_document( "task_id": task_id, "original_filename": original_name, "stored_path": str(stored_path), + "size_bytes": bytes_written, } diff --git a/app/api/event_schema.py b/app/api/event_schema.py index 2d94eec..e437d3e 100644 --- a/app/api/event_schema.py +++ b/app/api/event_schema.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel, model_validator +from pydantic import BaseModel, ConfigDict, Field, model_validator from typing import List, Optional, Union, Dict, Any, Literal """ @@ -9,45 +9,51 @@ events entering the system through the API endpoints. """ -class DocumentUploadEvent(BaseModel): +class StrictEvent(BaseModel): + """Base contract that rejects misspelled or unsupported event fields.""" + + model_config = ConfigDict(extra="forbid", str_strip_whitespace=True) + + +class DocumentUploadEvent(StrictEvent): event_type: Literal["document_upload"] filename: str file_url: str doc_type: Optional[str] = None - metadata: Dict[str, Any] + metadata: Dict[str, Any] = Field(default_factory=dict) -class DocumentClassificationEvent(BaseModel): +class DocumentClassificationEvent(StrictEvent): event_type: Literal["document_classification"] document_id: str text: str metadata: Dict[str, Any] -class InformationExtractionEvent(BaseModel): +class InformationExtractionEvent(StrictEvent): event_type: Literal["information_extraction"] document_id: str doc_type: str text: str - fields: List[str] + fields: List[str] = Field(min_length=1, max_length=100) -class SearchQueryEvent(BaseModel): +class SearchQueryEvent(StrictEvent): event_type: Literal["search_query"] query: str filters: Optional[Dict[str, Any]] = None - limit: Optional[int] = None + limit: Optional[int] = Field(default=None, ge=1, le=100) -class DocumentRoutingEvent(BaseModel): +class DocumentRoutingEvent(StrictEvent): event_type: Literal["document_routing"] document_id: str target_department: str reason: str -class DocumentSummaryEvent(BaseModel): +class DocumentSummaryEvent(StrictEvent): event_type: Literal["document_summary"] document_id: Optional[str] = None filename: Optional[str] = None doc_type: Optional[str] = None - chunks_limit: Optional[int] = None + chunks_limit: Optional[int] = Field(default=None, ge=1, le=100) @model_validator(mode="after") def validate_identifier(self): @@ -56,10 +62,10 @@ def validate_identifier(self): return self -class QAQueryEvent(BaseModel): +class QAQueryEvent(StrictEvent): event_type: Literal["qa_query"] query: str - top_k: Optional[int] = None + top_k: Optional[int] = Field(default=None, ge=1, le=50) filters: Optional[Dict[str, Any]] = None # Union of all event types for the single endpoint diff --git a/app/api/router.py b/app/api/router.py index 267ab58..ac0cc16 100644 --- a/app/api/router.py +++ b/app/api/router.py @@ -1,6 +1,6 @@ from fastapi import APIRouter, Depends -from app.api.dependencies import require_api_key +from app.api.dependencies import require_api_key, require_showcase_writable from app.api.endpoint import router as endpoint_router, public_router as public_endpoint_router from app.api.auth_router import router as auth_router @@ -13,7 +13,9 @@ router = APIRouter() -secured_router = APIRouter(dependencies=[Depends(require_api_key)]) +secured_router = APIRouter( + dependencies=[Depends(require_api_key), Depends(require_showcase_writable)] +) secured_router.include_router(endpoint_router, prefix="/events", tags=["events"]) router.include_router(auth_router) diff --git a/app/config/celery_config.py b/app/config/celery_config.py index d3940db..40e3330 100644 --- a/app/config/celery_config.py +++ b/app/config/celery_config.py @@ -46,6 +46,13 @@ def get_celery_config(): "result_serializer": "json", "enable_utc": True, "broker_connection_retry_on_startup": True, + "task_acks_late": True, + "task_reject_on_worker_lost": True, + "task_track_started": True, + "task_time_limit": 600, + "task_soft_time_limit": 540, + "worker_prefetch_multiplier": 1, + "result_expires": 86400, } diff --git a/app/config/database_config.py b/app/config/database_config.py index 73f847e..1bae633 100644 --- a/app/config/database_config.py +++ b/app/config/database_config.py @@ -26,7 +26,7 @@ class DatabaseConfig(BaseSettings): port: str = os.getenv("DATABASE_PORT", "5432") name: str = os.getenv("DATABASE_NAME", "doculens") pg_user: str = os.getenv("DATABASE_USER", "postgres") - password: str = os.getenv("DATABASE_PASSWORD") + password: str = os.getenv("DATABASE_PASSWORD", "") local: bool = False @property @@ -36,4 +36,9 @@ def service_url(self) -> str: return f"postgres://{self.pg_user}:{self.password}@localhost:{self.port}/{self.name}" return f"postgres://{self.pg_user}:{self.password}@{self.host}:{self.port}/{self.name}" + def service_url_for(self, *, local: bool = False) -> str: + """Build a URL without mutating the cached settings singleton.""" + host = "localhost" if local else self.host + return f"postgres://{self.pg_user}:{self.password}@{host}:{self.port}/{self.name}" + vector_store: VectorStoreConfig = VectorStoreConfig() diff --git a/app/config/llm_config.py b/app/config/llm_config.py index 97de355..a7c228c 100644 --- a/app/config/llm_config.py +++ b/app/config/llm_config.py @@ -21,7 +21,7 @@ class LLMProviderSettings(BaseSettings): class OpenAISettings(LLMProviderSettings): """Settings for OpenAI.""" - api_key: str = os.getenv("OPENAI_API_KEY") + api_key: Optional[str] = os.getenv("OPENAI_API_KEY") default_model: str = "gpt-4o" embedding_model: str = "text-embedding-3-small" @@ -29,7 +29,7 @@ class OpenAISettings(LLMProviderSettings): class AnthropicSettings(LLMProviderSettings): """Settings for Anthropic.""" - api_key: str = os.getenv("ANTHROPIC_API_KEY") + api_key: Optional[str] = os.getenv("ANTHROPIC_API_KEY") default_model: str = "claude-3-5-sonnet-20240620" max_tokens: int = 1024 @@ -45,7 +45,7 @@ class LlamaSettings(LLMProviderSettings): class OpenRouterSettings(LLMProviderSettings): """Settings for OpenRouter.""" - api_key: str = os.getenv("OPEN_ROUTER_API_KEY") + api_key: Optional[str] = os.getenv("OPEN_ROUTER_API_KEY") default_model: str = "openai/gpt-4o-mini" base_url: str = "https://openrouter.ai/api/v1" @@ -56,4 +56,4 @@ class LLMConfig(BaseSettings): openai: OpenAISettings = OpenAISettings() anthropic: AnthropicSettings = AnthropicSettings() llama: LlamaSettings = LlamaSettings() - openrouter: OpenRouterSettings = OpenRouterSettings() \ No newline at end of file + openrouter: OpenRouterSettings = OpenRouterSettings() diff --git a/app/config/settings.py b/app/config/settings.py index 29ca4f2..f51fcc6 100644 --- a/app/config/settings.py +++ b/app/config/settings.py @@ -1,44 +1,81 @@ +"""Validated application configuration. + +Environment variables are the public configuration API. Keeping them in one +model makes startup failures explicit and prevents infrastructure clients from +silently inventing their own defaults. +""" + from functools import lru_cache -from typing import Optional +from typing import Literal, Optional -from dotenv import load_dotenv -from pydantic import Field -from pydantic_settings import BaseSettings +from pydantic import Field, field_validator +from pydantic_settings import BaseSettings, SettingsConfigDict from app.config.database_config import DatabaseConfig from app.config.llm_config import LLMConfig -load_dotenv() -""" -Main settings for the application using Pydantic Settings. -""" +class Settings(BaseSettings): + """Runtime settings loaded from environment variables and an optional .env.""" + model_config = SettingsConfigDict(env_file=".env", extra="ignore", case_sensitive=False) -class Settings(BaseSettings): - """Main settings for the application.""" + app_name: str = "DocuLens AI" + environment: Literal["development", "test", "staging", "production"] = Field( + default="development", alias="DOCULENS_ENVIRONMENT" + ) + log_level: str = Field(default="INFO", alias="DOCULENS_LOG_LEVEL") + cors_origins: list[str] = Field( + default_factory=lambda: ["http://localhost:5173"], alias="DOCULENS_CORS_ORIGINS" + ) + initialize_database: bool = Field(default=True, alias="DOCULENS_INITIALIZE_DATABASE") + seed_demo_users: bool = Field(default=False, alias="DOCULENS_SEED_DEMO_USERS") + seed_demo_workspace: bool = Field(default=False, alias="DOCULENS_SEED_DEMO_WORKSPACE") + showcase_read_only: bool = Field(default=False, alias="DOCULENS_SHOWCASE_READ_ONLY") - app_name: str = "Doculens AI" - llm: LLMConfig = LLMConfig() - database: DatabaseConfig = DatabaseConfig() + llm: LLMConfig = Field(default_factory=LLMConfig) + database: DatabaseConfig = Field(default_factory=DatabaseConfig) api_key: Optional[str] = Field(default=None, alias="DOCULENS_API_KEY") api_key_header: str = Field(default="X-API-Key", alias="DOCULENS_API_KEY_HEADER") - summary_chunk_limit: int = Field(default=12, ge=1, alias="DOCULENS_SUMMARY_CHUNK_LIMIT") - qa_top_k: int = Field(default=5, ge=1, alias="DOCULENS_QA_TOP_K") - search_result_limit: int = Field(default=10, ge=1, alias="DOCULENS_SEARCH_RESULT_LIMIT") - search_preview_limit: int = Field(default=5, ge=1, alias="DOCULENS_SEARCH_PREVIEW_LIMIT") - chunk_preview_limit: int = Field(default=25, ge=1, alias="DOCULENS_CHUNK_PREVIEW_LIMIT") + summary_chunk_limit: int = Field(default=12, ge=1, le=100, alias="DOCULENS_SUMMARY_CHUNK_LIMIT") + qa_top_k: int = Field(default=5, ge=1, le=50, alias="DOCULENS_QA_TOP_K") + search_result_limit: int = Field(default=10, ge=1, le=100, alias="DOCULENS_SEARCH_RESULT_LIMIT") + search_preview_limit: int = Field(default=5, ge=1, le=50, alias="DOCULENS_SEARCH_PREVIEW_LIMIT") + chunk_preview_limit: int = Field(default=25, ge=1, le=100, alias="DOCULENS_CHUNK_PREVIEW_LIMIT") + chunk_max_tokens: int = Field(default=800, ge=128, le=4000, alias="DOCULENS_CHUNK_MAX_TOKENS") + embedding_batch_size: int = Field(default=64, ge=1, le=256, alias="DOCULENS_EMBEDDING_BATCH_SIZE") + embedding_cache_size: int = Field(default=1024, ge=0, le=10000, alias="DOCULENS_EMBEDDING_CACHE_SIZE") + provider_timeout_seconds: float = Field(default=30.0, ge=1, le=300, alias="DOCULENS_PROVIDER_TIMEOUT_SECONDS") + max_upload_bytes: int = Field(default=25 * 1024 * 1024, ge=1024, alias="DOCULENS_MAX_UPLOAD_BYTES") auth_secret_key: str = Field(default="doculens-dev-secret", alias="DOCULENS_AUTH_SECRET") auth_algorithm: str = Field(default="HS256", alias="DOCULENS_AUTH_ALGORITHM") auth_token_exp_minutes: int = Field(default=120, ge=5, alias="DOCULENS_AUTH_TOKEN_EXP_MINUTES") + @field_validator("log_level") + @classmethod + def validate_log_level(cls, value: str) -> str: + normalized = value.upper() + if normalized not in {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}: + raise ValueError("DOCULENS_LOG_LEVEL must be a standard Python log level") + return normalized + + def assert_production_safe(self) -> None: + """Reject development credentials that must never reach production.""" + if self.environment == "production" and self.auth_secret_key == "doculens-dev-secret": + raise ValueError("DOCULENS_AUTH_SECRET must be set in production") + if self.environment == "production" and self.seed_demo_users: + raise ValueError("DOCULENS_SEED_DEMO_USERS must be false in production") + if ( + self.environment == "production" + and self.seed_demo_workspace + and not self.showcase_read_only + ): + raise ValueError( + "DOCULENS_SEED_DEMO_WORKSPACE requires DOCULENS_SHOWCASE_READ_ONLY=true in production" + ) + @lru_cache def get_settings() -> Settings: - """ - Get the application settings. - - Returns: - Settings: The application settings. - """ + """Return the immutable-by-convention process configuration singleton.""" return Settings() diff --git a/app/core/observability.py b/app/core/observability.py new file mode 100644 index 0000000..2848109 --- /dev/null +++ b/app/core/observability.py @@ -0,0 +1,33 @@ +"""Small, dependency-free logging and request tracing primitives.""" + +import logging +import time +from uuid import uuid4 + +from fastapi import Request, Response + + +def configure_logging(level: str) -> None: + """Configure consistent process logging for API and worker processes.""" + logging.basicConfig( + level=level, + format="%(asctime)s %(levelname)s %(name)s %(message)s", + force=True, + ) + + +async def request_context_middleware(request: Request, call_next) -> Response: + """Attach a correlation id and emit one structured request completion log.""" + request_id = request.headers.get("X-Request-ID") or uuid4().hex + started = time.perf_counter() + response = await call_next(request) + response.headers["X-Request-ID"] = request_id + logging.getLogger("doculens.http").info( + "request_complete method=%s path=%s status=%s duration_ms=%.2f request_id=%s", + request.method, + request.url.path, + response.status_code, + (time.perf_counter() - started) * 1000, + request_id, + ) + return response diff --git a/app/doc_utils/chunking.py b/app/doc_utils/chunking.py index 5b21c2e..7eb412e 100644 --- a/app/doc_utils/chunking.py +++ b/app/doc_utils/chunking.py @@ -2,15 +2,17 @@ from docling_core.transforms.chunker.hybrid_chunker import HybridChunker +from app.config.settings import get_settings from app.doc_utils.utils.tokenizer import OpenAITokenizerWrapper -# Maximum context length for text-embedding-3-large -MAX_TOKENS: int = 8191 +# Deliberately much smaller than the embedding model limit. Retrieval quality is +# generally better with focused chunks than with page-sized 8k token passages. +DEFAULT_MAX_TOKENS: int = 800 def chunk_document( docling_document: Any, - max_tokens: int = MAX_TOKENS, + max_tokens: int | None = None, merge_peers: bool = True, ) -> List[Any]: """Chunk a Docling document using the HybridChunker. @@ -29,10 +31,11 @@ def chunk_document( if docling_document is None: raise ValueError("Cannot chunk a null document. Ensure extraction succeeded.") + effective_max_tokens = max_tokens or get_settings().chunk_max_tokens tokenizer = OpenAITokenizerWrapper() chunker = HybridChunker( tokenizer=tokenizer, merge_peers=merge_peers, ) - chunk_iter = chunker.chunk(docling_document, max_length=max_tokens) + chunk_iter = chunker.chunk(docling_document, max_length=effective_max_tokens) return list(chunk_iter) diff --git a/app/doc_utils/embedding.py b/app/doc_utils/embedding.py index dc0d782..f2cb837 100644 --- a/app/doc_utils/embedding.py +++ b/app/doc_utils/embedding.py @@ -1,143 +1,110 @@ +"""Chunk preparation and batched embedding persistence.""" + from datetime import datetime, timedelta, timezone +from functools import lru_cache from typing import Any, Dict, List, Optional + import pandas as pd -from openai import OpenAI +from timescale_vector.client import uuid_from_time from app.doc_utils.utils.tokenizer import OpenAITokenizerWrapper from app.services.vector_store import VectorStore -from timescale_vector.client import uuid_from_time - -# Constants -MAX_TOKENS = 8191 # text-embedding-3-large's maximum context length -# Initialize OpenAI client (make sure you have OPENAI_API_KEY in your environment variables) -client = OpenAI() -tokenizer = OpenAITokenizerWrapper() +MAX_EMBEDDING_TOKENS = 8191 -def _normalize_text(text: Optional[str]) -> str: - if not text: - return "" - return text.strip() +@lru_cache(maxsize=1) +def _get_tokenizer() -> OpenAITokenizerWrapper: + """Load tokenizer assets only when an embedding job needs them.""" + return OpenAITokenizerWrapper() -def _prepare_text_for_embedding(text: str) -> str: - token_ids = tokenizer.tokenizer.encode(text) - if len(token_ids) <= MAX_TOKENS: - return text - trimmed = token_ids[:MAX_TOKENS] - return tokenizer.tokenizer.decode(trimmed) +def _prepare_text(text: str) -> str: + normalized = " ".join(text.split()) + tokenizer = _get_tokenizer() + token_ids = tokenizer.tokenizer.encode(normalized) + if len(token_ids) > MAX_EMBEDDING_TOKENS: + return tokenizer.tokenizer.decode(token_ids[:MAX_EMBEDDING_TOKENS]) + return normalized -def _extract_chunk_text(chunk: Any) -> str: - for attr in ("text", "content", "value"): - value = getattr(chunk, attr, None) +def _chunk_text(chunk: Any) -> str: + for attribute in ("text", "content", "value"): + value = getattr(chunk, attribute, None) if value: return str(value) return str(chunk) -def _extract_metadata( +def _chunk_metadata( chunk: Any, document_id: Optional[str], chunk_index: int, token_count: int, - document_metadata: Optional[Dict[str, Any]] = None, + document_metadata: Optional[Dict[str, Any]], ) -> Dict[str, Any]: meta = getattr(chunk, "meta", None) origin = getattr(meta, "origin", None) - filename = getattr(origin, "filename", None) doc_items = getattr(meta, "doc_items", []) or [] - page_numbers = sorted([ - getattr(prov, "page_no") - for item in doc_items - for prov in getattr(item, "prov", []) or [] - if getattr(prov, "page_no", None) is not None - ]) + pages = sorted( + { + page + for item in doc_items + for provenance in (getattr(item, "prov", []) or []) + if (page := getattr(provenance, "page_no", None)) is not None + } + ) headings = getattr(meta, "headings", []) or [] - metadata: Dict[str, Any] = { - "filename": filename, - "page_numbers": page_numbers or None, + "document_id": document_id, + "filename": getattr(origin, "filename", None), + "page_numbers": pages or None, "title": headings[0] if headings else None, "chunk_index": chunk_index, "token_count": token_count, } - if document_id: - metadata["document_id"] = document_id - if document_metadata: - for key, value in document_metadata.items(): - if value is not None: - metadata[key] = value - return metadata + metadata.update({key: value for key, value in (document_metadata or {}).items() if value is not None}) + return {key: value for key, value in metadata.items() if value is not None} def embed_and_upsert_chunks( chunks: List[Any], - embedding_model: str = "text-embedding-3-small", + embedding_model: str | None = None, document_id: Optional[str] = None, document_metadata: Optional[Dict[str, Any]] = None, + vector_store: VectorStore | None = None, ) -> List[Dict[str, Any]]: - """Generate embeddings for Docling chunks and upsert them into the vector store. - - Args: - chunks: List of Docling chunk objects. - embedding_model: Name of the embedding model to use. - document_id: Optional identifier associated with the source document. + """Embed chunks in bounded batches and persist them with citation metadata. - Returns: - List of dictionaries summarising the inserted chunks (safe for serialization). + The optional store is an intentional injection seam: tests and alternative + vector backends do not need to patch module-level SDK clients. """ - if not chunks: + prepared = [_prepare_text(_chunk_text(chunk)) for chunk in chunks] + non_empty = [(chunk, text) for chunk, text in zip(chunks, prepared) if text] + if not non_empty: return [] - raw_texts = [_extract_chunk_text(chunk) for chunk in chunks] - prepared_texts = [_prepare_text_for_embedding(_normalize_text(text)) for text in raw_texts] - token_counts = [tokenizer.count_tokens(text) for text in prepared_texts] - - response = client.embeddings.create(input=prepared_texts, model=embedding_model) - embeddings = [item.embedding for item in response.data] - + store = vector_store or VectorStore() + tokenizer = _get_tokenizer() + texts = [text for _, text in non_empty] + embeddings = store.embed_texts(texts, model=embedding_model) base_time = datetime.now(timezone.utc) - record_ids: List[str] = [ - str(uuid_from_time(base_time + timedelta(microseconds=index))) - for index in range(len(chunks)) - ] - metadata_list = [ - _extract_metadata( - chunk, - document_id, - index, - token_counts[index], - document_metadata=document_metadata, - ) - for index, chunk in enumerate(chunks) + ids = [str(uuid_from_time(base_time + timedelta(microseconds=index))) for index in range(len(texts))] + metadata = [ + _chunk_metadata(chunk, document_id, index, tokenizer.count_tokens(text), document_metadata) + for index, ((chunk, text)) in enumerate(non_empty) ] + store.upsert(pd.DataFrame({"id": ids, "metadata": metadata, "contents": texts, "embedding": embeddings})) - df = pd.DataFrame( + return [ { - "id": record_ids, - "metadata": metadata_list, - "contents": prepared_texts, - "embedding": embeddings, + "id": record_id, + "preview": text[:160], + "token_count": meta["token_count"], + "page_numbers": meta.get("page_numbers"), + "document_id": meta.get("document_id"), + "doc_type": meta.get("doc_type"), + "filename": meta.get("filename"), } - ) - - vector_store = VectorStore() - vector_store.upsert(df) - - chunk_summaries: List[Dict[str, Any]] = [] - for record_id, text, metadata in zip(record_ids, prepared_texts, metadata_list): - chunk_summaries.append( - { - "id": record_id, - "preview": text[:160], - "token_count": metadata.get("token_count"), - "page_numbers": metadata.get("page_numbers"), - "document_id": metadata.get("document_id"), - "doc_type": metadata.get("doc_type"), - "filename": metadata.get("filename"), - } - ) - - return chunk_summaries + for record_id, text, meta in zip(ids, texts, metadata) + ] diff --git a/app/evaluation/__init__.py b/app/evaluation/__init__.py new file mode 100644 index 0000000..dda9657 --- /dev/null +++ b/app/evaluation/__init__.py @@ -0,0 +1 @@ +"""Offline evaluation helpers for retrieval and grounded generation.""" diff --git a/app/evaluation/retrieval.py b/app/evaluation/retrieval.py new file mode 100644 index 0000000..e0d5086 --- /dev/null +++ b/app/evaluation/retrieval.py @@ -0,0 +1,42 @@ +"""Dependency-free retrieval metrics suitable for CI regression tests.""" + +from dataclasses import dataclass +from statistics import mean +from typing import Iterable, Sequence + + +@dataclass(frozen=True) +class RetrievalExample: + """A ranked retrieval result paired with known relevant chunk identifiers.""" + + query: str + retrieved_ids: Sequence[str] + relevant_ids: frozenset[str] + + +def recall_at_k(example: RetrievalExample, k: int) -> float: + """Return the fraction of known relevant chunks retrieved in the top k.""" + if not example.relevant_ids: + return 1.0 + found = set(example.retrieved_ids[:k]) & example.relevant_ids + return len(found) / len(example.relevant_ids) + + +def reciprocal_rank(example: RetrievalExample) -> float: + """Return inverse rank of the first relevant result, or zero.""" + for rank, chunk_id in enumerate(example.retrieved_ids, start=1): + if chunk_id in example.relevant_ids: + return 1.0 / rank + return 0.0 + + +def evaluate(examples: Iterable[RetrievalExample], k: int = 5) -> dict[str, float]: + """Aggregate metrics for a versioned, human-labelled retrieval fixture.""" + cases = list(examples) + if not cases: + return {f"recall@{k}": 0.0, "mrr": 0.0, "examples": 0.0} + return { + f"recall@{k}": mean(recall_at_k(case, k) for case in cases), + "mrr": mean(reciprocal_rank(case) for case in cases), + "examples": float(len(cases)), + } diff --git a/app/main.py b/app/main.py index 3b207f9..f7096b6 100644 --- a/app/main.py +++ b/app/main.py @@ -1,80 +1,33 @@ +"""FastAPI application factory and lifecycle management.""" + import logging -from contextlib import contextmanager +from contextlib import asynccontextmanager, contextmanager +from typing import Iterator from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware +from sqlalchemy.orm import Session -from app.api.router import router as process_router +from app.api.router import router as api_router +from app.config.settings import Settings, get_settings +from app.core.observability import configure_logging, request_context_middleware +from app.database import event as _event_model # noqa: F401 +from app.database import user as _user_model # noqa: F401 from app.database.session import Base, SessionLocal, engine from app.services.auth_service import AuthService +from app.services.demo_workspace import seed_demo_workspace from app.services.vector_store import VectorStore -# ensure model metadata is imported before creating tables -from app.database import event as _event_model # noqa: F401 -from app.database import user as _user_model # noqa: F401 +logger = logging.getLogger(__name__) -app = FastAPI() - -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -app.include_router(process_router) - -DEFAULT_USER_SEED = [ - { - "email": "admin@doculens.ai", - "password": "Admin!234", - "full_name": "Avery Quinn", - "persona": "executive", - "role": "admin", - "access_level": "full", - }, - { - "email": "analyst@doculens.ai", - "password": "Analyst!234", - "full_name": "Jordan Patel", - "persona": "analyst", - "role": "analyst", - }, - { - "email": "reviewer@doculens.ai", - "password": "Reviewer!234", - "full_name": "Morgan Lee", - "persona": "reviewer", - "role": "reviewer", - }, - { - "email": "manager@doculens.ai", - "password": "Manager!234", - "full_name": "Taylor Brooks", - "persona": "manager", - "role": "manager", - }, - { - "email": "developer@doculens.ai", - "password": "Developer!234", - "full_name": "Riley Chen", - "persona": "developer", - "role": "developer", - }, - { - "email": "viewer@doculens.ai", - "password": "Viewer!234", - "full_name": "Skyler James", - "persona": "executive", - "role": "viewer", - "access_level": "minimal", - }, +DEMO_USERS = [ + {"email": "admin@doculens.ai", "password": "Admin!234", "full_name": "Demo Admin", "persona": "executive", "role": "admin"}, + {"email": "analyst@doculens.ai", "password": "Analyst!234", "full_name": "Demo Analyst", "persona": "analyst", "role": "analyst"}, ] @contextmanager -def _session_scope(): +def session_scope() -> Iterator[Session]: session = SessionLocal() try: yield session @@ -86,17 +39,63 @@ def _session_scope(): session.close() -@app.on_event("startup") -def ensure_vector_store_ready() -> None: - """Initialize database requirements and ensure supporting services are warm.""" +def initialize_dependencies(settings: Settings) -> None: + """Initialize local-development resources; migrations own production schema.""" + if not settings.initialize_database: + return Base.metadata.create_all(bind=engine) + if settings.seed_demo_users: + with session_scope() as session: + AuthService(session).ensure_seed_users(DEMO_USERS) + store = VectorStore() + store.create_tables() + store.create_keyword_search_index() + if settings.seed_demo_workspace: + with session_scope() as session: + inserted = seed_demo_workspace( + session, + embedding_dimensions=settings.database.vector_store.embedding_dimensions, + ) + if inserted: + logger.info("Seeded the synthetic local demo workspace") - with _session_scope() as session: - AuthService(session).ensure_seed_users(DEFAULT_USER_SEED) - try: - vector_store = VectorStore() - vector_store.create_tables() - vector_store.create_keyword_search_index() - except Exception as exc: - logging.getLogger(__name__).warning("Unable to initialize vector store: %s", exc) +def create_app(settings: Settings | None = None) -> FastAPI: + """Build an independently configurable application for runtime and tests.""" + runtime = settings or get_settings() + runtime.assert_production_safe() + configure_logging(runtime.log_level) + + @asynccontextmanager + async def lifespan(_: FastAPI): + try: + initialize_dependencies(runtime) + except Exception: + logger.exception("Dependency initialization failed; readiness will remain unhealthy") + yield + + application = FastAPI( + title=runtime.app_name, + version="1.0.0", + description="Asynchronous document intelligence and retrieval API.", + lifespan=lifespan, + ) + application.middleware("http")(request_context_middleware) + application.add_middleware( + CORSMiddleware, + allow_origins=runtime.cors_origins, + allow_credentials=True, + allow_methods=["GET", "POST", "PATCH", "DELETE", "OPTIONS"], + allow_headers=["Authorization", "Content-Type", runtime.api_key_header, "X-Request-ID"], + ) + application.include_router(api_router) + application.include_router(api_router, prefix="/api/v1") + + @application.get("/health/live", tags=["health"], summary="Process liveness") + def liveness() -> dict[str, str]: + return {"status": "ok"} + + return application + + +app = create_app() diff --git a/app/pyproject.toml b/app/pyproject.toml deleted file mode 100644 index bcb067e..0000000 --- a/app/pyproject.toml +++ /dev/null @@ -1,20 +0,0 @@ -[tool.black] -line-length = 135 -target-version = ['py39'] -skip-string-normalization = false -skip-magic-trailing-comma = false -exclude = ''' -/( - \.venv - | \.mypy_cache - | \.pytest_cache - | \.tox - | \.hg - | \.git - | \.svn - | \.ipynb_checkpoints - | dist - | build - | __pycache__ -)/ -''' \ No newline at end of file diff --git a/app/requirements.txt b/app/requirements.txt deleted file mode 100644 index 2c7264c..0000000 --- a/app/requirements.txt +++ /dev/null @@ -1,23 +0,0 @@ -alembic==1.13.1 -anthropic==0.31.2 -celery==5.4.0 -fastapi==0.111.1 -graphviz==0.20.3 -instructor==1.4.0 -ipython==8.31.0 -pandas==2.2.3 -psycopg2-binary==2.9.9 -pydantic==2.10.4 -pydantic-settings==2.7.0 -python-frontmatter==1.1.0 -redis==5.0.3 -timescale-vector==0.0.7 -docling -tiktoken -requests -python-dotenv -openai -pytest==8.3.3 -passlib[bcrypt]==1.7.4 -bcrypt==3.1.7 -python-jose[cryptography]==3.3.0 diff --git a/app/services/demo_workspace.py b/app/services/demo_workspace.py new file mode 100644 index 0000000..bc31e65 --- /dev/null +++ b/app/services/demo_workspace.py @@ -0,0 +1,437 @@ +"""Idempotent synthetic workspace data for local demos and screenshots. + +The seed is deliberately opt-in and contains no customer or maintainer data. It +exercises the same event, classification, and vector tables used by the product +so the local experience stays representative of the real application. +""" + +from __future__ import annotations + +import json +from dataclasses import dataclass +from datetime import datetime, timedelta, timezone +from typing import Sequence +from uuid import NAMESPACE_URL, UUID, uuid1, uuid5 + +from sqlalchemy import text +from sqlalchemy.orm import Session + +from app.database.event import Event +from app.database.models import DocumentClassificationHistory, DocumentLabel + +DEMO_SEED_VERSION = "workspace-v1" + + +@dataclass(frozen=True) +class DemoDocument: + slug: str + filename: str + doc_type: str + role: str + label: str + status: str + uploaded_hours_ago: int + due_hours_from_now: int | None + summary: str | None + bullet_points: tuple[str, ...] + chunks: tuple[str, ...] + + +DEMO_DOCUMENTS: tuple[DemoDocument, ...] = ( + DemoDocument( + slug="acme-msa", + filename="Acme Cloud — Master Services Agreement.pdf", + doc_type="Master Services Agreement", + role="Legal", + label="Commercial Agreement", + status="Ready", + uploaded_hours_ago=2, + due_hours_from_now=120, + summary="A two-year cloud services agreement with a 60-day renewal notice, annual price protection, and a negotiated liability cap.", + bullet_points=( + "Initial term ends September 30, 2026 and renews automatically for one year.", + "Written non-renewal notice is required at least 60 days before the term ends.", + "Aggregate liability is capped at fees paid during the preceding 12 months.", + ), + chunks=( + "The initial service term continues through September 30, 2026. The agreement renews automatically for successive one-year periods unless either party gives written notice at least 60 days before the current term ends.", + "Subscription fees may increase only once per renewal term and any increase may not exceed three percent. Acme must provide written notice of a proposed increase with the renewal notice.", + "Except for confidentiality, data protection, and indemnification obligations, each party's aggregate liability is limited to fees paid or payable during the twelve months preceding the event giving rise to the claim.", + "Customer data remains the exclusive property of Northstar Labs. Acme must return or securely delete customer data within thirty days after termination and provide written confirmation on request.", + ), + ), + DemoDocument( + slug="vendor-risk", + filename="Q3 Vendor Risk Review — Atlas Payments.pdf", + doc_type="Compliance Review", + role="Compliance", + label="Vendor Risk", + status="Needs review", + uploaded_hours_ago=5, + due_hours_from_now=-1, + summary=None, + bullet_points=(), + chunks=( + "Atlas Payments completed its SOC 2 Type II audit in May 2026. Two low-severity exceptions concerned delayed access recertification for contractor accounts.", + "The vendor processes payment metadata in the United States and Ireland. No primary account numbers are stored in the analytics environment.", + "Open action: obtain evidence that quarterly contractor access reviews were completed by July 10. Compliance owner: Maya Chen.", + "Residual risk is rated medium until the access-review evidence is accepted. No critical availability, privacy, or financial-control gaps were identified.", + ), + ), + DemoDocument( + slug="northstar-invoice", + filename="Northstar Cloud Invoice — June 2026.pdf", + doc_type="Invoice", + role="Finance", + label="Accounts Payable", + status="Ready", + uploaded_hours_ago=27, + due_hours_from_now=72, + summary="June cloud infrastructure invoice totaling $18,420, including a material increase in GPU compute and a one-time reserved-capacity credit.", + bullet_points=( + "Amount due is $18,420 by July 21, 2026.", + "GPU compute increased 24% month over month.", + "A $1,250 reserved-capacity credit was applied.", + ), + chunks=( + "Invoice NS-2026-0617 covers the billing period June 1 through June 30, 2026. Total charges are $19,670 before credits and $18,420 after credits.", + "GPU compute usage was 8,240 accelerator-hours at a blended cost of $1.42 per hour, an increase of twenty-four percent compared with May.", + "Reserved-capacity commitment credit: $1,250. Payment terms are net 15 and the payment due date is July 21, 2026.", + "Cost center allocation: AI Platform 62%, Document Operations 23%, Shared Infrastructure 15%.", + ), + ), + DemoDocument( + slug="security-handbook", + filename="Employee Security Handbook — 2026.pdf", + doc_type="Employee Policy", + role="HR", + label="Security Policy", + status="Ready", + uploaded_hours_ago=52, + due_hours_from_now=None, + summary="Company-wide security expectations covering device management, data handling, access reviews, and incident reporting.", + bullet_points=( + "Managed devices and phishing-resistant MFA are required for production access.", + "Suspected incidents must be reported within 30 minutes.", + "Restricted data may not be copied to personal storage or consumer AI tools.", + ), + chunks=( + "All employees and contractors must use a company-managed device and phishing-resistant multi-factor authentication before accessing production systems.", + "Suspected security incidents, including accidental disclosure or lost devices, must be reported to the security channel within thirty minutes of discovery.", + "Restricted customer data must not be copied to personal storage, public paste services, or consumer AI tools. Approved enterprise services must enforce retention controls.", + "Managers review privileged access quarterly. Access that is no longer required must be removed within one business day of the review decision.", + ), + ), + DemoDocument( + slug="incident-runbook", + filename="Production Incident Response Runbook.pdf", + doc_type="Operations Runbook", + role="Operations", + label="Incident Response", + status="Ready", + uploaded_hours_ago=126, + due_hours_from_now=None, + summary="Operational playbook for severity assessment, incident command, customer communications, mitigation, and post-incident review.", + bullet_points=( + "SEV-1 incidents require an incident commander and communications lead within 10 minutes.", + "Customer updates are published at least every 30 minutes.", + "A blameless review is due within five business days.", + ), + chunks=( + "For a SEV-1 incident, assign an incident commander, operations lead, and communications lead within ten minutes of declaration.", + "Publish the first customer-facing status update within fifteen minutes. Continue updates at least every thirty minutes until service is restored.", + "Prefer reversible mitigations such as traffic shaping, feature rollback, or queue isolation. Preserve logs and a timestamped decision record throughout the incident.", + "The incident commander owns a blameless post-incident review within five business days, including contributing factors, detection gaps, and tracked corrective actions.", + ), + ), + DemoDocument( + slug="ai-governance", + filename="AI Governance Research Brief.pdf", + doc_type="Research Brief", + role="Compliance", + label="AI Governance", + status="Ready", + uploaded_hours_ago=242, + due_hours_from_now=None, + summary="A practical control framework for evaluating model risk, grounding quality, human review, and auditability in document AI systems.", + bullet_points=( + "High-impact workflows require human approval and traceable source evidence.", + "Retrieval quality should be evaluated independently from answer quality.", + "Model, prompt, and index versions belong in the audit record.", + ), + chunks=( + "Document AI controls should be proportional to impact. High-impact decisions require human approval, visible source evidence, and a documented appeal path.", + "Teams should evaluate retrieval recall independently from answer faithfulness. A fluent answer cannot compensate for missing or irrelevant evidence.", + "Audit records should include model version, prompt version, index version, retrieved chunk identifiers, reviewer action, and final disposition.", + "Monitoring should cover citation validity, abstention behavior, latency, cost, drift in document mix, and the rate of human overrides.", + ), + ), +) + + +def _stable_uuid(*parts: object) -> UUID: + return uuid5(NAMESPACE_URL, "/".join(("doculens", DEMO_SEED_VERSION, *(str(part) for part in parts)))) + + +def _utc_now_naive() -> datetime: + return datetime.now(timezone.utc).replace(tzinfo=None, microsecond=0) + + +def seed_demo_workspace(session: Session, *, embedding_dimensions: int = 1536) -> bool: + """Seed the synthetic workspace once and return whether rows were inserted.""" + marker_id = _stable_uuid("event", "upload", DEMO_DOCUMENTS[0].slug) + if session.get(Event, marker_id) is not None: + return False + + now = _utc_now_naive() + _seed_labels(session, now) + + chunk_ids_by_slug: dict[str, list[UUID]] = {} + for document in DEMO_DOCUMENTS: + chunk_ids_by_slug[document.slug] = _seed_document(session, document, now, embedding_dimensions) + + _seed_qa_history(session, now) + _seed_search_history(session, now, chunk_ids_by_slug) + session.flush() + return True + + +def _seed_labels(session: Session, now: datetime) -> None: + parents: dict[str, UUID] = {} + for role in sorted({document.role for document in DEMO_DOCUMENTS}): + role_id = _stable_uuid("label", "domain", role) + parents[role] = role_id + session.add( + DocumentLabel( + id=role_id, + label_name=role, + label_type="domain", + description=f"Demo {role.lower()} workspace", + created_at=now, + updated_at=now, + ) + ) + + for document in DEMO_DOCUMENTS: + session.add( + DocumentLabel( + id=_stable_uuid("label", document.label), + label_name=document.label, + label_type="label", + parent_label_id=parents[document.role], + description=f"Synthetic demo label for {document.doc_type.lower()} documents", + created_at=now, + updated_at=now, + ) + ) + + +def _seed_document( + session: Session, + document: DemoDocument, + now: datetime, + embedding_dimensions: int, +) -> list[UUID]: + document_id = f"demo-{document.slug}" + uploaded_at = now - timedelta(hours=document.uploaded_hours_ago) + due_at = now + timedelta(hours=document.due_hours_from_now) if document.due_hours_from_now is not None else None + # Timescale's time-partitioned vector table extracts timestamps from UUIDv1 + # keys, so vector records intentionally use uuid1 rather than stable ids. + chunk_ids = [uuid1() for _ in document.chunks] + metadata = { + "assigned_role": document.role, + "status": document.status, + "due_at": due_at.isoformat() if due_at else None, + "owner": _owner_for_role(document.role), + "page_count": max(2, len(document.chunks)), + "demo_content": True, + "demo_seed": DEMO_SEED_VERSION, + } + upload_data = { + "event_type": "document_upload", + "filename": f"data/demo/{document.filename}", + "doc_type": document.doc_type, + "metadata": { + "uploaded_filename": document.filename, + "status": document.status, + "demo_seed": DEMO_SEED_VERSION, + }, + } + document_context = { + "id": document_id, + "filename": document.filename, + "original_filename": document.filename, + "doc_type": document.doc_type, + "chunk_count": len(document.chunks), + "embedded_chunk_count": len(document.chunks), + "vector_ids": [str(chunk_id) for chunk_id in chunk_ids], + "status": document.status, + "metadata": metadata, + } + session.add( + Event( + id=_stable_uuid("event", "upload", document.slug), + data=upload_data, + task_context={ + "event": upload_data, + "metadata": {"document": document_context}, + "nodes": {"DocumentIngestionNode": {"status": "completed", "chunk_count": len(document.chunks)}}, + }, + created_at=uploaded_at, + updated_at=uploaded_at + timedelta(minutes=6), + ) + ) + + if document.summary: + summary_time = uploaded_at + timedelta(minutes=8) + summary_payload = { + "summary": document.summary, + "bullet_points": list(document.bullet_points), + "next_steps": _next_steps(document), + "source_chunk_count": len(document.chunks), + "doc_type": document.doc_type, + "filename": document.filename, + "document_id": document_id, + "generated_at": summary_time.isoformat(), + } + session.add( + Event( + id=_stable_uuid("event", "summary", document.slug), + data={"event_type": "document_summary", "document_ids": [document_id]}, + task_context={"metadata": {"document_summaries": {document_id: summary_payload}}}, + created_at=summary_time, + updated_at=summary_time, + ) + ) + + session.add( + DocumentClassificationHistory( + id=_stable_uuid("classification", document.slug), + document_id=document_id, + label_name=document.label, + confidence=0.91, + source="ai", + classifier_version="demo-fixture-v1", + notes="Synthetic classification included with the local demo workspace.", + classification_metadata={"demo_seed": DEMO_SEED_VERSION, "role": document.role}, + created_at=uploaded_at + timedelta(minutes=7), + ) + ) + + for index, (chunk_id, contents) in enumerate(zip(chunk_ids, document.chunks), start=1): + chunk_metadata = { + "document_id": document_id, + "filename": document.filename, + "original_filename": document.filename, + "doc_type": document.doc_type, + "assigned_role": document.role, + "chunk_index": index, + "page_number": index, + "demo_seed": DEMO_SEED_VERSION, + } + session.execute( + text( + f""" + INSERT INTO embeddings (id, metadata, contents, embedding) + VALUES ( + :id, + CAST(:metadata AS jsonb), + :contents, + array_fill(0.0::real, ARRAY[{embedding_dimensions}])::vector + ) + ON CONFLICT (id) DO NOTHING + """ + ), + {"id": str(chunk_id), "metadata": json.dumps(chunk_metadata), "contents": contents}, + ) + return chunk_ids + + +def _seed_qa_history(session: Session, now: datetime) -> None: + document = DEMO_DOCUMENTS[0] + document_id = f"demo-{document.slug}" + query = "When do we need to give notice if we do not want the Acme agreement to renew?" + created_at = now - timedelta(hours=1, minutes=18) + reference = { + "reference": f"{document.filename} · page 1 · chunk 1", + "document_id": document_id, + "filename": document.filename, + "chunk_index": 1, + } + session.add( + Event( + id=_stable_uuid("event", "qa", "acme-renewal"), + data={"event_type": "qa_query", "query": query, "filters": {"document_id": document_id}}, + task_context={ + "event": {"event_type": "qa_query", "query": query}, + "metadata": { + "qa": { + "answer": "Send written non-renewal notice no later than August 1, 2026. The agreement requires at least 60 days' notice before the September 30 term end.", + "reasoning": "The renewal clause states both the term end date and the 60-day notice requirement.", + "confidence": 0.96, + "citations": [reference["reference"]], + } + }, + "nodes": {"QAQueryNode": {"chunk_references": [reference]}}, + }, + created_at=created_at, + updated_at=created_at + timedelta(seconds=3), + ) + ) + + +def _seed_search_history(session: Session, now: datetime, chunk_ids_by_slug: dict[str, list[UUID]]) -> None: + query = "documents with upcoming renewal or payment deadlines" + results = [] + for document in (DEMO_DOCUMENTS[0], DEMO_DOCUMENTS[2]): + results.append( + { + "id": str(chunk_ids_by_slug[document.slug][0]), + "contents": document.chunks[0], + "distance": 0.12 if document.slug == "acme-msa" else 0.19, + "metadata": { + "document_id": f"demo-{document.slug}", + "filename": document.filename, + "doc_type": document.doc_type, + "chunk_index": 1, + }, + } + ) + created_at = now - timedelta(minutes=42) + session.add( + Event( + id=_stable_uuid("event", "search", "upcoming-deadlines"), + data={"event_type": "search_query", "query": query, "filters": {}}, + task_context={ + "metadata": {"search": {"query": query, "filters": {}, "limit": 5, "results": results}}, + "nodes": { + "SemanticSearchNode": { + "limit": 5, + "result_count": len(results), + "preview": results, + "results_truncated": False, + } + }, + }, + created_at=created_at, + updated_at=created_at + timedelta(seconds=1), + ) + ) + + +def _owner_for_role(role: str) -> str: + return { + "Compliance": "Maya Chen", + "Finance": "Jordan Ellis", + "HR": "Priya Shah", + "Legal": "Elena Torres", + "Operations": "Noah Williams", + }.get(role, "Demo Analyst") + + +def _next_steps(document: DemoDocument) -> Sequence[str]: + if document.role == "Legal": + return ("Confirm renewal intent with the service owner.", "Calendar the August 1 notice deadline.") + if document.role == "Finance": + return ("Validate the GPU usage increase.", "Route invoice NS-2026-0617 for approval.") + return ("Share the summary with the document owner.",) diff --git a/app/services/vector_store.py b/app/services/vector_store.py index 81eaf05..c32e10c 100644 --- a/app/services/vector_store.py +++ b/app/services/vector_store.py @@ -1,6 +1,8 @@ import logging +from collections import OrderedDict from datetime import datetime from pathlib import Path +from threading import Lock from typing import Any, Dict, List, Optional, Tuple, Union import pandas as pd @@ -25,6 +27,9 @@ class VectorStore: """A class for managing vector operations and database interactions.""" + _embedding_cache: "OrderedDict[tuple[str, str], List[float]]" = OrderedDict() + _cache_lock = Lock() + def __init__(self, local: bool = False): """ Initialize the VectorStore with settings, OpenAI client, and Timescale Vector client. @@ -33,12 +38,17 @@ def __init__(self, local: bool = False): local (bool): If True, overrides .env to use localhost DB for running outside Docker. """ self.settings = get_settings() - self.openai_client = OpenAI(api_key=self.settings.llm.openai.api_key) + self.openai_client = OpenAI( + api_key=self.settings.llm.openai.api_key, + timeout=self.settings.provider_timeout_seconds, + max_retries=self.settings.llm.openai.max_retries, + ) self.embedding_model = self.settings.llm.openai.embedding_model self.vector_settings = self.settings.database.vector_store - self.settings.database.local = local + database_url = self.settings.database.service_url_for(local=local) + self.database_url = database_url self.vec_client = client.Sync( - self.settings.database.service_url, + database_url, self.vector_settings.table_name, self.vector_settings.embedding_dimensions, time_partition_interval=self.vector_settings.time_partition_interval, @@ -52,7 +62,7 @@ def create_keyword_search_index(self): ON {self.vector_settings.table_name} USING gin(to_tsvector('english', contents)); """ try: - with psycopg2.connect(self.settings.database.service_url) as conn: + with psycopg2.connect(self.database_url) as conn: with conn.cursor() as cur: cur.execute(create_index_sql) conn.commit() @@ -70,16 +80,39 @@ def get_embedding(self, text: str) -> List[float]: Returns: A list of floats representing the embedding. """ - text = text.replace("\n", " ") - embedding = ( - self.openai_client.embeddings.create( - input=[text], - model=self.embedding_model, + return self.embed_texts([text])[0] + + def embed_texts(self, texts: List[str], model: Optional[str] = None) -> List[List[float]]: + """Embed texts in bounded batches with a small process-local LRU cache.""" + selected_model = model or self.embedding_model + results: List[Optional[List[float]]] = [None] * len(texts) + missing: List[tuple[int, str, tuple[str, str]]] = [] + with self._cache_lock: + for index, text in enumerate(texts): + key = (selected_model, text.replace("\n", " ")) + cached = self._embedding_cache.get(key) + if cached is None: + missing.append((index, key[1], key)) + else: + self._embedding_cache.move_to_end(key) + results[index] = cached + + batch_size = self.settings.embedding_batch_size + for offset in range(0, len(missing), batch_size): + batch = missing[offset : offset + batch_size] + response = self.openai_client.embeddings.create( + input=[text for _, text, _ in batch], model=selected_model ) - .data[0] - .embedding - ) - return embedding + for (index, _, key), item in zip(batch, response.data): + vector = item.embedding + results[index] = vector + if self.settings.embedding_cache_size: + with self._cache_lock: + self._embedding_cache[key] = vector + self._embedding_cache.move_to_end(key) + while len(self._embedding_cache) > self.settings.embedding_cache_size: + self._embedding_cache.popitem(last=False) + return [vector for vector in results if vector is not None] def create_tables(self) -> None: """Create the necessary tablesin the database""" @@ -252,7 +285,7 @@ def fetch_document_chunks( """ params.append(limit) - with psycopg2.connect(self.settings.database.service_url) as conn: + with psycopg2.connect(self.database_url) as conn: with conn.cursor(cursor_factory=RealDictCursor) as cur: cur.execute(query, params) rows = cur.fetchall() @@ -341,7 +374,7 @@ def keyword_search( LIMIT %s """ - with psycopg2.connect(self.settings.database.service_url) as conn: + with psycopg2.connect(self.database_url) as conn: with conn.cursor(cursor_factory=RealDictCursor) as cur: cur.execute(search_sql, (query, limit)) results = cur.fetchall() diff --git a/app/start.sh b/app/start.sh index 78ed7b1..80970e9 100755 --- a/app/start.sh +++ b/app/start.sh @@ -1,9 +1,7 @@ #!/bin/sh -# Ensure Python can resolve the project package when running inside the container -export PYTHONPATH=${PYTHONPATH:-/} +if [ "${DOCULENS_RUN_MIGRATIONS:-false}" = "true" ]; then + alembic -c /workspace/app/alembic.ini upgrade head +fi -# Uncomment next line to automatically apply Alembic database migrations -# alembic upgrade head - -exec uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload +exec uvicorn app.main:app --host 0.0.0.0 --port 8080 --proxy-headers diff --git a/docker/Caddyfile.showcase b/docker/Caddyfile.showcase new file mode 100644 index 0000000..67db64c --- /dev/null +++ b/docker/Caddyfile.showcase @@ -0,0 +1,26 @@ +{$CADDY_DOMAIN} { + encode zstd gzip + + log { + output stdout + format console + level info + } + + header { + -Server + Referrer-Policy "strict-origin-when-cross-origin" + X-Content-Type-Options "nosniff" + X-Frame-Options "DENY" + Permissions-Policy "camera=(), microphone=(), geolocation=()" + } + + @api path /events* /auth* /api* /health* /docs* /redoc* /openapi.json + handle @api { + reverse_proxy api:8080 + } + + handle { + reverse_proxy frontend:80 + } +} diff --git a/docker/Dockerfile.api b/docker/Dockerfile.api index 3131c5b..e1f93b6 100644 --- a/docker/Dockerfile.api +++ b/docker/Dockerfile.api @@ -6,21 +6,21 @@ RUN apt-get update \ python3-dev \ libpq-dev \ build-essential \ + curl \ && rm -rf /var/lib/apt/lists/* ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 -WORKDIR /app +WORKDIR /workspace -ADD app/requirements.txt . -RUN pip install -r requirements.txt +COPY pyproject.toml README.md ./ +COPY app ./app +RUN pip install --no-cache-dir . -ADD app/ /app - -RUN chmod +x /app/start.sh +RUN chmod +x /workspace/app/start.sh EXPOSE 8080 -CMD ["/app/start.sh"] \ No newline at end of file +CMD ["/workspace/app/start.sh"] diff --git a/docker/Dockerfile.celery b/docker/Dockerfile.celery index acf7acb..85ce31a 100644 --- a/docker/Dockerfile.celery +++ b/docker/Dockerfile.celery @@ -19,16 +19,14 @@ ENV DOCLING_CACHE_DIR=${HOME}/.cache/docling RUN mkdir -p "${EASYOCR_HOME}" "${DOCLING_CACHE_DIR}" \ && chown -R celery:celery /home/celery -WORKDIR /app +WORKDIR /workspace -ADD app/requirements.txt . +COPY pyproject.toml README.md ./ +COPY app ./app +RUN pip install --no-cache-dir . -RUN pip install -r requirements.txt watchdog - -ADD app/ /app - -RUN chown -R celery:celery /app +RUN chown -R celery:celery /workspace USER celery -CMD ["sh", "-c", "watchmedo auto-restart --directory=./ --pattern='*.py' --recursive -- celery -A config.celery_config worker --loglevel=info --concurrency=1"] +CMD ["celery", "-A", "app.config.celery_config", "worker", "--loglevel=info", "--concurrency=2"] diff --git a/docker/Dockerfile.frontend b/docker/Dockerfile.frontend new file mode 100644 index 0000000..f3ad07f --- /dev/null +++ b/docker/Dockerfile.frontend @@ -0,0 +1,12 @@ +FROM node:20-alpine AS build + +WORKDIR /workspace +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci +COPY frontend/ ./ +RUN npm run build + +FROM nginx:1.27-alpine +COPY --from=build /workspace/dist /usr/share/nginx/html +COPY docker/nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 diff --git a/docker/docker-compose.showcase.yml b/docker/docker-compose.showcase.yml new file mode 100644 index 0000000..d20ed26 --- /dev/null +++ b/docker/docker-compose.showcase.yml @@ -0,0 +1,72 @@ +name: ${PROJECT_NAME:-doculens_showcase} + +services: + frontend: + build: + context: .. + dockerfile: docker/Dockerfile.frontend + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"] + interval: 10s + timeout: 3s + retries: 5 + + api: + build: + context: .. + dockerfile: docker/Dockerfile.api + env_file: + - ../${DOCULENS_ENV_FILE:-.env.showcase} + depends_on: + database: + condition: service_healthy + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost:8080/health/live"] + interval: 10s + timeout: 3s + retries: 10 + + caddy: + image: caddy:2.10-alpine + depends_on: + api: + condition: service_healthy + frontend: + condition: service_healthy + environment: + CADDY_DOMAIN: ${CADDY_DOMAIN:?Set CADDY_DOMAIN in .env.showcase} + ports: + - "80:80" + - "443:443" + - "443:443/udp" + restart: unless-stopped + volumes: + - ./Caddyfile.showcase:/etc/caddy/Caddyfile:ro + - caddy_config:/config + - caddy_data:/data + + database: + image: timescale/timescaledb-ha:pg16 + environment: + POSTGRES_DB: ${DATABASE_NAME:?Set DATABASE_NAME in .env.showcase} + POSTGRES_PASSWORD: ${DATABASE_PASSWORD:?Set DATABASE_PASSWORD in .env.showcase} + POSTGRES_USER: ${DATABASE_USER:?Set DATABASE_USER in .env.showcase} + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 5s + retries: 20 + volumes: + - postgres_data:/home/postgres/pgdata + +volumes: + caddy_config: + caddy_data: + postgres_data: + +networks: + default: + name: "${PROJECT_NAME:-doculens_showcase}_network" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 45fc900..1063918 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,29 +1,47 @@ services: + frontend: + build: + context: .. + dockerfile: docker/Dockerfile.frontend + container_name: "${PROJECT_NAME}_frontend" + ports: + - "127.0.0.1:5173:80" + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"] + interval: 10s + timeout: 3s + retries: 5 api: build: context: .. dockerfile: docker/Dockerfile.api container_name: "${PROJECT_NAME}_api" - environment: - - PYTHONPATH=/ depends_on: - - database - - redis + database: + condition: service_healthy + redis: + condition: service_healthy ports: - "127.0.0.1:8080:8080" - restart: always + restart: unless-stopped + env_file: + - ../.env + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost:8080/health/live"] + interval: 10s + timeout: 3s + retries: 5 volumes: - - ./../app/:/app + - ingestion_data:/workspace/data/ingestion caddy: container_name: "${PROJECT_NAME}_caddy" - env_file: - - ./.env image: caddy:latest ports: - "80:80" - "127.0.0.1:2019:2019" - "443:443" - restart: always + restart: unless-stopped volumes: - ./Caddyfile:/etc/caddy/Caddyfile - /var/log/caddy:/var/log/caddy @@ -35,14 +53,18 @@ services: dockerfile: docker/Dockerfile.celery container_name: "${PROJECT_NAME}_celery_worker" depends_on: - - database - - redis - restart: always + database: + condition: service_healthy + redis: + condition: service_healthy + restart: unless-stopped + env_file: + - ../.env environment: - EASYOCR_HOME=/home/celery/.EasyOCR - DOCLING_CACHE_DIR=/home/celery/.cache/docling volumes: - - ./../app:/app + - ingestion_data:/workspace/data/ingestion - easyocr_cache:/home/celery/.EasyOCR - docling_cache:/home/celery/.cache/docling database: @@ -53,8 +75,13 @@ services: POSTGRES_PASSWORD: ${DATABASE_PASSWORD} POSTGRES_USER: ${DATABASE_USER} ports: - - "127.0.0.1:5432:5432" - restart: always + - "127.0.0.1:${DATABASE_EXPOSE_PORT:-5432}:5432" + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 5s + retries: 10 volumes: - postgres_data:/home/postgres/pgdata @@ -70,8 +97,8 @@ services: timeout: 10s image: redis:latest ports: - - "127.0.0.1:6379:6379" - restart: always + - "127.0.0.1:${REDIS_EXPOSE_PORT:-6379}:6379" + restart: unless-stopped volumes: - redis_data:/data @@ -83,9 +110,9 @@ volumes: redis_data: easyocr_cache: docling_cache: + ingestion_data: networks: default: driver: bridge - external: true name: "${PROJECT_NAME}_network" diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..e3527ca --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,16 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location = /health { + access_log off; + return 200 "ok\n"; + add_header Content-Type text/plain; + } +} diff --git a/docs/deploy-showcase.md b/docs/deploy-showcase.md new file mode 100644 index 0000000..d8a347a --- /dev/null +++ b/docs/deploy-showcase.md @@ -0,0 +1,82 @@ +# Deploy the portfolio showcase + +This deployment is intentionally a **read-only product tour**, not a public SaaS trial. Visitors can inspect the synthetic workspace, navigate documents, use global search, and review grounded answers with citations. Uploads, live model calls, classification changes, and destructive actions are removed in the UI and rejected by the API. + +## Recommended shape + +Use one Ubuntu VPS with at least 2 vCPUs and 4 GB RAM. The showcase runs four containers on a private Compose network: + +```text +Internet → Caddy (HTTPS) → React frontend + → FastAPI read API → PostgreSQL + pgvector +``` + +There is no Celery worker in showcase mode because visitors cannot enqueue work. This materially reduces memory use and removes surprise AI-provider spend. The tradeoff is deliberate: the hosted site demonstrates completed pipeline outputs rather than processing arbitrary visitor files. + +## 1. Prepare DNS and the server + +1. Create an Ubuntu VPS and add an `A` record such as `demo.example.com` pointing to its public IPv4 address. +2. Allow inbound TCP 22, 80, and 443 and UDP 443. Keep PostgreSQL private. +3. Install Docker Engine and the Compose plugin using Docker's official Ubuntu instructions. +4. Clone the repository onto the server. + +## 2. Configure the showcase + +```bash +cp .env.showcase.example .env.showcase +openssl rand -hex 32 +openssl rand -base64 36 +``` + +Edit `.env.showcase`: + +- set `CADDY_DOMAIN` to the DNS name; +- put the same HTTPS origin in `DOCULENS_CORS_ORIGINS`; +- replace the auth secret and database password with the generated values. + +Do not add real provider keys. The API blocks all state-changing event routes before a pipeline or provider can run. + +## 3. Launch + +```bash +make showcase-up +docker compose --env-file .env.showcase -f docker/docker-compose.showcase.yml ps +curl --fail https://demo.example.com/health/live +``` + +Caddy obtains and renews the TLS certificate automatically after DNS resolves and ports 80/443 are reachable. The first API startup applies Alembic migrations, creates the vector table/index if absent, and inserts the versioned synthetic workspace. Seeding is idempotent, so restarts do not duplicate data. + +## 4. Update and roll back + +Before an update, record the deployed commit and take a database dump: + +```bash +git rev-parse HEAD +docker compose --env-file .env.showcase -f docker/docker-compose.showcase.yml exec -T database \ + pg_dump -U postgres -d doculens -Fc > doculens-showcase.dump +git pull --ff-only +make showcase-up +``` + +To roll back application code, check out the previously recorded commit and run `make showcase-up` again. Restore the database dump only when a migration is not backward-compatible; routine UI/API rollbacks should not require it. + +## 5. Verify the public boundary + +```bash +# Read succeeds. +curl --fail https://demo.example.com/api/v1/events/config + +# Mutation must return HTTP 403. +curl -i https://demo.example.com/api/v1/events \ + -H 'Content-Type: application/json' \ + -d '{"event_type":"qa_query","query":"test"}' +``` + +Also verify `/`, `/app`, `/app/qa`, `/app/pipeline`, and `/docs` in a private browser window. `/app` should open without credentials and show a visible **Read-only showcase** label. + +## Operational notes + +- Back up the `postgres_data` volume or schedule `pg_dump`; Caddy certificates live in `caddy_data`. +- Use provider/VPS uptime monitoring against `/health/live` and the homepage. +- Keep Docker and the host patched. Rebuild monthly even when application code has not changed. +- This manifest is for a single-node portfolio demo. A real customer deployment would need user-scoped authorization, object storage, managed secrets, a worker, durable provider budgets, and tenant isolation. diff --git a/docs/design-system.md b/docs/design-system.md new file mode 100644 index 0000000..6fafb6e --- /dev/null +++ b/docs/design-system.md @@ -0,0 +1,37 @@ +# DocuLens design system + +DocuLens uses a quiet, evidence-first visual language designed for long document-review sessions. The system intentionally favors hierarchy, legibility, and provenance over decorative dashboard density. + +## Foundations + +- **Typography:** Manrope carries interface and editorial copy; DM Mono is reserved for metadata, shortcuts, identifiers, and technical labels. +- **Color:** porcelain surfaces and ink text form the neutral foundation. Cobalt communicates focus and action; amber marks evidence and citations. Semantic success, warning, and danger colors are limited to real system state. +- **Spacing:** an eight-pixel rhythm governs layout, with four-pixel increments used inside compact controls. +- **Shape:** controls use restrained 10–14 px radii; large marketing surfaces use broader radii to create hierarchy without turning every element into a card. +- **Elevation:** borders establish most grouping. Shadows are reserved for floating navigation, dialogs, menus, and the primary product mockup. + +All values are exposed as semantic CSS variables in `frontend/src/styles/globals.css`. Components consume roles such as `background`, `foreground`, `muted`, `border`, and `primary` instead of raw palette values. + +## Interaction principles + +1. Primary actions are visually unambiguous; secondary actions remain quiet until hover or focus. +2. Every interactive control has a keyboard-visible focus ring and a descriptive accessible label. +3. Motion communicates entrance, progress, or state change. It never blocks input and is disabled when the operating system requests reduced motion. +4. Dark mode is a first-class theme, persisted locally and initialized from the operating-system preference. +5. Product pages preserve working context through a stable sidebar and command search, while public pages use a simpler editorial frame. + +## Component boundaries + +```text +components/ +├── brand/ product identity primitives +├── layout/ application shell and navigation +├── ui/ reusable, domain-neutral controls +└── dashboard/ data visualization and workspace composition +``` + +Domain pages compose primitives but do not redefine their visual states. This keeps accessibility and interaction behavior consistent while allowing document workflows to evolve independently. + +## Performance tradeoffs + +DocuLens uses CSS transitions and keyframes instead of an animation library. This limits orchestration features but avoids adding a runtime dependency for effects that are short, local, and deterministic. Authenticated pages are split at route boundaries so marketing visitors download only the public experience. diff --git a/docs/engineering-notes.md b/docs/engineering-notes.md new file mode 100644 index 0000000..17a3162 --- /dev/null +++ b/docs/engineering-notes.md @@ -0,0 +1,43 @@ +# Engineering notes + +## Scope of the production hardening pass + +This project deliberately remains a modular monolith. The main risks were inconsistent configuration, implicit global clients, unsafe startup defaults, coarse retrieval chunks, unbounded embedding requests, permissive API inputs, and a developer workflow that differed from CI. + +## Major changes + +### Application lifecycle and API versioning + +FastAPI now uses an application factory and lifespan hook. This makes isolated testing possible and gives startup policy one owner. `/api/v1` is the canonical namespace; legacy routes are aliases so the React client is not broken. Database initialization is configurable, demo accounts are opt-in, and production rejects demo credentials. + +Tradeoff: aliases duplicate paths in OpenAPI during the compatibility window. Functionality is otherwise unchanged. + +### Configuration and security + +Operational limits, CORS, environment, logging, provider timeout, chunk size, embedding batches, cache size, and upload size now live in the validated settings model. Vector-store construction no longer mutates the cached database configuration. Uploads are streamed with a hard byte limit and partial files are removed after failure. + +Tradeoff: invalid configuration now fails early instead of being tolerated. This is intentional and does not affect correctly configured environments. + +### Retrieval and embeddings + +The default chunk target changed from the embedding model's 8,191-token ceiling to 800 tokens. Embeddings are requested in bounded batches through an injectable vector-store seam, reuse a bounded in-memory LRU, and retain page/chunk provenance for citations. Recall@K and MRR helpers make future retrieval changes measurable. + +Tokenizer construction is lazy because tiktoken may fetch its vocabulary on first use. API imports, health checks, and unit-test collection therefore remain network-independent; the worker pays initialization cost only when it processes an embedding job. Docling is pinned to the Python 3.12-tested 2.95.0 release to prevent expensive resolver backtracking and surprise parser changes. + +Tradeoff: smaller chunks create more rows and can increase embedding cost. They reduce irrelevant context per hit and make citations more precise. The exact value should be tuned against a labelled corpus. + +### Reliability and observability + +Requests receive correlation ids and emit duration/status logs. Celery uses late acknowledgement, worker-loss rejection, bounded execution time, single-message prefetch, and expiring results. Docker services have readiness ordering and restart policies appropriate for development. + +Tradeoff: late-acknowledged tasks can execute more than once after a crash. Pipeline side effects therefore need to stay idempotent; vector upserts and event-based checks provide a foundation, but full idempotency deserves explicit integration coverage. + +### Developer workflow + +The repository root now owns packaging, Ruff, Pyright, pytest, coverage, Make targets, pre-commit, and a documented environment template. CI installs the same editable development package and executes the same quality gates. + +Tradeoff: contributors using the former `app/requirements.txt` workflow must move to the root editable install. One dependency definition is worth the small migration cost because CI, local development, and containers can no longer drift. + +## Intentionally deferred + +The 1,200-line event endpoint module should be split by documents, labels, QA, search, and insights. Doing that safely requires route-level characterization tests first; moving it mechanically would create diff volume without improving behavior. Durable event status/error columns also require a migration and UI contract, so they are recorded on the roadmap instead of hidden inside JSON. diff --git a/docs/images/landing.jpg b/docs/images/landing.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77f2bfc68095966066e20eea2143467902270e86 GIT binary patch literal 106225 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 -=>C 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 literal 0 HcmV?d00001 diff --git a/docs/images/login.jpg b/docs/images/login.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f6f3c0b1a6dc41e4919f861b49ffe44f9b5a67b3 GIT binary patch literal 63180 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 Rehr#S(dCO_Vb6b9_z$#9(e(fT literal 0 HcmV?d00001 diff --git a/docs/images/work-queues.jpg b/docs/images/work-queues.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54f4f172cce367036c3b3442d8ce99e0e285c5ff GIT binary patch literal 75414 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�FAOIHoL2;%z0T{(4))A0D2!q{tv53T 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%0DN0!Z zy{%rA9?hjGVCc4zAf?w&V53hL?(+7{t!;e?Xg{DO7QO71rCqa159p=mgWqNd2zxgp zgL%lltVdl>F1eO%&i7wD@Z)yg=1@*P&ml5Q!tZlECJqYZQ4L1kNcH`u&rKn=szWaB z_=4Rk;uHtDH9hwi_4!r;JCti@dXuK<^lz8N<)F(-*_fiXLC(u!iw4(aR-1^#zE9#Y zH!w&0L$8ON;y2%O*>mnLF+IS6+@+hhno>J@m!+H47`PA*$y&C=$;mFTLR(cZ7Q1qZ z@&V7;Vddpq10FALM`K@aOo0+1#em)WT=!#A-R+??GkolUXT~*H03+l%Nix!=W$59> z8=o%AA8-M@fP&{}0eTvhYV-kbe|tY?Az$5)+;`kZlj67+g!%E5UY=xDTwIFI&9g9( zo#NgLljIP1WJcW@&AIB0Fac8c_AsX4--qTXXAjfdSfc39hmKmUrz>zqOuCLd)rQF) ztB)$RHsf}zr`+%1Aco2B6rW9 z_Ln!JY#H}{w;X=s#WiOy_68ASK$QY$+lMH97AJeH7nEYzwMfR$ltV!RnkrXmk+rkC zJ5cP(Ed}|;fO%uBgjKFRK-uG&kpxszW>$Ar*O3222xZHUdl}@LJKoP6<^3#$u`u$R zUnuU==L!@A94@?Dl2FswX&X%8dI%lGqMBTS>ss3VF9hpU_jM{5Nu9A0mBZprCWhx; zXm2&b7&c#s!FLr&HMcu=gd)s>1tG#-uJ9p*^aDTeeb=cEMY&kr%x)FPyyN{9Bs3pY zP@>n%pb*r8D!^;MjdyT}N<0inod`+%f%B_1f?53Dc9_!ca$1Z%@4%`{yc3^1W)ihB z(vwc`1ZvN_0}}e=w4$T~B?TVSoV6Lw$w;W5v5;S^-f((n`y0aBkGI8i3nVm~PSVCI z7HYv^Yo#HBBjfa0-LHAJ4j=Kl!X@9SB9$1rw#uYj9&YJX%(W~c7IIzhN^jYy(iPq_ z5((xTSQ6gAv8)JUM)hRH`EzrX`IzN>Tm(-SPE#ID)6lRYb?me_OYv+#_Z+I!_{Pl< zn!}|@vMXeIDXUjy>HHKnr$PvG;LyTye1TDIgYseGyO!NK9pgTBMe=vO%7#PEO!LWN zh1W-W8mORTl-EPtVoJm<;eKS3k|yxB6XIE?qwVh*COk%b8QYf8AACCn(A$2WD^zN@ zbx|c)-In|*RbNs_6q%~q`y=ul)vZTtlX~&Qe&gB8Ow0*yMbG1i(uBuijhKdiCm!U_2gutQ6?ip=?svDst9=#W3mB-}fL3M11=H z5YV>YRjcM&MyG@M&u{&cwEek!D{bbt(w8Yw*=R-=f#>3EQ7!yNx+S~<&%>EK_>pED zs@)Nzi!Ym=HYClTC-Y)|buRp6NM^$>OTE+Z68_baIj|2xTW!DR;eNGb=Ia6J!2L_K z@2{53cm3C;e=OF&mg!GF61rEQQ2u`JY4Jtn0J^H=!4{bt+kxzdR$f2=ZzUJp6h)46&l|RvD T`*#r1e}GB - + - frontend + + + DocuLens AI — Answers that show their work

diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/frontend/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index b280c8b..ee70771 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,17 +4,18 @@ import { Upload, X } from 'lucide-react'; import { AppShell } from './components/layout/AppShell'; import { Button } from './components/ui/button'; -import { useSettings } from './settings/useSettings'; import { useEventNotifications } from './hooks/useEventNotifications'; import { DocumentUploadForm } from './components/DocumentUploadForm'; import type { UploadResponse } from './api/types'; +import { Badge } from './components/ui/badge'; +import { useSettings } from './settings/useSettings'; export function AppLayout() { - const { serverConfig } = useSettings(); const { pathname } = useLocation(); const navigate = useNavigate(); - const appName = serverConfig?.app_name ?? 'DocuLens AI'; - const isIntake = pathname === '/'; + const isIntake = pathname === '/app'; + const { serverConfig } = useSettings(); + const isShowcaseReadOnly = Boolean(serverConfig?.showcase_read_only); const [isUploadOpen, setIsUploadOpen] = useState(false); useEventNotifications(); @@ -30,7 +31,7 @@ export function AppLayout() { const handleUploadComplete = useCallback( (response: UploadResponse) => { setIsUploadOpen(false); - navigate('/pipeline', { replace: false, state: { recentUpload: response.event_id } }); + navigate('/app/pipeline', { replace: false, state: { recentUpload: response.event_id } }); }, [navigate], ); @@ -49,29 +50,34 @@ export function AppLayout() { return ( <> - - New Upload - + isShowcaseReadOnly ? ( + + Read-only showcase + + ) : ( + + ) } > - {isUploadOpen ? ( -
+ {isUploadOpen && !isShowcaseReadOnly ? ( +

- Upload & ingest documents + Add documents

-

Drop in PDFs or scans to fast-track routing and review.

+

Upload PDFs, scans, or text files to your workspace.

+ {!isShowcaseReadOnly ? <> - {isArchived ? ( + : Curated result}
@@ -557,7 +566,7 @@ export function DocumentDetail({ document, onEventQueued }: DocumentDetailProps) {pendingAction && confirmConfig ? (
-
+
@@ -633,7 +642,7 @@ export function DocumentDetail({ document, onEventQueued }: DocumentDetailProps) Document classification - {displaySource ? `Latest label generated by ${displaySource}.` : 'Predicted label for this document.'} + {displaySource ? `Latest label generated by ${displaySource.toLowerCase() === 'ai' ? 'AI' : displaySource}.` : 'Predicted label for this document.'} @@ -674,7 +683,7 @@ export function DocumentDetail({ document, onEventQueued }: DocumentDetailProps)
) : null} -
+ {!isShowcaseReadOnly ?

Override classification

{candidateLabels.length ? (
@@ -729,7 +738,7 @@ export function DocumentDetail({ document, onEventQueued }: DocumentDetailProps) {isOverriding ? 'Saving…' : 'Save override'}
-
+
: null}

Classification history

@@ -785,10 +794,10 @@ export function DocumentDetail({ document, onEventQueued }: DocumentDetailProps) Summaries help reviewers get context before diving into stage progress. - + : Curated result} @@ -803,15 +812,15 @@ function ProcessingTimeline({ stages }: { stages: ReturnType Processing status - Where this document is in the digitisation journey. + Extraction, indexing, summary, and assignment progress. {stages.map((stage) => ( -
+
{stage.state === 'complete' ? ( - + ) : stage.state === 'active' ? ( - + ) : ( )} diff --git a/frontend/src/components/DocumentList.tsx b/frontend/src/components/DocumentList.tsx index 4d4e4a7..70732d2 100644 --- a/frontend/src/components/DocumentList.tsx +++ b/frontend/src/components/DocumentList.tsx @@ -1,11 +1,10 @@ import { useMemo, useState } from 'react'; -import { Clock, FileText } from 'lucide-react'; +import { Clock, FileText, Search } from 'lucide-react'; import type { DocumentEntry } from '../api/types'; import { cn } from '../lib/utils'; import { inferDueDate, inferRole, inferStatus, formatDateTime } from '../lib/routing'; import { Badge } from './ui/badge'; -import { Card, CardContent, CardHeader, CardTitle } from './ui/card'; import { Input } from './ui/input'; export interface DocumentListProps { @@ -30,23 +29,21 @@ export function DocumentList({ documents, onSelect, selectedId }: DocumentListPr }, [documents, filter]); return ( - - -
- Documents - - {documents.length} - -
+
+
+ setFilter(event.target.value)} - className="h-10 rounded-lg border-platinum-600" + className="h-10 rounded-xl border-border/70 bg-surface-subtle pl-9" /> - - + + {filtered.length} + +
+
{filtered.map((doc) => { const isSelected = doc.document_id === selectedId; @@ -60,12 +57,12 @@ export function DocumentList({ documents, onSelect, selectedId }: DocumentListPr key={doc.document_id} onClick={() => onSelect(doc)} className={cn( - 'w-full rounded-lg border border-platinum-600 bg-white px-4 py-3 text-left transition-colors hover:border-lapis-500/40 hover:bg-sky-blue-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-lapis-500/40', - isSelected ? 'border-lapis-500 bg-sky-blue-900 shadow-sm' : '', + 'w-full rounded-xl border border-border/70 bg-background px-4 py-3 text-left transition-colors hover:border-primary/30 hover:bg-surface-subtle focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30', + isSelected ? 'border-primary/40 bg-primary/[0.06] shadow-sm ring-1 ring-primary/15' : '', )} >
-
+
@@ -103,7 +100,7 @@ export function DocumentList({ documents, onSelect, selectedId }: DocumentListPr
) : null}
- - +
+
); } diff --git a/frontend/src/components/DocumentUploadForm.tsx b/frontend/src/components/DocumentUploadForm.tsx index b23bae0..8659972 100644 --- a/frontend/src/components/DocumentUploadForm.tsx +++ b/frontend/src/components/DocumentUploadForm.tsx @@ -266,7 +266,7 @@ export function DocumentUploadForm({ onUploaded }: DocumentUploadFormProps) { value={docType} onChange={(event) => setDocType(event.target.value)} /> -

Optional label used by downstream pipelines.

+

Optional type used to organize the document and guide review.

@@ -280,7 +280,7 @@ export function DocumentUploadForm({ onUploaded }: DocumentUploadFormProps) { {metadataError ? (

{metadataError}

) : ( -

Attach structured hints for routing or extraction.

+

Attach optional structured context for processing and assignment.

)}
@@ -297,7 +297,7 @@ export function DocumentUploadForm({ onUploaded }: DocumentUploadFormProps) { {queue.map((item) => (
  • diff --git a/frontend/src/components/brand/Logo.tsx b/frontend/src/components/brand/Logo.tsx new file mode 100644 index 0000000..ac79777 --- /dev/null +++ b/frontend/src/components/brand/Logo.tsx @@ -0,0 +1,19 @@ +import { Link } from 'react-router-dom'; +import { ScanText } from 'lucide-react'; + +import { cn } from '../../lib/utils'; + +export function Logo({ compact = false, className }: { compact?: boolean; className?: string }) { + return ( + + + + + {!compact ? ( + + DocuLens AI + + ) : null} + + ); +} diff --git a/frontend/src/components/dashboard/PersonaQuickstart.tsx b/frontend/src/components/dashboard/PersonaQuickstart.tsx index a6a46fc..9592616 100644 --- a/frontend/src/components/dashboard/PersonaQuickstart.tsx +++ b/frontend/src/components/dashboard/PersonaQuickstart.tsx @@ -53,7 +53,7 @@ interface QuickstartActionCardProps { function QuickstartActionCard({ title, description, href }: QuickstartActionCardProps) { return ( -
    +

    {title}

    {description}

    diff --git a/frontend/src/components/dashboard/personaConfig.ts b/frontend/src/components/dashboard/personaConfig.ts index e3def19..39fe813 100644 --- a/frontend/src/components/dashboard/personaConfig.ts +++ b/frontend/src/components/dashboard/personaConfig.ts @@ -24,7 +24,7 @@ export const PERSONA_CONFIG: Record = { { title: 'QA the latest batch', description: 'Run targeted QA across priority documents with citations.', - href: '/qa', + href: '/app/qa', }, { title: 'Approve summaries', @@ -41,17 +41,17 @@ export const PERSONA_CONFIG: Record = { { title: 'Scan today’s KPIs', description: 'Check dashboards for SLA risks and backlog growth.', - href: '/work-queues', + href: '/app/work-queues', }, { title: 'Coach reviewers', description: 'Spot coaching opportunities by filtering documents awaiting approval.', - href: '/pipeline', + href: '/app/pipeline', }, { title: 'Broadcast status', description: 'Share quality and savings snapshots upstream.', - href: '/settings', + href: '/app/settings', }, ], }, @@ -63,7 +63,7 @@ export const PERSONA_CONFIG: Record = { { title: 'Triage review queue', description: 'Filter for documents awaiting human approval and add feedback.', - href: '/work-queues', + href: '/app/work-queues', }, { title: 'Escalate edge cases', @@ -85,17 +85,17 @@ export const PERSONA_CONFIG: Record = { { title: 'Sync API credentials', description: 'Confirm API key headers in Settings match environment config.', - href: '/settings', + href: '/app/settings', }, { title: 'Monitor job feed', description: 'Review QA/search results for anomalies or retriable failures.', - href: '/qa', + href: '/app/qa', }, { title: 'Inspect embedding health', description: 'Check pipeline diagnostics for drift or processing gaps.', - href: '/settings', + href: '/app/settings', }, ], }, @@ -117,7 +117,7 @@ export const PERSONA_CONFIG: Record = { { title: 'Align roadmap', description: 'Spot gaps in coverage and align teams on next investments.', - href: '/settings', + href: '/app/settings', }, ], }, diff --git a/frontend/src/components/layout/AppShell.tsx b/frontend/src/components/layout/AppShell.tsx index 6fd3ef2..1851faa 100644 --- a/frontend/src/components/layout/AppShell.tsx +++ b/frontend/src/components/layout/AppShell.tsx @@ -1,16 +1,34 @@ import { type FormEvent, type ReactNode, useEffect, useState } from 'react'; -import { NavLink, useNavigate } from 'react-router-dom'; -import { LayoutDashboard, UsersRound, GitBranch, MessageSquare, Settings, Search, Plus, Loader2 } from 'lucide-react'; +import { NavLink, useLocation, useNavigate } from 'react-router-dom'; +import { + Activity, + ChevronsUpDown, + Command, + FileStack, + FolderKanban, + LayoutDashboard, + Loader2, + Menu, + MessageSquareText, + PanelLeftClose, + PanelLeftOpen, + Plus, + Search, + Settings, + Sparkles, + X, +} from 'lucide-react'; -import { Button } from '../ui/button'; -import { Input } from '../ui/input'; +import { fetchDocuments } from '../../api/client'; +import type { DocumentEntry } from '../../api/types'; import { cn } from '../../lib/utils'; -import { Badge } from '../ui/badge'; +import { useUIStore } from '../../stores/uiStore'; +import { Logo } from '../brand/Logo'; import { NotificationBell } from '../notifications/NotificationBell'; import { NotificationToaster } from '../notifications/NotificationToaster'; import { ProfileMenu } from '../profile/ProfileMenu'; -import { fetchDocuments } from '../../api/client'; -import type { DocumentEntry } from '../../api/types'; +import { Button } from '../ui/button'; +import { ThemeToggle } from '../ui/theme-toggle'; interface AppShellProps { headerAction?: ReactNode; @@ -20,249 +38,196 @@ interface AppShellProps { onLaunchUpload?: () => void; } -const NAV_ITEMS = [ - { to: '/', label: 'Intake', icon: LayoutDashboard }, - { to: '/work-queues', label: 'Work Queues', icon: UsersRound }, - { to: '/pipeline', label: 'Pipeline', icon: GitBranch }, - { to: '/qa', label: 'QA Studio', icon: MessageSquare }, - { to: '/settings', label: 'Settings', icon: Settings }, +const PRIMARY_NAV = [ + { to: '/app', label: 'Overview', icon: LayoutDashboard, end: true }, + { to: '/app/qa', label: 'Ask DocuLens', icon: MessageSquareText }, + { to: '/app/pipeline', label: 'Documents', icon: FileStack }, + { to: '/app/work-queues', label: 'Work queues', icon: FolderKanban }, ]; -const PLAYBOOK_STEPS = [ - { - title: 'Intake', - description: 'Upload the paperwork, confirm detected fields, and tag urgency so processing kicks off instantly.', - }, - { - title: 'Routing', - description: 'DocuLens routes items by type, risk, and region—manual overrides stay tracked for audit.', - }, - { - title: 'Resolution', - description: 'Review the AI summary, add notes, and complete checklist items before exporting decisions.', - }, +const SECONDARY_NAV = [ + { to: '/app/pipeline', label: 'Activity', icon: Activity }, + { to: '/app/settings', label: 'Settings', icon: Settings }, ]; -export function AppShell({ - headerAction, - children, - productName = 'DocuLens AI', - productTagline = 'Digitize every document. Route every task.', - onLaunchUpload, -}: AppShellProps) { +const PAGE_META: Record = { + '/app': { title: 'Workspace', description: 'Your documents, decisions, and active work in one place.' }, + '/app/qa': { title: 'Ask DocuLens', description: 'Explore your documents with answers grounded in source evidence.' }, + '/app/pipeline': { title: 'Documents', description: 'Review summaries, classifications, source content, and processing status.' }, + '/app/work-queues': { title: 'Work queues', description: 'Route documents to the right team and keep decisions moving.' }, + '/app/settings': { title: 'Workspace settings', description: 'Configure models, retrieval, access, and preferences.' }, +}; + +export function AppShell({ headerAction, children, onLaunchUpload }: AppShellProps) { + const { pathname } = useLocation(); const navigate = useNavigate(); + const { isSidebarOpen, isSidebarCollapsed, toggleSidebar, toggleSidebarCollapsed } = useUIStore(); + const [isCommandOpen, setIsCommandOpen] = useState(false); const [searchValue, setSearchValue] = useState(''); - const [isSearchActive, setIsSearchActive] = useState(false); const [searchResults, setSearchResults] = useState([]); const [isSearching, setIsSearching] = useState(false); const [searchError, setSearchError] = useState(null); + const page = PAGE_META[pathname] ?? PAGE_META['/app']; useEffect(() => { - const trimmed = searchValue.trim().toLowerCase(); - if (!trimmed) { + const handleKey = (event: KeyboardEvent) => { + if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') { + event.preventDefault(); + setIsCommandOpen((open) => !open); + } + if (event.key === 'Escape') { + setIsCommandOpen(false); + toggleSidebar(false); + } + }; + window.addEventListener('keydown', handleKey); + return () => window.removeEventListener('keydown', handleKey); + }, [toggleSidebar]); + + useEffect(() => { + const query = searchValue.trim().toLowerCase(); + if (!query) { setSearchResults([]); setSearchError(null); - setIsSearching(false); return; } - let cancelled = false; setIsSearching(true); - - const timer = setTimeout(async () => { - try { - const docs = await fetchDocuments(150); - if (cancelled) return; - - const filtered = docs.filter((doc) => { - const status = (doc.status ?? '').toLowerCase(); - if (status === 'deleted') { - return false; - } - const haystack = [ - doc.filename, - doc.doc_type, - doc.summary?.summary, - doc.document_id, - doc.metadata ? JSON.stringify(doc.metadata) : '', - ] - .filter(Boolean) - .join(' ') - .toLowerCase(); - return haystack.includes(trimmed); - }); - - if (cancelled) return; - setSearchResults(filtered.slice(0, 5)); - setSearchError(filtered.length ? null : `No results for “${searchValue.trim()}”.`); - } catch (error) { + const timer = window.setTimeout(() => { + fetchDocuments(150) + .then((documents) => { if (cancelled) return; - const message = error instanceof Error ? error.message : 'Unable to search documents.'; - setSearchError(message); - setSearchResults([]); - } finally { - if (!cancelled) { - setIsSearching(false); - } - } - }, 200); - - return () => { - cancelled = true; - clearTimeout(timer); - }; + const matches = documents.filter((document) => [document.filename, document.doc_type, document.summary?.summary, document.document_id].filter(Boolean).join(' ').toLowerCase().includes(query)); + setSearchResults(matches.slice(0, 6)); + setSearchError(matches.length ? null : `No documents match “${searchValue.trim()}”`); + }) + .catch((error: unknown) => !cancelled && setSearchError(error instanceof Error ? error.message : 'Search is unavailable.')) + .finally(() => !cancelled && setIsSearching(false)); + }, 160); + return () => { cancelled = true; window.clearTimeout(timer); }; }, [searchValue]); - const handleSearchSubmit = (event: FormEvent) => { - event.preventDefault(); - if (searchValue.trim()) { - setIsSearchActive(true); - } + const selectDocument = (id: string) => { + navigate(`/app/pipeline?document=${id}`); + setIsCommandOpen(false); + setSearchValue(''); }; - const handleResultSelect = (documentId: string) => { - navigate(`/pipeline?document=${documentId}`); + const openDestination = (path: string) => { + navigate(path); + setIsCommandOpen(false); setSearchValue(''); - setSearchResults([]); - setSearchError(null); - setIsSearchActive(false); }; return ( -
    - -
    -
    -
    -
    -
    -
    - - setSearchValue(event.target.value)} - onFocus={() => setIsSearchActive(true)} - onBlur={() => setTimeout(() => setIsSearchActive(false), 150)} - placeholder="Search documents, teams, or tags…" - aria-label="Search workspace" - className="h-10 rounded-full border border-platinum-600 bg-white pl-10 pr-4 shadow" - /> - {(isSearchActive && searchValue.trim()) || (searchError && searchValue.trim()) ? ( -
    - {isSearching ? ( -
    - - Searching… -
    - ) : searchResults.length ? ( -
      - {searchResults.map((doc) => ( -
    • - -
    • - ))} -
    - ) : ( -
    - {searchError ?? `No results for “${searchValue.trim()}”.`} -
    - )} -
    - ) : null} - -
    -
    - - {headerAction} - -
    -
    - +
    +
    +
    + + +
    {headerAction}
    -
    {children}
    +
    +
    +
    +

    {page.title}

    {page.description}

    + All systems operational +
    + {children} +
    +
    + {isCommandOpen ? ( +
    setIsCommandOpen(false)}> +
    event.stopPropagation()}> +
    +
    event.preventDefault()} className="flex h-12 items-center gap-3 rounded-xl border border-border/80 bg-surface-subtle px-3 shadow-sm transition focus-within:border-primary/50 focus-within:ring-4 focus-within:ring-primary/10"> + + setSearchValue(event.target.value)} placeholder="Search documents and summaries…" className="h-full min-w-0 flex-1 appearance-none border-0 bg-transparent p-0 text-sm text-foreground shadow-none outline-none placeholder:text-muted-foreground focus:border-0 focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0" /> + + +
    +
    + {!searchValue.trim() ? : isSearching ?
    Searching your workspace…
    : searchResults.length ? searchResults.map((document) => ) :

    {searchError}

    } +
    +
    +
    + ) : null}
    ); } -function navLinkPillClass(isActive: boolean) { - return cn( - 'rounded-full border px-3 py-1 text-sm transition-colors', - isActive ? 'border-border bg-card text-foreground' : 'border-transparent text-muted-foreground hover:border-border hover:bg-card', - ); +function SidebarLink({ to, label, icon: Icon, end, collapsed, onClick }: { to: string; label: string; icon: typeof LayoutDashboard; end?: boolean; collapsed: boolean; onClick: () => void }) { + return cn('group flex items-center gap-2.5 rounded-xl px-3 py-2.5 text-xs font-medium transition-all', collapsed && 'lg:justify-center lg:px-2', isActive ? 'bg-background text-foreground shadow-sm ring-1 ring-border/70' : 'text-muted-foreground hover:bg-background/70 hover:text-foreground')}>{label}; } - -function sidebarLinkClass(isActive: boolean) { - return cn( - 'group flex items-center gap-3 rounded-xl px-4 py-2 text-sm font-medium transition-all', - isActive - ? 'bg-gradient-to-r from-lapis-500/15 via-lapis-500/10 to-transparent text-lapis-600 shadow-[0_12px_32px_rgba(47,102,144,0.18)] ring-1 ring-inset ring-lapis-500/40 backdrop-blur-sm' - : 'text-muted-foreground hover:bg-lapis-500/5 hover:text-foreground', +function ChevronHint() { return ; } +function CommandEmpty({ onNavigate }: { onNavigate: (path: string) => void }) { + return ( +
    +

    Quick actions

    + + +
    ); } diff --git a/frontend/src/components/notifications/ActivityFeed.tsx b/frontend/src/components/notifications/ActivityFeed.tsx index e55e675..22acc3e 100644 --- a/frontend/src/components/notifications/ActivityFeed.tsx +++ b/frontend/src/components/notifications/ActivityFeed.tsx @@ -1,6 +1,9 @@ -import { type ComponentType } from 'react'; -import { Activity, Brain, FileText, MessageSquare, RefreshCw } from 'lucide-react'; +import { type ComponentType, useMemo } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { Activity, Brain, FileText, MessageSquare, RefreshCw, Search } from 'lucide-react'; +import { fetchEvents } from '../../api/client'; +import type { EventEntry } from '../../api/types'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card'; import { Button } from '../ui/button'; import { useNotificationStore } from '../../stores/notificationStore'; @@ -9,31 +12,49 @@ const iconMap: Record> = { upload: FileText, summary: Brain, qa: MessageSquare, + search: Search, default: Activity, }; export function ActivityFeed({ limit = 2 }: { limit?: number }) { - const notifications = useNotificationStore((state) => state.notifications).slice(0, limit); + const notifications = useNotificationStore((state) => state.notifications); + const { data: events = [], isFetching, refetch } = useQuery({ + queryKey: ['workspace-activity', limit], + queryFn: () => fetchEvents(Math.max(limit * 3, 10)), + }); + const activity = useMemo(() => { + const localItems: ActivityItem[] = notifications.map((item) => ({ + id: item.id, + title: item.title, + description: item.description, + timestamp: item.timestamp, + variant: 'default', + })); + const eventItems = events.map(toActivityItem).filter((item): item is ActivityItem => item !== null); + return [...localItems, ...eventItems] + .sort((first, second) => second.timestamp - first.timestamp) + .slice(0, limit); + }, [events, limit, notifications]); return (
    Recent activity - Key pipeline events from the past few minutes. + Recent searches, answers, summaries, and uploads.
    -
    - {notifications.length === 0 ? ( + {activity.length === 0 ? (

    Actions taken in the console will appear here.

    ) : ( - notifications.map((item) => { + activity.map((item) => { const Icon = iconMap[item.variant] ?? iconMap.default; return ( -
    +

    {item.title}

    @@ -50,3 +71,73 @@ export function ActivityFeed({ limit = 2 }: { limit?: number }) { ); } + +interface ActivityItem { + id: string; + title: string; + description?: string; + timestamp: number; + variant: string; +} + +function toActivityItem(event: EventEntry): ActivityItem | null { + const eventType = stringValue(event.data.event_type); + const timestamp = Date.parse(event.created_at); + if (!eventType || Number.isNaN(timestamp)) return null; + + if (eventType === 'document_upload') { + const metadata = objectValue(event.data.metadata); + const filename = stringValue(metadata.uploaded_filename) ?? stringValue(event.data.filename) ?? 'Document'; + return { + id: event.id, + title: 'Document indexed', + description: filename.split('/').pop(), + timestamp, + variant: 'upload', + }; + } + + if (eventType === 'document_summary') { + const context = objectValue(event.task_context); + const metadata = objectValue(context.metadata); + const summaries = objectValue(metadata.document_summaries); + const firstSummary = objectValue(Object.values(summaries)[0]); + return { + id: event.id, + title: 'Summary completed', + description: stringValue(firstSummary.filename) ?? 'Document summary is ready', + timestamp, + variant: 'summary', + }; + } + + if (eventType === 'qa_query') { + return { + id: event.id, + title: 'Grounded answer generated', + description: stringValue(event.data.query), + timestamp, + variant: 'qa', + }; + } + + if (eventType === 'search_query') { + return { + id: event.id, + title: 'Semantic search completed', + description: stringValue(event.data.query), + timestamp, + variant: 'search', + }; + } + + return null; +} + +function objectValue(value: unknown): Record { + return value && typeof value === 'object' && !Array.isArray(value) ? value as Record : {}; +} + +function stringValue(value: unknown): string | undefined { + return typeof value === 'string' && value.trim() ? value : undefined; +} diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx index 52830c7..c99e8ec 100644 --- a/frontend/src/components/ui/button.tsx +++ b/frontend/src/components/ui/button.tsx @@ -5,22 +5,22 @@ import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '../../lib/utils'; const buttonVariants = cva( - 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background', + 'inline-flex items-center justify-center whitespace-nowrap rounded-xl text-sm font-semibold transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98] ring-offset-background', { variants: { variant: { - default: 'bg-primary text-primary-foreground shadow-subtle hover:bg-primary/90', + default: 'bg-foreground text-background shadow-sm hover:bg-foreground/90 dark:bg-primary dark:text-primary-foreground dark:hover:bg-primary/90', secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', - accent: 'bg-accent text-accent-foreground shadow-subtle hover:bg-accent/85', - outline: 'border border-border bg-transparent hover:bg-muted', - ghost: 'hover:bg-muted hover:text-foreground', + accent: 'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90', + outline: 'border border-border bg-background hover:border-muted-foreground/30 hover:bg-muted/60', + ghost: 'hover:bg-muted/70 hover:text-foreground', destructive: 'bg-destructive text-destructive-foreground shadow-subtle hover:bg-destructive/80', muted: 'bg-muted text-muted-foreground hover:bg-muted/80', }, size: { default: 'h-10 px-4 py-2', - sm: 'h-9 rounded-md px-3', - lg: 'h-11 rounded-md px-5 text-base', + sm: 'h-9 rounded-lg px-3', + lg: 'h-11 rounded-xl px-5 text-base', icon: 'h-10 w-10', }, }, diff --git a/frontend/src/components/ui/card.tsx b/frontend/src/components/ui/card.tsx index cefddb1..0d717e0 100644 --- a/frontend/src/components/ui/card.tsx +++ b/frontend/src/components/ui/card.tsx @@ -7,7 +7,7 @@ export const Card = React.forwardRef(({ className ref={ref} type={type} className={cn( - 'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-none transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50', + 'flex h-10 w-full rounded-xl border border-input bg-background px-3 py-2 text-sm shadow-sm transition-all placeholder:text-muted-foreground focus:border-primary/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/15 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50', className, )} {...props} diff --git a/frontend/src/components/ui/theme-toggle.tsx b/frontend/src/components/ui/theme-toggle.tsx new file mode 100644 index 0000000..d59e7aa --- /dev/null +++ b/frontend/src/components/ui/theme-toggle.tsx @@ -0,0 +1,25 @@ +import { useEffect, useState } from 'react'; +import { Moon, Sun } from 'lucide-react'; + +import { Button } from './button'; + +function readTheme() { + if (typeof window === 'undefined') return false; + const stored = window.localStorage.getItem('doculens.theme'); + return stored ? stored === 'dark' : window.matchMedia('(prefers-color-scheme: dark)').matches; +} + +export function ThemeToggle() { + const [dark, setDark] = useState(readTheme); + + useEffect(() => { + document.documentElement.classList.toggle('dark', dark); + window.localStorage.setItem('doculens.theme', dark ? 'dark' : 'light'); + }, [dark]); + + return ( + + ); +} diff --git a/frontend/src/hooks/useEventNotifications.ts b/frontend/src/hooks/useEventNotifications.ts index 5070c60..c31dad7 100644 --- a/frontend/src/hooks/useEventNotifications.ts +++ b/frontend/src/hooks/useEventNotifications.ts @@ -94,7 +94,7 @@ export function useEventNotifications() { title: 'QA answer ready', description: entry.answer ? `${entry.answer.slice(0, 80)}…` : entry.query, variant: 'success', - href: '/qa', + href: '/app/qa', timestamp: Number.isNaN(occurredAt) ? undefined : occurredAt, }); } @@ -115,7 +115,7 @@ export function useEventNotifications() { title: 'Search results updated', description: `${entry.query} (${entry.result_count} results)`, variant: 'info', - href: '/qa', + href: '/app/qa', timestamp: Number.isNaN(occurredAt) ? undefined : occurredAt, }); } diff --git a/frontend/src/lib/pipeline.ts b/frontend/src/lib/pipeline.ts new file mode 100644 index 0000000..dff5a55 --- /dev/null +++ b/frontend/src/lib/pipeline.ts @@ -0,0 +1,47 @@ +import type { DocumentEntry } from '../api/types'; +import { inferRole, inferStatus } from './routing'; + +export interface PipelineStage { + id: 'upload' | 'extraction' | 'embedding' | 'summary' | 'routing'; + label: string; + description: string; + state: 'pending' | 'active' | 'complete'; +} + +export function derivePipelineStages(document: DocumentEntry): PipelineStage[] { + const terminal = ['completed', 'archived'].includes(inferStatus(document).toLowerCase()); + const hasChunks = (document.chunk_count ?? 0) > 0; + const hasEmbeddings = (document.embedded_chunk_count ?? 0) > 0; + const hasSummary = Boolean(document.summary?.summary); + const hasRoute = Boolean(document.assigned_role) || inferRole(document) !== 'Operations'; + const state = (complete: boolean, active: boolean): PipelineStage['state'] => + complete ? 'complete' : active ? 'active' : 'pending'; + + return [ + { id: 'upload', label: 'Received', description: 'Document accepted and stored.', state: 'complete' }, + { + id: 'extraction', + label: 'Extracted', + description: 'Layout and text converted into chunks.', + state: state(hasChunks, !hasChunks), + }, + { + id: 'embedding', + label: 'Indexed', + description: 'Citation-ready chunks embedded for retrieval.', + state: state(hasEmbeddings, hasChunks), + }, + { + id: 'summary', + label: 'Summarised', + description: 'Key facts and next actions generated.', + state: state(hasSummary, hasEmbeddings), + }, + { + id: 'routing', + label: 'Routed', + description: 'Assigned to an operational work queue.', + state: state(hasRoute || terminal, hasSummary), + }, + ]; +} diff --git a/frontend/src/lib/queryClient.ts b/frontend/src/lib/queryClient.ts new file mode 100644 index 0000000..314af02 --- /dev/null +++ b/frontend/src/lib/queryClient.ts @@ -0,0 +1,12 @@ +import { QueryClient } from '@tanstack/react-query'; + +export const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 15_000, + retry: 2, + refetchOnWindowFocus: false, + }, + mutations: { retry: 0 }, + }, +}); diff --git a/frontend/src/lib/routing.ts b/frontend/src/lib/routing.ts new file mode 100644 index 0000000..1758d62 --- /dev/null +++ b/frontend/src/lib/routing.ts @@ -0,0 +1,50 @@ +import type { DocumentEntry } from '../api/types'; + +export const ROLE_ORDER = ['Finance', 'Compliance', 'Operations', 'Legal', 'HR', 'Integrator'] as const; +export type RoleKey = (typeof ROLE_ORDER)[number]; + +function metadataValue(document: DocumentEntry, key: string): unknown { + const metadata = document.metadata; + return metadata && typeof metadata === 'object' ? metadata[key] : undefined; +} + +export function inferRole(document: DocumentEntry): RoleKey { + const candidate = document.assigned_role ?? metadataValue(document, 'assigned_role') ?? metadataValue(document, 'role'); + if (typeof candidate === 'string') { + const match = ROLE_ORDER.find((role) => role.toLowerCase() === candidate.toLowerCase()); + if (match) return match; + } + + const type = (document.doc_type ?? '').toLowerCase(); + if (/resume|cv|offer|employee|training/.test(type)) return 'HR'; + if (/contract|agreement|legal/.test(type)) return 'Legal'; + if (/policy|audit|compliance|tax/.test(type)) return 'Compliance'; + if (/invoice|receipt|expense|financial/.test(type)) return 'Finance'; + return 'Operations'; +} + +export function inferStatus(document: DocumentEntry): string { + if (document.deleted_at) return 'Deleted'; + if (document.archived_at) return 'Archived'; + const explicit = document.status ?? metadataValue(document, 'status'); + if (typeof explicit === 'string' && explicit.trim()) return explicit; + if (document.summary && (document.embedded_chunk_count ?? 0) > 0) return 'Completed'; + if ((document.embedded_chunk_count ?? 0) > 0) return 'Enriching'; + if ((document.chunk_count ?? 0) > 0) return 'Embedding'; + return 'Processing'; +} + +export function inferDueDate(document: DocumentEntry): string | null { + const candidate = document.due_at ?? metadataValue(document, 'due_at') ?? metadataValue(document, 'due_date'); + return typeof candidate === 'string' && candidate ? candidate : null; +} + +export function formatDateTime(value?: string | null): string { + if (!value) return 'Not set'; + const parsed = new Date(value); + if (Number.isNaN(parsed.getTime())) return 'Invalid date'; + return new Intl.DateTimeFormat(undefined, { + dateStyle: 'medium', + timeStyle: 'short', + }).format(parsed); +} diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts new file mode 100644 index 0000000..2819a83 --- /dev/null +++ b/frontend/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 033bc97..7332e9d 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,20 +1,33 @@ -import React from 'react'; +import React, { Suspense, lazy } from 'react'; import ReactDOM from 'react-dom/client'; import { QueryClientProvider } from '@tanstack/react-query'; -import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { BrowserRouter, Route, Routes } from 'react-router-dom'; -import { AppLayout } from './App'; -import './styles/globals.css'; -import { IntakePage } from './pages/IntakePage'; -import { WorkQueuesPage } from './pages/WorkQueuesPage'; -import { PipelinePage } from './pages/PipelinePage'; -import { QaPage } from './pages/QaPage'; -import { SettingsPage } from './pages/SettingsPage'; -import { SettingsProvider } from './settings/SettingsProvider'; -import { queryClient } from './lib/queryClient'; + import { AuthProvider } from './auth/AuthProvider'; import { ProtectedRoute } from './auth/ProtectedRoute'; -import { LoginPage } from './pages/LoginPage'; +import { queryClient } from './lib/queryClient'; +import { SettingsProvider } from './settings/SettingsProvider'; +import './styles/globals.css'; + +const AppLayout = lazy(() => import('./App')); +const LandingPage = lazy(() => import('./pages/LandingPage')); +const LoginPage = lazy(() => import('./pages/LoginPage').then((module) => ({ default: module.LoginPage }))); +const IntakePage = lazy(() => import('./pages/IntakePage').then((module) => ({ default: module.IntakePage }))); +const WorkQueuesPage = lazy(() => import('./pages/WorkQueuesPage').then((module) => ({ default: module.WorkQueuesPage }))); +const PipelinePage = lazy(() => import('./pages/PipelinePage').then((module) => ({ default: module.PipelinePage }))); +const QaPage = lazy(() => import('./pages/QaPage').then((module) => ({ default: module.QaPage }))); +const SettingsPage = lazy(() => import('./pages/SettingsPage').then((module) => ({ default: module.SettingsPage }))); + +export function RouteLoader() { + return ( +
    +
    + + Preparing your workspace +
    +
    + ); +} ReactDOM.createRoot(document.getElementById('root')!).render( @@ -22,20 +35,29 @@ ReactDOM.createRoot(document.getElementById('root')!).render( - - } /> - }> - } /> - } /> - } /> - } /> - } /> - - + }> + + } /> + } /> + + + + } + > + } /> + } /> + } /> + } /> + } /> + + + - , ); diff --git a/frontend/src/pages/IntakePage.tsx b/frontend/src/pages/IntakePage.tsx index 9c61175..baa895c 100644 --- a/frontend/src/pages/IntakePage.tsx +++ b/frontend/src/pages/IntakePage.tsx @@ -1,140 +1,115 @@ import { useEffect, useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { - AlertTriangle, ArrowRight, - BarChart3, - Building2, - Clock, - FileSpreadsheet, - TrendingUp, - Users, + CheckCircle2, + Clock3, + FileText, + Loader2, + MessageSquareText, + RefreshCw, + Search, + ShieldCheck, + Sparkles, } from 'lucide-react'; import { Link } from 'react-router-dom'; import { fetchDashboardInsights, fetchDocuments } from '../api/client'; import type { DashboardInsights, DocumentEntry } from '../api/types'; import { ActivityFeed } from '../components/notifications/ActivityFeed'; -import { Button } from '../components/ui/button'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/ui/card'; import { Badge } from '../components/ui/badge'; +import { Button } from '../components/ui/button'; import { cn } from '../lib/utils'; -import { ROLE_ORDER, inferDueDate, inferRole, inferStatus, formatDateTime } from '../lib/routing'; - -type RoleSummary = Record; +import { formatDateTime, inferDueDate, inferRole, inferStatus } from '../lib/routing'; + +const FALLBACK_METRICS: DashboardInsights = { + total_documents: 0, + summarised_documents: 0, + chunk_count: 0, + embedded_count: 0, + queue_latency: '—', + estimated_savings: 0, + hours_saved: 0, + analyst_rate: 65, + sla_risk_count: 0, + sla_risk_message: 'Everything is on track.', + throughput_series: [], + compliance_series: [], + delta_processed: '—', + delta_processed_tone: 'neutral', + delta_summaries: '—', + delta_summaries_tone: 'neutral', + today_total: 0, + today_summaries: 0, + yesterday_total: 0, + yesterday_summaries: 0, +}; export function IntakePage() { const [documents, setDocuments] = useState([]); - const [error, setError] = useState(null); - const [isLoading, setIsLoading] = useState(false); - const [attentionView, setAttentionView] = useState<'overdue' | 'upcoming'>('overdue'); + const [documentsError, setDocumentsError] = useState(null); + const [isLoadingDocuments, setIsLoadingDocuments] = useState(false); + const currentTime = useMemo(() => Date.now(), []); const { data: insights, isFetching: isFetchingInsights, refetch: refetchInsights, error: insightsError, - } = useQuery({ - queryKey: ['dashboard-insights'], - queryFn: fetchDashboardInsights, - }); - - const metrics: DashboardInsights = - insights ?? { - total_documents: documents.length, - summarised_documents: documents.filter((doc) => Boolean(doc.summary)).length, - chunk_count: documents.reduce((acc, doc) => acc + (doc.chunk_count ?? 0), 0), - embedded_count: documents.reduce((acc, doc) => acc + (doc.embedded_chunk_count ?? 0), 0), - queue_latency: '—', - estimated_savings: 0, - hours_saved: 0, - analyst_rate: 65, - sla_risk_count: 0, - sla_risk_message: 'All documents are within SLA thresholds.', - throughput_series: [], - compliance_series: [], - delta_processed: '—', - delta_processed_tone: 'neutral', - delta_summaries: '—', - delta_summaries_tone: 'neutral', - today_total: 0, - today_summaries: 0, - yesterday_total: 0, - yesterday_summaries: 0, - }; + } = useQuery({ queryKey: ['dashboard-insights'], queryFn: fetchDashboardInsights }); + + const metrics = insights ?? { + ...FALLBACK_METRICS, + total_documents: documents.length, + summarised_documents: documents.filter((document) => Boolean(document.summary)).length, + chunk_count: documents.reduce((total, document) => total + (document.chunk_count ?? 0), 0), + embedded_count: documents.reduce((total, document) => total + (document.embedded_chunk_count ?? 0), 0), + }; const loadDocuments = () => { - setIsLoading(true); - setError(null); + setIsLoadingDocuments(true); + setDocumentsError(null); fetchDocuments(100) .then((items) => setDocuments( - items.filter((doc) => { - const status = inferStatus(doc).toLowerCase(); - return status !== 'archived' && status !== 'deleted'; - }), + items.filter((document) => !['archived', 'deleted'].includes(inferStatus(document).toLowerCase())), ), ) - .catch((err: unknown) => { - const message = err instanceof Error ? err.message : 'Failed to load documents'; - setError(message); - }) - .finally(() => setIsLoading(false)); + .catch((error: unknown) => + setDocumentsError(error instanceof Error ? error.message : 'Unable to load workspace documents.'), + ) + .finally(() => setIsLoadingDocuments(false)); }; useEffect(() => { loadDocuments(); }, []); - const roleSummary = useMemo(() => { - const summary: RoleSummary = Object.fromEntries(ROLE_ORDER.map((role) => [role, { count: 0, overdue: 0 }])); - const now = Date.now(); - for (const doc of documents) { - const role = inferRole(doc); - const dueAt = inferDueDate(doc); - const status = inferStatus(doc).toLowerCase(); - summary[role].count += 1; - if (dueAt) { - const dueTime = Date.parse(dueAt); - if (!Number.isNaN(dueTime) && dueTime < now && status !== 'completed') { - summary[role].overdue += 1; - } - } - } - return summary; - }, [documents]); - - const totalQueued = useMemo( - () => ROLE_ORDER.reduce((acc, role) => acc + (roleSummary[role]?.count ?? 0), 0), - [roleSummary], - ); - - const recentUploads = useMemo(() => documents.slice(0, 6), [documents]); - - const now = Date.now(); - const twoDays = 48 * 60 * 60 * 1000; - const overdueDocs = useMemo( - () => - documents.filter((doc) => { - const due = inferDueDate(doc); - if (!due) return false; - const dueTime = Date.parse(due); - return !Number.isNaN(dueTime) && dueTime < now; - }), - [documents, now], - ); - const dueSoonDocs = useMemo( + const recentDocuments = useMemo( () => - documents.filter((doc) => { - const due = inferDueDate(doc); - if (!due) return false; - const dueTime = Date.parse(due); - return !Number.isNaN(dueTime) && dueTime >= now && dueTime <= now + twoDays; - }), - [documents, now, twoDays], + documents + .slice() + .sort((first, second) => Date.parse(second.uploaded_at) - Date.parse(first.uploaded_at)) + .slice(0, 5), + [documents], ); - const attentionDocs = attentionView === 'overdue' ? overdueDocs : dueSoonDocs; + const attentionDocuments = useMemo(() => { + const windowEnd = currentTime + 48 * 60 * 60 * 1000; + return documents + .filter((document) => { + const dueAt = inferDueDate(document); + if (!dueAt || ['ready', 'completed', 'archived'].includes(inferStatus(document).toLowerCase())) return false; + const dueTime = Date.parse(dueAt); + return !Number.isNaN(dueTime) && dueTime <= windowEnd; + }) + .sort((first, second) => Date.parse(inferDueDate(first) ?? '') - Date.parse(inferDueDate(second) ?? '')) + .slice(0, 3); + }, [currentTime, documents]); + + const summaryCoverage = percentage(metrics.summarised_documents, metrics.total_documents); + const embeddingCoverage = percentage(metrics.embedded_count, metrics.chunk_count); + const isRefreshing = isLoadingDocuments || isFetchingInsights; const handleRefresh = () => { loadDocuments(); @@ -142,672 +117,190 @@ export function IntakePage() { }; return ( -
    -
    -
    -

    Operations centre

    -
    -

    Intake performance

    - - Updated {new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} - -
    -
    - -
    -
    - - -
    - - - - -
    - - {metrics.sla_risk_message ? ( -
    0 - ? 'border-destructive/40 bg-destructive/5 text-destructive' - : 'border-sky-300/60 bg-sky-50 text-sky-800', - )} - > - -
    -

    SLA update

    -

    - {metrics.sla_risk_message} -

    -
    - {metrics.sla_risk_count > 0 ? ( - - ) : null} -
    - ) : null} - - - -
    -
    - - - +
    +
    +
    +
    +
    +
    + Workspace pulse
    -
    - - +

    + {metrics.total_documents.toLocaleString()} documents are searchable. + + {metrics.sla_risk_count > 0 ? `${metrics.sla_risk_count} need a decision.` : 'Nothing is blocking your team.'} + +

    +

    + Ask a question, continue a review, or inspect the evidence behind any answer. +

    +
    + +
    +
    +

    Since yesterday

    +
    + + + +
    +
    -
    - - - - - Sync status - Pipeline heartbeat and manual refresh. - - -
    - {insightsError ? ( - Unable to refresh dashboard insights. - ) : error ? ( - {error} - ) : isLoading || isFetchingInsights ? ( - Refreshing data… - ) : ( - Everything looks healthy. - )} -
    - -
    -
    - - - - - - Recent uploads - Documents awaiting processing or routing. - - - {recentUploads.length === 0 ? ( -

    No documents ingested yet.

    - ) : ( - recentUploads.map((doc) => ( -
    -
    -
    -

    {doc.filename ?? doc.document_id}

    - {doc.doc_type ? ( - - {doc.doc_type} - - ) : null} -
    -

    - Uploaded {formatDateTime(doc.uploaded_at)} · Status {inferStatus(doc)} -

    -
    - -
    - )) - )} -
    -
    - - - +
    + + +
    -
    -
    -); -} - -type MetricVariant = 'lapis' | 'cerulean' | 'platinum' | 'sky'; - -function HeadlineMetric({ - icon: Icon, - label, - value, - helper, - variant, -}: { - icon: typeof Building2; - label: string; - value: string; - helper?: string; - variant: MetricVariant; -}) { - const palette: Record = { - lapis: { - bg: 'from-[#edf3f8] to-white', - accent: 'bg-[#2f6690] text-white', - }, - cerulean: { - bg: 'from-[#e9f4fb] to-white', - accent: 'bg-[#3a7ca5] text-white', - }, - platinum: { - bg: 'from-[#f5f6f4] to-white', - accent: 'bg-[#b7c0b7] text-[#1f2d32]', - }, - sky: { - bg: 'from-[#e8f2f8] to-white', - accent: 'bg-[#5189b3] text-white', - }, - }; - return ( - - -
    - - - - {label} + {(documentsError || insightsError) ? ( +
    + {documentsError ?? 'Workspace insights are temporarily unavailable.'} +
    - {value} - {helper ?

    {helper}

    : null} - - - ); -} - -function HeroTile({ label, value, delta }: { label: string; value: string; delta: string }) { - return ( - - -
    -

    {label}

    -

    {value}

    -
    -
    -
    - - Velocity + ) : null} + +
    +
    +
    +
    +
    +

    Continue working

    +

    Recently added and processed documents.

    +
    +
    + + +
    - {delta && delta !== '—' ? ( -

    Change vs last period: {delta}

    + + {isLoadingDocuments && !recentDocuments.length ? ( +
    Loading documents…
    + ) : !recentDocuments.length ? ( +

    Your workspace is ready.

    Upload a document to begin building searchable knowledge.

    ) : ( -

    No change recorded

    +
    + {recentDocuments.map((document) => )} +
    )} +
    +
    - - - ); -} -function HighlightCard({ title, value, helper }: { title: string; value: string; helper: string }) { - return ( - - -
    -
    -

    {title}

    -

    {value}

    -
    -
    - -
    +
    +
    +
    + +

    Ask your workspace

    +

    Get an answer grounded in the documents your team has already reviewed.

    + + Ask a question… + +
    +
    +

    Try asking

    +
    + {['Which contracts renew this quarter?', 'Summarize the open compliance risks'].map((prompt) => ( + + {prompt} + + ))} +
    +
    +
    + + +
    -

    {helper}

    - - +
    +
    ); } -function AttentionCard({ - documents, - overdueTotal, - dueSoonTotal, - view, - onChangeView, -}: { - documents: DocumentEntry[]; - overdueTotal: number; - dueSoonTotal: number; - view: 'overdue' | 'upcoming'; - onChangeView: (view: 'overdue' | 'upcoming') => void; -}) { +function PulseRow({ label, value, detail }: { label: string; value: string | number; detail: string }) { return ( - - -
    -
    - Documents needing attention - Route or follow up before SLAs slip. -
    -
    - - -
    -
    -
    - - {documents.length === 0 ? ( -
    - {view === 'overdue' ? 'No overdue documents right now.' : 'No documents due in the next 48 hours.'} -
    - ) : ( - documents.slice(0, 6).map((doc) => { - const role = inferRole(doc); - const status = inferStatus(doc); - const dueAt = formatDateTime(inferDueDate(doc)); - return ( -
    -
    -
    -

    {doc.filename ?? doc.document_id}

    - - {role} - -
    -

    Status: {status}

    -

    Due: {dueAt}

    -
    - -
    - ); - }) - )} -
    -
    +
    + {label} + {value}{detail} +
    ); } -function SummaryProgressCard({ completed, total }: { completed: number; total: number }) { - const percentage = total > 0 ? Math.round((completed / total) * 100) : 0; +function HeroStat({ label, value, helper }: { label: string; value: string; helper: string }) { return ( - - - Summary coverage - - {total > 0 - ? `${completed.toLocaleString()} of ${total.toLocaleString()} documents have summaries ready.` - : 'No documents ingested yet.'} - - - -
    -
    -
    -
    - {percentage}% -
    -
    - {completed.toLocaleString()} ready - {Math.max(total - completed, 0).toLocaleString()} pending review - {total.toLocaleString()} total uploaded -
    - - +
    +

    {label}

    +
    {value}{helper}
    +
    ); } -function EmbeddingCoverageCard({ chunkCount, embeddedCount }: { chunkCount: number; embeddedCount: number }) { - const coverage = chunkCount > 0 ? Math.round((embeddedCount / chunkCount) * 100) : 0; +function DocumentRow({ document }: { document: DocumentEntry }) { + const status = inferStatus(document); + const role = inferRole(document); + const isReady = status.toLowerCase() === 'ready'; return ( - - -
    - Embedding coverage - {coverage}% -
    - Share of chunks with embeddings for search. -
    - -
    -
    -
    -
    -
    -
    - {embeddedCount.toLocaleString()} embedded chunks - {chunkCount.toLocaleString()} total processed -
    - - + +
    + + {document.filename ?? document.document_id}{document.doc_type ?? 'Unclassified'} · Added {formatDateTime(document.uploaded_at)} +
    +
    + {role} + {status} + +
    + ); } -function QueueHealthCard({ totalQueued, overdue, dueSoon }: { totalQueued: number; overdue: number; dueSoon: number }) { - const onTrack = Math.max(totalQueued - overdue - dueSoon, 0); - const totalBar = Math.max(totalQueued, 1); - const segments = [ - { label: 'Overdue', value: overdue, color: '#d97706' }, - { label: 'Due soon', value: dueSoon, color: '#3a7ca5' }, - { label: 'On track', value: onTrack, color: '#2f6690' }, - ]; - +function AttentionPanel({ documents, riskCount }: { documents: DocumentEntry[]; riskCount: number }) { return ( - - - Queue status - Breakdown of items awaiting action. - - - {totalQueued === 0 ? ( -
    - All caught up—no queue today. -
    - ) : ( - <> -
    - {segments - .filter(({ value }) => value > 0) - .map(({ label, value, color }) => ( -
    - ))} -
    -
    - {segments.map(({ label, value, color }) => ( -
    -
    - - {label} -
    - - {value.toLocaleString()} ({Math.round((value / totalBar) * 100)}%) - -
    - ))} -
    - - )} - - +
    +

    Needs attention

    {riskCount > 0 ? `${riskCount} ${riskCount === 1 ? 'review is' : 'reviews are'} approaching SLA` : 'No urgent reviews'}

    +
    + {documents.length ? documents.map((document) => ( + + {document.filename ?? document.document_id}Due {formatDateTime(inferDueDate(document))} + + )) :

    The queue is clear. New SLA risks will appear here.

    } +
    + +
    ); } -function TrendCard({ title, series }: { title: string; series: Array<{ label: string; value: number }> }) { - const values = series.length ? series.map((item) => item.value) : [10, 18, 12, 20, 17, 24, 19]; - const max = Math.max(...values, 1); - const chartPoints = values - .map((value, index) => { - const x = (index / Math.max(values.length - 1, 1)) * 100; - const y = 100 - (value / max) * 80 - 10; - return `${x},${y}`; - }) - .join(' '); - - const labels = series.length ? series.map((item) => item.label) : ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; - +function CoveragePanel({ summaryCoverage, embeddingCoverage, metrics }: { summaryCoverage: number; embeddingCoverage: number; metrics: DashboardInsights }) { return ( - - - {title} - Volume of documents processed over time. - - - - - - - - - - - - -
    - {labels.slice(-4).map((label) => ( - {label} - ))} -
    -
    -
    +
    +

    Knowledge readiness

    How much of your workspace can answer questions today.

    +
    + + +
    +
    Citations and page provenance enabled for indexed sources.
    +
    ); } -function WorkflowOverviewCard({ summary }: { summary: RoleSummary }) { - const total = ROLE_ORDER.reduce((acc, role) => acc + (summary[role]?.count ?? 0), 0); - const palette = ['#2f6690', '#3a7ca5', '#16425b', '#81c3d7', '#1b4965', '#0d1f2d']; - const radius = 15; - const circumference = 2 * Math.PI * radius; - let cumulative = 0; - - const segments = ROLE_ORDER.map((role, index) => { - const value = summary[role]?.count ?? 0; - const dash = total > 0 ? (value / total) * circumference : 0; - const percentage = total > 0 ? Math.round((value / total) * 100) : 0; - const segment = { - role, - value, - dash, - offset: cumulative, - color: palette[index % palette.length], - percentage, - }; - cumulative += dash; - return segment; - }); - +function CoverageRow({ label, value, helper }: { label: string; value: number; helper: string }) { return ( - - - Workflow by role - Current queue mix and ownership across teams. - - -
    - {ROLE_ORDER.map((role) => ( -
    -

    {role}

    -
    -

    {summary[role].count.toLocaleString()} in queue

    -

    {summary[role].overdue.toLocaleString()} overdue

    -
    -
    - ))} -
    -
    - {total === 0 ? ( -
    - No active queue items. -
    - ) : ( - <> - - - - {segments.map(({ role, dash, offset, color }) => - dash > 0 ? ( - - ) : null, - )} - - -
    - {segments.map(({ role, value, color, percentage }) => ( -
    -
    - - {role} -
    - - {value.toLocaleString()} ({percentage}%) - -
    - ))} -
    - - )} -
    -
    -
    +
    {label}{helper} · {value}%
    ); } -function OpsInsightsCard({ - total, - completed, - overdue, - dueSoon, -}: { - total: number; - completed: number; - overdue: number; - dueSoon: number; -}) { - const completionRate = total > 0 ? Math.round((completed / total) * 100) : 0; - const remaining = Math.max(total - completed, 0); - const automationRate = total > 0 ? Math.round((completed / Math.max(total, 1)) * 100) : 0; - const tiles = [ - { - label: 'Summary completion', - value: `${completionRate}%`, - detail: `${completed.toLocaleString()} ready · ${remaining.toLocaleString()} pending`, - }, - { - label: 'Routing backlog', - value: overdue > 0 ? `${overdue}` : 'On track', - detail: - overdue > 0 - ? dueSoon > 0 - ? `${dueSoon} due within 48h` - : 'Escalate overdue items' - : dueSoon > 0 - ? `${dueSoon} due within 48h` - : 'Nothing queued', - }, - { - label: 'Automation coverage', - value: `${automationRate}%`, - detail: total > 0 ? 'Completed via AI summarisation' : 'Awaiting uploads', - }, - ]; - - return ( - - - Operations insights - Quick health check on throughput and backlog. - - - {tiles.map(({ label, value, detail }) => ( -
    -
    - - {label} - - {detail} -
    - {value} -
    - ))} -
    -
    - ); +function percentage(value: number, total: number) { + return total > 0 ? Math.round((value / total) * 100) : 0; } diff --git a/frontend/src/pages/LandingPage.tsx b/frontend/src/pages/LandingPage.tsx new file mode 100644 index 0000000..38aa034 --- /dev/null +++ b/frontend/src/pages/LandingPage.tsx @@ -0,0 +1,291 @@ +import { type ReactNode, useEffect, useState } from 'react'; +import { Link } from 'react-router-dom'; +import { + ArrowRight, + BrainCircuit, + Check, + ChevronRight, + CircleCheck, + Database, + FileCheck2, + FileSearch, + Github, + Layers3, + MessageSquareText, + Network, + ScanLine, + Search, + ShieldCheck, + Sparkles, + UploadCloud, + UsersRound, + WalletCards, + Workflow, + Zap, +} from 'lucide-react'; + +import { Logo } from '../components/brand/Logo'; +import { Button } from '../components/ui/button'; +import { ThemeToggle } from '../components/ui/theme-toggle'; + +const capabilities = [ + { icon: ScanLine, title: 'Structure-aware extraction', copy: 'Keep headings, tables, page numbers, and reading order intact through ingestion.' }, + { icon: Search, title: 'Retrieval with intent', copy: 'Find the passages that answer a question, not merely the pages sharing its keywords.' }, + { icon: MessageSquareText, title: 'Grounded document chat', copy: 'Reason across long files while keeping every claim tied to its supporting context.' }, + { icon: FileCheck2, title: 'Evidence by default', copy: 'Expose source document, page, chunk, and confidence alongside every generated answer.' }, + { icon: Layers3, title: 'Multi-document synthesis', copy: 'Compare contracts, policies, reports, and research without losing provenance.' }, + { icon: ShieldCheck, title: 'Operational control', copy: 'Track ingestion, classifications, reviews, retries, and lifecycle events in one workspace.' }, +]; + +const useCases = [ + { icon: FileCheck2, team: 'Legal', question: 'Where do renewal terms conflict across our vendor agreements?', outcome: 'Clause review with page-level evidence' }, + { icon: ShieldCheck, team: 'Compliance', question: 'Which controls are incomplete, and what source proves it?', outcome: 'Auditable gap analysis' }, + { icon: BrainCircuit, team: 'Research', question: 'What do these studies agree on—and where do they diverge?', outcome: 'Cross-document synthesis' }, + { icon: WalletCards, team: 'Finance', question: 'What changed between the forecast and the board report?', outcome: 'Traceable variance analysis' }, + { icon: UsersRound, team: 'People', question: 'Which policy applies to this employee request?', outcome: 'Fast policy navigation' }, +]; + +const stack = ['React 19', 'TypeScript', 'FastAPI', 'Celery', 'Docling', 'PostgreSQL', 'pgvector', 'OpenAI']; + +export default function LandingPage() { + const [scrolled, setScrolled] = useState(false); + + useEffect(() => { + const update = () => setScrolled(window.scrollY > 12); + update(); + window.addEventListener('scroll', update, { passive: true }); + return () => window.removeEventListener('scroll', update); + }, []); + + return ( +
    +
    +
    + + +
    + + + +
    +
    +
    + +
    +
    +
    + +
    + +
    + +
    +
    +
    +

    From file to finding

    A pipeline you can explain.

    +

    Every stage produces typed, inspectable outputs instead of hiding work inside one model call.

    +
    +
    + } title="Ingest" copy="Extract structure, OCR scans, and preserve page provenance." detail="Docling + validation" /> + } title="Understand" copy="Create bounded chunks, batch embeddings, and retrieve with filters." detail="pgvector + evaluation" /> + } title="Answer" copy="Construct grounded context and return evidence with confidence." detail="Structured model output" /> +
    +
    +
    + +
    +
    + +
    + Trust is a product feature +

    Answers that show their work.

    +

    A fluent answer is not enough. DocuLens pairs each claim with source context, page metadata, retrieval confidence, and the original document.

    +
    + + + +
    +
    +
    +
    + +
    +
    +
    +
    + Production-minded architecture +

    Fast at the edge. Durable underneath.

    +

    FastAPI accepts work quickly. Celery handles retryable document and model tasks. PostgreSQL remains the durable boundary for events, metadata, and vectors.

    +
    {stack.map((item) => {item})}
    +
    + +
    +
    +
    + +
    +
    +
    Evidence-heavy work

    Useful wherever the source matters.

    +
    + {useCases.map(({ icon: Icon, team, question, outcome }) => ( +
    +

    {team}

    +

    “{question}”

    +

    {outcome}

    +
    + ))} +
    +
    +
    + +
    +
    +
    +

    Make documents operational

    Know what your documents know.

    Run DocuLens locally, inspect the architecture, and ask your first evidence-grounded question.

    + +
    +
    +
    +
    + + +
    + ); +} + +function EvidenceCanvas() { + return ( +
    +
    +
    +
    +
    +
    Private workspace
    +
    +
    +
    +
    +

    Master services agreement

    Acme Cloud, Inc.

    18 / 28
    +

    12. Term and termination

    +

    This Agreement begins on the Effective Date and continues for the Initial Term.

    Thereafter, the Agreement automatically renews for successive one-year periods unless either party provides written notice at least sixty (60) days before renewal.

    Either party may terminate for material breach following a thirty-day cure period.

    +
    +
    +

    Answer

    94% confidence

    The agreement renews annually unless either party gives 60 days’ written notice. Material breach has a 30-day cure period.

    +
    +
    + +
    +
    +
    + ); +} + +function ProofPoint({ value, label }: { value: string; label: string }) { + return

    {value}

    {label}

    ; +} + +function Eyebrow({ children }: { children: ReactNode }) { + return

    {children}

    ; +} + +function WorkflowStep({ index, icon, title, copy, detail }: { index: string; icon: ReactNode; title: string; copy: string; detail: string }) { + return
    {icon}{index}

    {title}

    {copy}

    {detail}

    ; +} + +function EvidenceStory() { + return ( +
    +
    +

    Q2 Board Report.pdf

    41 pages · indexed 2 minutes ago

    +

    Question

    What are the top risks to the forecast?

    +
    +

    Grounded answer

    High confidence

    The report identifies enterprise concentration, delayed European expansion, and model inference costs as the three material forecast risks.

    +
    + ); +} + +function TrustRow({ title, copy }: { title: string; copy: string }) { + return

    {title}

    {copy}

    ; +} + +function ArchitectureMap() { + const nodes = [ + { icon: Workflow, title: 'FastAPI', copy: 'Validated, versioned API' }, + { icon: Zap, title: 'Celery', copy: 'Durable async workflows' }, + { icon: Network, title: 'RAG pipeline', copy: 'Extract, chunk, retrieve' }, + { icon: Database, title: 'Postgres + vectors', copy: 'Events and evidence' }, + ]; + return
    {nodes.map(({ icon: Icon, title, copy }, index) =>
    0{index + 1}

    {title}

    {copy}

    )}
    ; +} + +function SourcePill({ label }: { label: string }) { + return {label}; +} + +function SourceCard({ index, title, page, score, active = false }: { index: string; title: string; page: string; score: string; active?: boolean }) { + return
    {index}

    {title}

    {page}{score}
    ; +} + +function EvidenceMetric({ value, label }: { value: string; label: string }) { + return

    {value}

    {label}

    ; +} diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx index 02f90a5..3653af4 100644 --- a/frontend/src/pages/LoginPage.tsx +++ b/frontend/src/pages/LoginPage.tsx @@ -1,35 +1,29 @@ import { type FormEvent, useState } from 'react'; -import { Navigate, useLocation, useNavigate } from 'react-router-dom'; -import { Lock, LogIn, Mail } from 'lucide-react'; +import { Link, Navigate, useLocation, useNavigate } from 'react-router-dom'; +import { ArrowLeft, ArrowRight, Check, Eye, EyeOff, FileCheck2, LockKeyhole, Sparkles } from 'lucide-react'; import { useAuth } from '../auth/useAuth'; +import { Logo } from '../components/brand/Logo'; import { Button } from '../components/ui/button'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/ui/card'; import { Input } from '../components/ui/input'; -import { Badge } from '../components/ui/badge'; +import { ThemeToggle } from '../components/ui/theme-toggle'; +import { useSettings } from '../settings/useSettings'; -const DEMO_ACCOUNTS = [ - { email: 'admin@doculens.ai', role: 'Admin', password: 'Admin!234' }, - { email: 'analyst@doculens.ai', role: 'Analyst', password: 'Analyst!234' }, - { email: 'reviewer@doculens.ai', role: 'Reviewer', password: 'Reviewer!234' }, - { email: 'manager@doculens.ai', role: 'Manager', password: 'Manager!234' }, - { email: 'developer@doculens.ai', role: 'Developer', password: 'Developer!234' }, - { email: 'viewer@doculens.ai', role: 'Viewer', password: 'Viewer!234' }, -]; +const DEMO_ACCOUNT = { email: 'analyst@doculens.ai', password: 'Analyst!234' }; export function LoginPage() { const { user, login } = useAuth(); + const { serverConfig } = useSettings(); const navigate = useNavigate(); const location = useLocation(); const fromState = (location.state as { from?: { pathname?: string } } | undefined)?.from; const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); + const [showPassword, setShowPassword] = useState(false); const [error, setError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); - if (user) { - return ; - } + if (user || serverConfig?.showcase_read_only) return ; const handleSubmit = async (event: FormEvent) => { event.preventDefault(); @@ -37,93 +31,50 @@ export function LoginPage() { setIsSubmitting(true); try { await login(email, password); - const redirectTo = fromState?.pathname ?? '/'; - navigate(redirectTo, { replace: true }); - } catch (err) { - console.error(err); - setError('We could not sign you in with those credentials.'); + navigate(fromState?.pathname ?? '/app', { replace: true }); + } catch { + setError('Those credentials do not match this workspace.'); setIsSubmitting(false); } }; - return ( -
    - - - Sign in to DocuLens - - Secure access for analysts, reviewers, managers, and administrators. - - - -
    -
    - -
    - - setEmail(event.target.value)} - className="pl-9" - /> -
    -
    - -
    - -
    - - setPassword(event.target.value)} - className="pl-9" - /> -
    -
    + const useDemo = () => { + setEmail(DEMO_ACCOUNT.email); + setPassword(DEMO_ACCOUNT.password); + setError(null); + }; - {error ?

    {error}

    : null} + return ( +
    +
    +
    +
    +
    + Evidence-first document AI +

    Turn documents into decisions.

    +

    Search, summarize, classify, and ask complex questions—with every insight grounded in the source.

    +
    + {['Precise semantic retrieval', 'Page-level citations', 'Structured AI outputs', 'Auditable event history'].map((item) =>
    {item}
    )} +
    +
    +
    Built for teams where evidence matters.
    +
    - +
    +
    +
    +

    Workspace access

    Welcome back

    Sign in to continue to your DocuLens workspace.

    + +
    setEmail(event.target.value)} placeholder="you@company.com" className="h-11 rounded-xl bg-background" />
    +
    setPassword(event.target.value)} placeholder="Enter your password" className="h-11 rounded-xl bg-background pr-10" />
    + {error ?
    {error}
    : null} + - -
    -

    Role directory

    -

    - Demo credentials for each persona are available below. Rotate passwords in production and manage accounts from the admin - console. -

    -
      - {DEMO_ACCOUNTS.map((account) => ( -
    • -
      - {account.role} - {account.email} -
      -

      Password: {account.password}

      -
    • - ))} -
    -
    - - +
    Portfolio demo
    + +

    By continuing, you agree to the workspace security policy.
    Demo accounts are disabled in production.

    +
    +
    ); } diff --git a/frontend/src/pages/PipelinePage.tsx b/frontend/src/pages/PipelinePage.tsx index 386ccbc..3803414 100644 --- a/frontend/src/pages/PipelinePage.tsx +++ b/frontend/src/pages/PipelinePage.tsx @@ -130,14 +130,14 @@ export function PipelinePage() {
    - Pipeline overview - Quick snapshot of throughput and bottlenecks. + Document status + What is ready, processing, or needs your attention. - - - - + + + +
    @@ -151,8 +151,8 @@ export function PipelinePage() { - Document inventory - Select an item to inspect its pipeline details. + All documents + Select a document to review its summary, classification, and sources.
    - ) : ( -
    -
    -
    - {filteredDocuments.map((doc) => { - const isActive = doc.document_id === selectedDocumentId; - const role = inferRole(doc); - const status = inferStatus(doc); - const uploadedLabel = doc.uploaded_at ? new Date(doc.uploaded_at).toLocaleDateString() : '—'; - return ( - - ); - })} -
    -
    -
    - )} - -
    + +
    setDocumentFilter(event.target.value)} placeholder="Search sources…" aria-label="Search sources" className="h-9 rounded-lg bg-background pl-8 text-xs" />
    + + + {isLoadingDocuments ?
    Loading sources…
    : documentsError ?
    {documentsError}
    : !filteredDocuments.length ?
    No sources match your filter.
    : ( +
    {filteredDocuments.map((doc) => { + const isActive = doc.document_id === selectedDocumentId; + return ; + })}
    + )} +
    + + ) : null} - - + +
    -
    - - QA Studio - - - Conversational RAG grounded in {selectedDocument ? selectedDocument.filename ?? selectedDocument.document_id : 'your documents'}. - + +
    + + +
    -
    - {selectedDocument ? ( -
    - Document: - {selectedDocument.filename ?? selectedDocument.document_id} - {inferRole(selectedDocument)} - {inferStatus(selectedDocument)} - Uploaded {formatDateTime(selectedDocument.uploaded_at)} -
    - ) : null} - {historyError ? ( -
    {historyError}
    - ) : null} + {historyError ?
    {historyError}
    : null} - -
    - {!selectedDocument ? ( - - ) : !chatMessages.length ? ( - - ) : ( - chatMessages.map((message) => ) - )} + +
    +
    + {!selectedDocument ? : !chatMessages.length ? : chatMessages.map((message) => )} +
    -
    -
    -