Final Push

This commit is contained in:
2026-05-13 21:08:27 +01:00
parent e4f4992a1b
commit 659e4a72c5
32 changed files with 2173 additions and 3500 deletions

218
docs/01-project-overview.md Normal file
View File

@@ -0,0 +1,218 @@
# 01 — Project Overview
## What is LexiChain?
**LexiChain** is a full-stack BFSI (Banking, Financial Services & Insurance) contract intelligence platform. It transforms raw PDF and image contract documents into structured, searchable, and verifiable data through a multi-layer pipeline:
1. **Upload** — Users upload insurance policies, loan agreements, or investment contracts.
2. **AI Extraction** — Google Gemini (primary) or Mistral AI (fallback) reads the document and extracts structured metadata.
3. **RAG Q&A** — Users can ask natural-language questions about any analyzed contract.
4. **Blockchain Proof** — Every document's SHA-256 hash is registered on Ethereum (Sepolia testnet or local Hardhat) providing tamper-proof, timestamped proof-of-deposit.
5. **Notifications** — The platform emails users about upcoming contract renewals and expiries.
6. **Analytics** — A dashboard aggregates contract statistics, type distributions, and status trends.
---
## Feature List
| Feature | Description |
|---------|-------------|
| **Authentication** | Clerk-powered sign-in/sign-up with SSO support |
| **Contract Upload** | Drag-and-drop PDF/image upload via UploadThing |
| **AI Analysis** | Structured extraction: type, dates, premium, provider, key clauses |
| **AI Fallback** | Mistral Large + Pixtral vision model when Gemini is unavailable |
| **Contract Q&A** | RAG-grounded question answering on analyzed contracts |
| **Blockchain Proof** | On-chain document hash registration (Sepolia testnet) |
| **Blockchain Explorer** | In-app UI to verify document hashes and view transaction proofs |
| **Email Notifications** | SMTP-based renewal and expiry alerts |
| **In-App Notifications** | Real-time notification bar with read/dismiss |
| **Analytics Dashboard** | KPIs, status distribution, contract type charts (Recharts) |
| **Dark / Light Mode** | Full theme support via next-themes |
| **PDF Certificate Export** | Downloadable PDF certificates with QR codes |
| **CSV Export** | Contract list export to CSV |
---
## Technology Stack
### Core Framework
| Layer | Technology |
|-------|-----------|
| Framework | Next.js 16.x (App Router) |
| Language | TypeScript 5.x (strict mode) |
| Runtime | Node.js ≥ 20 |
| React | 19.x |
### Frontend
| Technology | Purpose |
|-----------|---------|
| Tailwind CSS + tailwindcss-animate | Utility-first styling |
| shadcn/ui (Radix UI primitives) | Accessible component library |
| Lucide React | Icon set |
| Motion (Framer Motion v12) | Animations and micro-interactions |
| Recharts | Analytics charts |
| Sonner | Toast notifications |
| next-themes | Dark/light mode |
| react-hook-form + zod | Form validation |
### Backend & Data
| Technology | Purpose |
|-----------|---------|
| PostgreSQL | Primary relational database |
| Prisma ORM | Schema management, type-safe queries, migrations |
| Clerk | Authentication, user management |
| UploadThing | File upload and CDN storage |
| Nodemailer | SMTP email delivery |
### AI & Intelligence
| Technology | Purpose |
|-----------|---------|
| Google Gemini (via `@google/generative-ai`) | Primary multimodal contract extraction |
| Mistral AI (REST API) | Fallback extraction + OCR |
| Pixtral (Mistral Vision) | Image/scanned document fallback |
| Gemini text-embedding-004 | Vector embeddings for RAG |
### Blockchain
| Technology | Purpose |
|-----------|---------|
| Solidity 0.8.24 | Smart contract language |
| Hardhat | Compilation, testing, local node, deployment |
| ethers.js v6 | Server-side blockchain interaction |
| Ethereum Sepolia | Production testnet (free, no cost) |
### PDF & Certificates
| Technology | Purpose |
|-----------|---------|
| PDFKit | Server-side PDF certificate generation |
| jsPDF + jspdf-autotable | Client-side PDF/table export |
| pdf-parse | PDF text extraction for OCR fallback |
| qrcode | QR code generation for certificates |
---
## Architecture Overview
```
┌─────────────────────────────────────────────────────────────────┐
│ USER BROWSER │
│ Next.js App Router UI │
└───────────────────────┬─────────────────────────────────────────┘
┌─────────────▼──────────────┐
│ Clerk Middleware │ Route protection (proxy.ts)
│ (proxy.ts) │ Blocks unauthenticated access
└─────────────┬──────────────┘
┌─────────────▼──────────────┐
│ Server Actions │ lib/actions/* — authenticated
│ & Route Handlers │ server-side operations
└──────┬──────────┬──────────┘
│ │
┌────────────▼──┐ ┌────▼───────────┐
│ lib/services │ │ app/api/* │
│ (domain logic)│ │ (webhooks, │
│ │ │ uploadthing) │
└────────────────┘ └────────────────┘
┌──────┴──────────────────────────────────┐
│ External Integrations │
│ │
│ PostgreSQL UploadThing Gemini API │
│ (Prisma) (file CDN) (primary AI) │
│ │
│ Mistral AI Ethereum SMTP Server │
│ (fallback) Sepolia (email) │
└──────────────────────────────────────────┘
```
---
## User Flows
### 1. Sign Up & Onboarding
```
User visits /sign-up
→ Clerk handles registration
→ Clerk fires webhook (user.created)
→ app/api/webhooks/clerk syncs User record to PostgreSQL
→ User redirected to /dashboard
```
### 2. Contract Upload & Analysis
```
User uploads PDF from /contracts
→ UploadThing receives file → stores on CDN → returns URL
→ saveContract() server action creates Contract row (status: UPLOADED)
→ User clicks "Analyze"
→ analyzeContractAction() sets status: PROCESSING
→ AIService downloads file → sends to Gemini → parses JSON response
→ ContractService.updateWithAIResults() saves extracted data
→ BlockchainService hashes file → registers hash on Sepolia
→ Status set to COMPLETED
→ NotificationService creates in-app + email notification
```
### 3. Contract Q&A (RAG)
```
User asks question in contract detail page
→ askContractQuestionAction() fetches contract + RAG chunks
→ RAGService finds most similar chunks via cosine similarity
→ AIService sends contract context + question to Gemini
→ Answer streamed back to UI
```
### 4. Blockchain Verification
```
User opens /blockchain explorer
→ BlockchainService.getNetworkStats() queries Sepolia node
→ User pastes document hash or views registered documents
→ BlockchainService.verifyOnChain() calls verifyDocument() on Solidity contract
→ Result shown: exists / timestamp / depositor address
```
---
## Project Directory Structure
```
bfsi-project/
├── app/ Next.js App Router
│ ├── (auth)/ Sign-in / Sign-up pages
│ ├── (dashboard)/ Protected workspace pages
│ │ ├── dashboard/ Analytics overview
│ │ ├── contacts/ Contract list & detail
│ │ └── blockchain/ Blockchain explorer
│ └── api/ Route handlers
│ ├── contracts/ Contract CRUD endpoints
│ ├── uploadthing/ UploadThing integration
│ └── webhooks/ Clerk webhook receiver
├── blockchain/ Hardhat smart contract project
│ ├── contracts/ Solidity source files
│ └── scripts/ Deployment scripts
├── components/ Reusable React components
│ ├── layout/ Shell, sidebar, header
│ └── ui/ shadcn/ui design system
├── docs/ This documentation folder
├── features/ Feature-scoped components
│ ├── ai/ AI analysis UI
│ ├── analytics/ Dashboard charts
│ ├── auth/ Auth-related UI
│ ├── blockchain/ Blockchain explorer UI
│ ├── claims/ Claims management
│ ├── contracts/ Contract upload/list/detail
│ ├── home/ Landing page
│ └── notifications/ Notification center
├── hooks/ Custom React hooks
├── lib/
│ ├── db/ Prisma client singleton
│ ├── services/ All domain services (AI, Blockchain, etc.)
│ │ └── ai/ AI sub-modules (parser, normalizer, prompts)
│ ├── upload.ts UploadThing configuration
│ └── utils.ts Shared utility functions
├── prisma/ Database schema and migrations
├── public/ Static assets
├── scripts/ Dev tooling scripts
├── types/ Shared TypeScript types
├── proxy.ts Clerk middleware (route protection)
└── next.config.ts Next.js configuration
```

374
docs/02-services.md Normal file
View File

@@ -0,0 +1,374 @@
# 02 — Services Reference
All domain services live in `lib/services/`. They are plain TypeScript classes with static methods — no instantiation needed. Services are **server-only** (never imported in client components).
---
## Table of Contents
1. [AIService](#1-aiservice)
2. [RAGService](#2-ragservice)
3. [BlockchainService](#3-blockchainservice)
4. [ContractService](#4-contractservice)
5. [NotificationService](#5-notificationservice)
6. [EmailService](#6-emailservice)
7. [StatsService](#7-statsservice)
8. [CertificateService](#8-certificateservice)
9. [StorageService](#9-storageservice)
---
## 1. AIService
**File:** `lib/services/ai.service.ts`
**Sub-modules:** `lib/services/ai/` (parser, normalizer, prompt builder, key manager)
### Purpose
Extracts structured information from uploaded contract documents (PDF or image). Implements a multi-model fallback chain with automatic retry and JSON repair.
### Pipeline
```
File URL
Download bytes + resolve MIME type
Pre-validation (is this actually a contract?)
Build adaptive prompt (with context from previous analyses)
[Attempt 1..N]
├── Try Gemini primary model (key rotation across AI_API_KEY1/2/3)
├── Try Gemini secondary model (if AI_MODEL_SECONDARY_GEMINI is set)
├── Try Gemini with lenient settings (last Gemini attempt)
└── If all Gemini models fail → Mistral Fallback
├── PDF: extract text via pdf-parse → ground Mistral on text
└── Image: send to Pixtral vision model directly
Parse JSON → normalize → validate
On parse failure: call Mistral repair model → emergency field extraction
Return NormalizedAnalysis
```
### Key Methods
| Method | Description |
|--------|-------------|
| `analyzeContract(fileUrl, options?)` | Main entry point — full extraction pipeline |
| `askAboutContract(question, contract, userId?)` | RAG-grounded Q&A on an analyzed contract |
| `preValidateContract(input)` | Quick pre-check to reject non-contract files |
| `buildAdaptiveContext(userId?)` | Builds few-shot examples from user's previous contracts |
### Configuration
| Environment Variable | Default | Description |
|---------------------|---------|-------------|
| `AI_API_KEY1` / `AI_API_KEY2` / `AI_API_KEY3` | — | Gemini API keys (rotated automatically) |
| `AI_MODEL_PRIMARY` | `gemini-2.5-flash-preview-04-17` | Primary Gemini extraction model |
| `AI_MODEL_SECONDARY_GEMINI` | — | Optional secondary Gemini model |
| `AI_EMBEDDING_MODEL` | `text-embedding-004` | Gemini embedding model for RAG |
| `MISTRAL_API_KEY` | — | Mistral API key (activates fallback) |
| `AI_MODEL_FALLBACK` | `mistral-large-latest` | Mistral text fallback model |
| `AI_MODEL_MISTRAL_VISION` | `pixtral-large-latest` | Mistral multimodal model for images |
| `AI_MODEL_MISTRAL_OCR` | `mistral-ocr-latest` | Mistral OCR model |
| `AI_FORCE_FALLBACK_TEST` | — | Set to `"1"` to bypass Gemini for testing |
### Sub-modules
| File | Purpose |
|------|---------|
| `ai/analysis.prompt.ts` | Builds the Gemini extraction prompt with few-shot examples |
| `ai/analysis.parser.ts` | Robust JSON parser with fence stripping and repair |
| `ai/analysis.normalizer.ts` | Normalizes raw AI output into `NormalizedAnalysis` shape |
| `ai/analysis.types.ts` | TypeScript types for AI input/output |
| `ai/key-manager.ts` | Round-robin Gemini API key rotation with quota exhaustion detection |
### Output Schema (`NormalizedAnalysis`)
```typescript
{
title: string | null
type: ContractType | null // enum: INSURANCE_AUTO, LOAN, etc.
provider: string | null
policyNumber: string | null
startDate: Date | null
endDate: Date | null
premium: number | null
summary: string
extractedText: string
keyPoints: {
guarantees: string[]
exclusions: string[]
franchise: string | null
importantDates: string[]
explainability: Array<{
field: string
why: string
sourceSnippet: string
sourceHints: { page: string|null, section: string|null, confidence: number }
}>
}
keyPeople: Array<{ name: string, role: string|null, email: string|null, phone: string|null }>
relevantDates: Array<{ date: string, description: string, type: string }>
}
```
---
## 2. RAGService
**File:** `lib/services/rag.service.ts`
### Purpose
Retrieval-Augmented Generation (RAG) — splits contract text into chunks, generates embeddings, stores them in PostgreSQL, and retrieves the most relevant chunks when answering user questions.
### How It Works
```
analyzeContract completes
RAGService.indexContract(contractId, extractedText)
├── Split text into 512-token chunks with 64-token overlap
├── Generate embeddings via Gemini text-embedding-004
└── Store in ContractRagChunk table
User asks question
RAGService.query(contractId, question)
├── Embed the question via text-embedding-004
├── Load all chunks for this contract from DB
├── Compute cosine similarity between question embedding and each chunk
└── Return top-K most relevant chunks
```
### Key Methods
| Method | Description |
|--------|-------------|
| `indexContract(contractId, text)` | Chunks, embeds, and stores contract text |
| `query(contractId, question, topK?)` | Returns most similar chunks to a question |
| `deleteIndex(contractId)` | Removes all RAG chunks for a contract |
### Storage
Chunks are stored in the `ContractRagChunk` model:
- `content` — raw chunk text
- `embedding` — float array (Gemini embedding vector)
- `contentHash` — SHA-256 of content (deduplication)
- `chunkIndex` — position in original document
---
## 3. BlockchainService
**File:** `lib/services/blockchain.service.ts`
### Purpose
Server-side Ethereum integration. Computes SHA-256 hashes of documents and registers them on the `DocumentRegistry` smart contract, providing tamper-proof, timestamped proof-of-deposit.
> **Important:** This service uses a **server-side wallet** (`JsonRpcProvider + Wallet`). Users do NOT need MetaMask or any wallet.
### How It Works
```
Contract file URL
BlockchainService.hashDocument(fileUrl)
├── Downloads raw file bytes from UploadThing CDN
└── Computes SHA-256 → returns 0x-prefixed bytes32 string
BlockchainService.registerOnChain(documentHash, fileName)
├── Calls contract.registerDocument(bytes32) via server wallet
├── Waits for transaction to be mined (1 confirmation)
├── Gets block timestamp → this becomes the legal proof date
└── Returns BlockchainProof { txHash, blockNumber, blockTimestamp, ... }
```
### Configuration
| Environment Variable | Description |
|---------------------|-------------|
| `BLOCKCHAIN_NETWORK` | `"hardhat"` (dev) or `"sepolia"` (production) |
| `BLOCKCHAIN_RPC_URL` | JSON-RPC endpoint (Sepolia public RPC or Alchemy/Infura) |
| `BLOCKCHAIN_PRIVATE_KEY` | Private key of the signing wallet (holds Sepolia ETH) |
| `BLOCKCHAIN_CONTRACT_ADDRESS` | Deployed `DocumentRegistry` contract address |
### Key Methods
| Method | Description |
|--------|-------------|
| `hashDocument(fileUrl)` | Downloads file and computes SHA-256 |
| `registerOnChain(hash, fileName)` | Registers hash on the smart contract |
| `hashAndRegister(fileUrl, fileName)` | Convenience: hash + register in one call |
| `verifyOnChain(documentHash)` | Read-only verification of a hash |
| `getNetworkStats()` | Returns network status, block number, total docs |
| `isConfigured()` | Returns false if env vars are missing (graceful degradation) |
### Graceful Degradation
If `BLOCKCHAIN_CONTRACT_ADDRESS` or `BLOCKCHAIN_PRIVATE_KEY` are not set, `isConfigured()` returns `false` and the app skips blockchain registration silently. The rest of the analysis pipeline completes normally.
---
## 4. ContractService
**File:** `lib/services/contract.service.ts`
### Purpose
CRUD operations and lifecycle management for Contract records. Acts as the single point of interaction with the `Contract` Prisma model.
### Status Machine
```
UPLOADED → PROCESSING → COMPLETED
└──→ FAILED
```
| Status | Meaning |
|--------|---------|
| `UPLOADED` | File received, waiting for analysis |
| `PROCESSING` | AI analysis in progress |
| `COMPLETED` | Analysis done, blockchain registered |
| `FAILED` | Analysis failed (error stored) |
### Key Methods
| Method | Description |
|--------|-------------|
| `create(userId, fileData)` | Creates a new Contract record (status: UPLOADED) |
| `updateWithAIResults(id, analysis)` | Saves AI-extracted fields, sets status COMPLETED |
| `updateBlockchainProof(id, proof)` | Saves blockchain transaction details |
| `setProcessing(id)` | Sets status to PROCESSING |
| `setFailed(id, error)` | Sets status to FAILED with error message |
| `getById(id, userId)` | Fetches a contract, validates ownership |
| `listForUser(userId, filters?)` | Returns all contracts for a user |
| `deleteContract(id, userId)` | Deletes contract + cascades to chunks/notifications |
---
## 5. NotificationService
**File:** `lib/services/notification.service.ts`
### Purpose
Creates, reads, and manages in-app notifications. Also schedules deadline-based alerts for contracts nearing expiration.
### Notification Types
| Type | Trigger |
|------|---------|
| `SUCCESS` | Contract analysis completed |
| `ERROR` | Analysis failed |
| `INFO` | Blockchain registration, general events |
| `WARNING` | Contract nearing expiry (30 days) |
| `DEADLINE` | Contract expires in < 7 days |
### Key Methods
| Method | Description |
|--------|-------------|
| `createNotification(userId, data)` | Creates an in-app notification |
| `getUnread(userId)` | Returns all unread notifications |
| `markAsRead(id, userId)` | Marks a notification as read |
| `markAllAsRead(userId)` | Marks all as read |
| `checkDeadlines(userId)` | Scans contracts nearing expiry and creates alerts |
| `deleteExpired()` | Purges expired notifications |
---
## 6. EmailService
**File:** `lib/services/email.service.ts`
### Purpose
Sends transactional emails using Nodemailer over SMTP. Falls back to Ethereal (test inbox) when running outside production and no SMTP credentials are configured.
### Configuration
| Variable | Description |
|----------|-------------|
| `EMAIL_HOST` | SMTP server hostname (e.g., `smtp-relay.brevo.com`) |
| `EMAIL_PORT` | SMTP port (`587` for STARTTLS, `465` for SSL) |
| `EMAIL_SECURE` | `true` for SSL/TLS, `false` for STARTTLS |
| `EMAIL_USER` | SMTP username |
| `EMAIL_PASS` | SMTP password |
| `MAIL_FROM` | From address, e.g., `LexiChain <no-reply@yourdomain.com>` |
### Email Types Sent
| Email | Trigger |
|-------|---------|
| Contract analysis complete | AI analysis finishes successfully |
| Analysis failed | AI analysis encounters an error |
| Contract expiry warning | Contract expires within 30 days |
| Contract expiry imminent | Contract expires within 7 days |
| Blockchain registration | Document hash registered on-chain |
### Dev Fallback
If `EMAIL_HOST` is not set and `NODE_ENV !== production`, the service creates an [Ethereal](https://ethereal.email/) test account automatically. The preview URL is printed to the server console.
---
## 7. StatsService
**File:** `lib/services/stats.service.ts`
### Purpose
Computes aggregated analytics for the dashboard. All queries run server-side via Prisma.
### Metrics Provided
| Metric | Description |
|--------|-------------|
| Total contracts | Count of all user contracts |
| By status | Breakdown: UPLOADED / PROCESSING / COMPLETED / FAILED |
| By type | Distribution across ContractType enum values |
| By month | Monthly upload trend (last 12 months) |
| Expiring soon | Contracts expiring within 30/90 days |
| Average premium | Average premium across completed contracts |
| Blockchain coverage | % of contracts with on-chain proof |
| Recent activity | Last N contracts with status |
---
## 8. CertificateService
**File:** `lib/services/certificate.service.ts`
### Purpose
Generates downloadable PDF certificates of document registration using PDFKit. The certificate includes:
- Contract metadata (title, type, dates, provider)
- Document SHA-256 hash
- Blockchain transaction hash and block number
- Registration timestamp (block timestamp)
- QR code linking to Etherscan (Sepolia)
### Key Methods
| Method | Description |
|--------|-------------|
| `generateCertificate(contract)` | Returns a PDF Buffer for a completed+blockchain contract |
| `generateCertificateStream(contract)` | Returns a Node.js stream for streaming response |
---
## 9. StorageService
**File:** `lib/services/storage.service.ts`
### Purpose
Thin wrapper around UploadThing. Provides utilities for:
- Deleting uploaded files (cleanup on contract delete)
- Building file access URLs
- Validating file constraints
### Configuration
UploadThing is configured in `lib/upload.ts` and exposed via `app/api/uploadthing/`.
| Variable | Description |
|----------|-------------|
| `UPLOADTHING_TOKEN` | UploadThing authentication token |
| `UPLOADTHING_APP_ID` | UploadThing application ID |

230
docs/03-database-schema.md Normal file
View File

@@ -0,0 +1,230 @@
# 03 — Database Schema
**ORM:** Prisma
**Database:** PostgreSQL
**Schema file:** `prisma/schema.prisma`
---
## Entity Relationship Diagram
```
User
├──< Contract (one user → many contracts)
│ ├──< ContractRagChunk (one contract → many RAG chunks)
│ ├──< Notification (one contract → many notifications)
│ └──< BlockchainTransaction (one contract → many blockchain txs)
├──< Notification (one user → many notifications)
└──< BlockchainTransaction (one user → many blockchain txs)
```
---
## Models
### `User`
Stores platform users, synchronized from Clerk via webhook.
| Column | Type | Notes |
|--------|------|-------|
| `id` | `String` (cuid) | Primary key |
| `clerkId` | `String` | Unique Clerk user ID |
| `email` | `String` | Unique email address |
| `firstName` | `String?` | Optional first name |
| `lastName` | `String?` | Optional last name |
| `imageUrl` | `String?` | Clerk profile image URL |
| `createdAt` | `DateTime` | Record creation timestamp |
| `updatedAt` | `DateTime` | Auto-updated on changes |
**Indexes:** `clerkId`, `email`
**Sync:** Created/updated by `app/api/webhooks/clerk/` in response to Clerk `user.created` and `user.updated` events.
---
### `Contract`
The core entity — one record per uploaded document.
**File Information (from upload):**
| Column | Type | Notes |
|--------|------|-------|
| `id` | `String` (cuid) | Primary key |
| `userId` | `String` | FK → User.id (cascade delete) |
| `fileName` | `String` | Original file name |
| `fileUrl` | `String` | UploadThing CDN URL |
| `fileSize` | `Int` | File size in bytes |
| `mimeType` | `String` | `application/pdf` or `image/*` |
**AI-Extracted Fields (filled after analysis):**
| Column | Type | Notes |
|--------|------|-------|
| `title` | `String?` | Contract title |
| `type` | `ContractType?` | Enum (see below) |
| `provider` | `String?` | Insurance company / bank name |
| `policyNumber` | `String?` | Policy or contract reference number |
| `startDate` | `DateTime?` | Contract start date |
| `endDate` | `DateTime?` | Contract end / expiry date |
| `premium` | `Decimal(10,2)?` | Annual/monthly premium amount |
| `extractedText` | `String?` (Text) | Full text extracted from document |
| `summary` | `String?` (Text) | 4-6 sentence AI summary |
| `keyPoints` | `Json?` | Guarantees, exclusions, explainability |
**Processing:**
| Column | Type | Notes |
|--------|------|-------|
| `status` | `ContractStatus` | Default: `UPLOADED` |
**Blockchain Proof:**
| Column | Type | Notes |
|--------|------|-------|
| `documentHash` | `String?` | SHA-256 hash of the file (0x-prefixed) |
| `txHash` | `String?` | Ethereum transaction hash |
| `blockNumber` | `Int?` | Block number where tx was mined |
| `blockTimestamp` | `DateTime?` | Block timestamp = legal proof date |
| `blockchainNetwork` | `String?` | `"hardhat"` or `"sepolia"` |
| `contractAddress` | `String?` | DocumentRegistry contract address |
**Indexes:** `userId`, `status`, `type`, `endDate`
**Relations:** `ContractRagChunk[]`, `Notification[]`, `BlockchainTransaction[]`
---
### `ContractRagChunk`
Stores text chunks and their vector embeddings for RAG (Retrieval-Augmented Generation).
| Column | Type | Notes |
|--------|------|-------|
| `id` | `String` (cuid) | Primary key |
| `contractId` | `String` | FK → Contract.id (cascade delete) |
| `chunkIndex` | `Int` | Position in the document |
| `content` | `String` | Raw text content of the chunk |
| `contentHash` | `String` | SHA-256 of content (deduplication) |
| `embedding` | `Float[]` | Gemini text-embedding-004 vector |
| `createdAt` | `DateTime` | — |
| `updatedAt` | `DateTime` | — |
**Unique constraint:** `(contractId, chunkIndex)` — no duplicate chunks per contract.
**Indexes:** `contractId`, `contentHash`, `chunkIndex`
> **Note:** PostgreSQL stores `Float[]` as a native array column. Cosine similarity is computed in application code, not via pgvector. A future enhancement could migrate to pgvector for large-scale similarity search.
---
### `Notification`
In-app notifications for users.
| Column | Type | Notes |
|--------|------|-------|
| `id` | `String` (cuid) | Primary key |
| `userId` | `String` | FK → User.id (cascade delete) |
| `contractId` | `String?` | Optional FK → Contract.id (set null on delete) |
| `type` | `NotificationType` | Enum: SUCCESS, WARNING, ERROR, INFO, DEADLINE |
| `title` | `String` | Short notification title |
| `message` | `String` | Full notification message |
| `icon` | `String?` | Icon identifier for UI rendering |
| `actionType` | `String?` | e.g., `"RENEWAL_REMINDER"`, `"UPLOAD_SUCCESS"` |
| `actionData` | `Json?` | Additional action-specific payload |
| `read` | `Boolean` | Default: `false` |
| `createdAt` | `DateTime` | — |
| `expiresAt` | `DateTime?` | Optional expiration for auto-cleanup |
**Indexes:** `userId`, `contractId`, `type`, `read`, `createdAt`
---
### `BlockchainTransaction`
Audit log of every on-chain document registration.
| Column | Type | Notes |
|--------|------|-------|
| `id` | `String` (cuid) | Primary key |
| `userId` | `String` | FK → User.id (cascade delete) |
| `contractId` | `String` | FK → Contract.id (cascade delete) |
| `documentHash` | `String` | SHA-256 hash of the document |
| `txHash` | `String` (unique) | Ethereum transaction hash |
| `blockNumber` | `Int` | Block number where tx was mined |
| `blockTimestamp` | `DateTime` | Block timestamp |
| `network` | `String` | `"hardhat"` or `"sepolia"` |
| `contractAddress` | `String` | Smart contract address |
| `status` | `String` | Default: `"CONFIRMED"` (PENDING/CONFIRMED/FAILED) |
| `createdAt` | `DateTime` | — |
**Indexes:** `userId`, `contractId`, `txHash`, `network`
---
## Enums
### `ContractType`
| Value | Description |
|-------|-------------|
| `INSURANCE_AUTO` | Auto/vehicle insurance |
| `INSURANCE_HOME` | Home/property insurance |
| `INSURANCE_HEALTH` | Health insurance |
| `INSURANCE_LIFE` | Life insurance |
| `LOAN` | Bank loan / mortgage |
| `CREDIT_CARD` | Credit card agreement |
| `INVESTMENT` | Investment / fund agreement |
| `OTHER` | Any other contract type |
### `ContractStatus`
| Value | Description |
|-------|-------------|
| `UPLOADED` | File received, awaiting analysis |
| `PROCESSING` | AI analysis in progress |
| `COMPLETED` | Analysis done and blockchain registered |
| `FAILED` | Analysis or registration failed |
### `NotificationType`
| Value | Description |
|-------|-------------|
| `SUCCESS` | Successful operation (analysis complete, etc.) |
| `WARNING` | Non-critical issue or approaching deadline |
| `ERROR` | Failed operation |
| `INFO` | General informational message |
| `DEADLINE` | Contract expiry deadline approaching |
---
## Database Operations
### Migrations
```bash
# Create a new migration in development
npm run db:migrate:dev -- --name <migration_name>
# Apply pending migrations in production
npm run db:migrate
# Regenerate Prisma client after schema changes
npm run db:generate
```
### Prisma Studio (visual DB browser)
```bash
npm run db:studio
```
### Connection Pooling (Production)
For high-traffic production deployments, use **PgBouncer** or **Prisma Accelerate** to pool PostgreSQL connections. The `DATABASE_URL` format with connection pooling:
```
DATABASE_URL="postgresql://USER:PASS@HOST:PORT/DB?pgbouncer=true&connection_limit=1"
```
Set `connection_limit=1` when using PgBouncer in transaction mode.

279
docs/04-api-reference.md Normal file
View File

@@ -0,0 +1,279 @@
# 04 — API Reference
This document covers all Next.js route handlers (`app/api/`) and key server actions (`features/*/api/`).
> **Authentication:** All protected endpoints require a valid Clerk session. Unauthenticated requests receive a `401 Unauthorized` response. Route-level protection is enforced by `proxy.ts` (Clerk middleware).
---
## Route Handlers (`app/api/`)
### `POST /api/uploadthing`
**File:** `app/api/uploadthing/route.ts`
**Purpose:** UploadThing file upload endpoint. Handles authenticated file uploads and triggers contract creation.
**Constraints:**
- Max file size: 32 MB
- Accepted types: `application/pdf`, `image/jpeg`, `image/png`, `image/webp`
- Authentication: Clerk session required
**Flow:**
1. UploadThing middleware validates the session via Clerk
2. File is stored on UploadThing CDN
3. On completion, returns `{ fileUrl, fileName, fileSize, mimeType }` to the client
---
### `POST /api/webhooks/clerk`
**File:** `app/api/webhooks/clerk/route.ts`
**Purpose:** Receives Clerk lifecycle events and syncs user data to PostgreSQL.
**Verification:** Request signature verified via Svix + `CLERK_WEBHOOK_SECRET`
**Handled Events:**
| Event | Action |
|-------|--------|
| `user.created` | Creates a new `User` record in PostgreSQL |
| `user.updated` | Updates `email`, `firstName`, `lastName`, `imageUrl` |
| `user.deleted` | Deletes `User` record (cascades to contracts, notifications) |
**Response:** `200 OK` on success, `400 Bad Request` if signature invalid.
---
### `GET /api/contracts/[id]/download`
**File:** `app/api/contracts/[id]/download/route.ts`
**Purpose:** Proxies contract file download through the server (adds auth check before serving).
**Authentication:** Clerk session + ownership validation
**Response:** File stream with appropriate `Content-Type` and `Content-Disposition` headers.
---
## Server Actions (`features/contracts/api/contract.action.ts`)
All server actions are decorated with `"use server"` and perform double authentication (Clerk session + DB ownership check).
---
### `saveContract(data)`
Saves a new contract after UploadThing upload, then **automatically triggers AI analysis**.
**Parameters:**
```typescript
{
fileName: string
fileUrl: string
fileSize: number
mimeType: string
}
```
**Returns:**
```typescript
{ success: true, contract: Contract } |
{ success: true, contract: Contract, analysisSuccess: false, analysisError: string } |
{ success: false, error: string }
```
**Side effects:**
- Creates `Contract` record (status: `UPLOADED`)
- Creates in-app notification (upload success)
- Triggers `analyzeContractAction()` automatically
- Revalidates `/contacts` and `/dashboard`
---
### `getContracts(filters?)`
Returns all contracts for the authenticated user with optional filtering.
**Parameters:**
```typescript
{
status?: ContractStatus
type?: ContractType
search?: string // searches title, provider, policyNumber, fileName
}
```
**Returns:**
```typescript
{
success: true,
contracts: SerializedContract[]
}
```
**Serialization:** `Decimal``number`, `Date` → ISO string
---
### `getContract(id)`
Returns a single contract by ID.
**Parameters:** `id: string` (contract ID)
**Returns:** `{ success: true, contract: Contract } | { success: false, error: string }`
---
### `deleteContract(id)`
Permanently deletes a contract (ownership validated, cascades to RAG chunks and notifications).
**Returns:** `{ success: true } | { success: false, error: string }`
**Side effects:**
- Deletes file from UploadThing CDN
- Cascades delete to `ContractRagChunk`, `Notification`, `BlockchainTransaction`
- Creates in-app notification (delete success)
- Revalidates `/contacts` and `/dashboard`
---
### `deleteAllContractsAction()`
Deletes all contracts for the authenticated user.
**Returns:** `{ success: true, deletedCount: number } | { success: false, error: string }`
---
### `analyzeContractAction(id)`
Triggers the full AI analysis pipeline for a contract.
**Parameters:** `id: string` (contract ID)
**Returns:**
```typescript
{ success: true, contract: NormalizedAnalysis } |
{
success: false,
error: string,
errorCode: "INVALID_CONTRACT" | "ANALYSIS_ERROR"
}
```
**Pipeline:**
1. Set status → `PROCESSING`
2. Run AI extraction (Gemini → Mistral fallback)
3. Validate AI output
4. Save extracted fields to DB
5. Build RAG chunks (embeddings)
6. Register document hash on blockchain (non-blocking)
7. Send analysis complete email (non-blocking)
8. Create in-app notification
9. Set status → `COMPLETED`
**Error codes:**
- `INVALID_CONTRACT` — uploaded file is not a recognized contract document
- `ANALYSIS_ERROR` — analysis pipeline failed (AI error, parse error, etc.)
---
### `askContractQuestionAction(id, question)`
Answers a natural-language question about a specific contract using RAG + AI.
**Parameters:**
```typescript
id: string // contract ID
question: string // user's question
```
**Returns:**
```typescript
{ success: true, answer: string } |
{ success: false, error: string }
```
**Pipeline:**
1. Load contract from DB
2. RAGService retrieves top-6 most relevant chunks
3. AIService sends question + contract context + RAG chunks to Gemini
4. Sanitized answer returned to UI
---
### `getContractStats()`
Returns analytics data for the dashboard.
**Returns:**
```typescript
{
success: true,
stats: {
total: number
byStatus: Record<ContractStatus, number>
byType: Record<ContractType, number>
byMonth: Array<{ month: string, count: number }>
expiringSoon: number
averagePremium: number | null
blockchainCoverage: number // percentage
}
}
```
---
## Notification Server Actions
**File:** `features/notifications/api/` (or `lib/services/notification.service.ts`)
### `getNotificationsAction()`
Returns all unread (and recent read) notifications for the user.
### `markNotificationReadAction(id)`
Marks a single notification as read.
### `markAllNotificationsReadAction()`
Marks all notifications as read.
### `deleteNotificationAction(id)`
Deletes a single notification.
---
## Blockchain Server Actions
**File:** `features/blockchain/api/`
### `getBlockchainStatsAction()`
Returns network stats: total verified docs, block number, network name, connection status.
### `verifyDocumentAction(documentHash)`
Verifies whether a given SHA-256 hash is registered on-chain.
**Returns:**
```typescript
{
exists: boolean
timestamp: number // Unix timestamp
depositor: string // Ethereum address
formattedDate: string // Human-readable date
}
```
---
## Health Check Endpoint
The Dockerfile `HEALTHCHECK` calls:
```
GET /api/health
```
This route should return `200 OK` with `{ status: "ok" }`.
If this route does not exist, create it at `app/api/health/route.ts`:
```typescript
export async function GET() {
return Response.json({ status: "ok" });
}
```

281
docs/05-smart-contract.md Normal file
View File

@@ -0,0 +1,281 @@
# 05 — Smart Contract: DocumentRegistry
**File:** `blockchain/contracts/DocumentRegistry.sol`
**Solidity version:** `^0.8.24`
**Network:** Ethereum Sepolia Testnet (production) / Hardhat Local (development)
**Purpose:** Tamper-proof, timestamped proof-of-deposit for BFSI contract documents.
---
## Design Philosophy
> No document content is stored on-chain — only its SHA-256 hash.
This design provides:
- **Privacy**: No sensitive data ever reaches the blockchain
- **Verifiability**: Anyone with the original document can verify it existed at a specific time
- **Immutability**: Once registered, the hash and timestamp cannot be altered
- **Legal Standing**: Block timestamp provides a cryptographically provable submission date
---
## How It Works
```
1. User uploads contract PDF to LexiChain
2. Server computes SHA-256 hash of the raw file bytes
3. Server wallet signs and sends registerDocument(bytes32) transaction
4. Transaction is mined → block.timestamp becomes the proof date
5. txHash, blockNumber, blockTimestamp saved to PostgreSQL
6. User can verify anytime via verifyDocument(bytes32)
```
---
## Contract Architecture
### State Variables
| Variable | Type | Visibility | Description |
|----------|------|-----------|-------------|
| `owner` | `address` | `public` | Platform backend wallet address |
| `totalDocuments` | `uint256` | `public` | Total number of registered document hashes |
| `documents` | `mapping(bytes32 => DocumentRecord)` | `private` | Hash → registration record |
| `depositorDocuments` | `mapping(address => bytes32[])` | `private` | Address → list of hashes they registered |
### Structs
```solidity
struct DocumentRecord {
uint256 timestamp; // block.timestamp at registration
address depositor; // msg.sender (platform wallet)
bool exists; // false = not registered
}
```
### Events
```solidity
event DocumentRegistered(
bytes32 indexed docHash,
uint256 timestamp,
address indexed depositor
);
event DocumentVerified(
bytes32 indexed docHash,
bool exists,
address indexed verifier
);
```
### Modifiers
```solidity
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function");
_;
}
```
---
## Function Reference
### `registerDocument(bytes32 _docHash)` — write
```
Access: onlyOwner
Gas: ~50,000 gas
```
Registers a document hash on-chain. Reverts if the same hash is already registered (idempotent via `requires`).
**Parameters:**
- `_docHash` — SHA-256 hash of the document as `bytes32`
**Emits:** `DocumentRegistered(docHash, block.timestamp, msg.sender)`
---
### `verifyDocument(bytes32 _docHash)` — view (free)
```
Access: Anyone
Gas: 0 (read-only call)
```
Checks if a document hash is registered and returns its record.
**Returns:**
```solidity
bool exists // true if registered
uint256 timestamp // Unix timestamp of registration (0 if not found)
address depositor // Address that registered it (address(0) if not found)
```
---
### `getTimestamp(bytes32 _docHash)` — view (free)
Returns only the registration timestamp for a given hash (0 if not registered).
---
### `getDocumentsByDepositor(address _depositor)` — view (free)
Returns all document hashes registered by a specific address.
---
### `getDocumentCount(address _depositor)` — view (free)
Returns the count of documents registered by a specific address.
---
### `transferOwnership(address _newOwner)` — write
```
Access: onlyOwner
```
Transfers contract ownership to a new address. Required if the platform wallet changes.
---
## ABI (Application Binary Interface)
```json
[
"function registerDocument(bytes32 _docHash) external",
"function verifyDocument(bytes32 _docHash) external view returns (bool exists, uint256 timestamp, address depositor)",
"function getTimestamp(bytes32 _docHash) external view returns (uint256)",
"function getDocumentsByDepositor(address _depositor) external view returns (bytes32[] memory)",
"function getDocumentCount(address _depositor) external view returns (uint256)",
"function totalDocuments() external view returns (uint256)",
"function owner() external view returns (address)",
"function transferOwnership(address _newOwner) external",
"event DocumentRegistered(bytes32 indexed docHash, uint256 timestamp, address indexed depositor)"
]
```
---
## Security Model
| Property | Implementation |
|----------|---------------|
| **Owner-only writes** | `onlyOwner` modifier prevents anyone else from registering |
| **No duplicates** | `require(!documents[hash].exists)` prevents double-registration |
| **Privacy** | Only hashes stored — no filename, no metadata, no user data |
| **Immutability** | No update/delete functions — hashes are permanent once registered |
| **Dedicated wallet** | Platform uses a separate wallet (not a personal wallet) |
---
## Deployment
### Prerequisites
1. Install Hardhat dependencies:
```bash
cd blockchain
npm install
```
2. Compile the contract:
```bash
npx hardhat compile
```
---
### Local Development (Hardhat Node)
The `npm run dev` command in the root automatically:
1. Starts a Hardhat node on `http://localhost:8545`
2. Deploys `DocumentRegistry.sol` to the local chain
3. Saves the contract address to `blockchain/.dev-deploy.json`
4. Starts the Next.js dev server with the correct env vars
To deploy manually:
```bash
# Terminal 1: Start local node
cd blockchain
npx hardhat node
# Terminal 2: Deploy
npx hardhat run scripts/deploy.ts --network localhost
```
---
### Production (Ethereum Sepolia Testnet)
**Why Sepolia?**
- 100% free (no real ETH needed)
- Stable Ethereum testnet maintained by the Ethereum Foundation
- Supported by Etherscan, Alchemy, Infura, MetaMask
- No node to run or maintain
- Transactions viewable on https://sepolia.etherscan.io
**Step 1: Get Sepolia ETH (free)**
Use one of these faucets:
- https://sepoliafaucet.com (Alchemy — requires account)
- https://faucet.quicknode.com/ethereum/sepolia
- https://www.infura.io/faucet/sepolia
A few test ETH is enough for thousands of contract registrations (~0.0005 ETH per registration).
**Step 2: Set environment variables**
```bash
# In blockchain/.env or your shell:
SEPOLIA_RPC_URL=https://rpc.sepolia.org
DEPLOYER_PRIVATE_KEY=0x<your-dedicated-wallet-private-key>
```
> ⚠️ **CRITICAL**: Never use a wallet that holds real ETH. Create a dedicated deployment wallet.
**Step 3: Deploy to Sepolia**
```bash
cd blockchain
npx hardhat run scripts/deploy.ts --network sepolia
```
The script outputs:
```
DocumentRegistry deployed to: 0x<CONTRACT_ADDRESS>
BLOCKCHAIN_CONTRACT_ADDRESS=0x<CONTRACT_ADDRESS>
```
**Step 4: Set app environment variables**
```bash
BLOCKCHAIN_NETWORK=sepolia
BLOCKCHAIN_RPC_URL=https://rpc.sepolia.org
BLOCKCHAIN_CONTRACT_ADDRESS=0x<your-deployed-address>
BLOCKCHAIN_PRIVATE_KEY=0x<your-wallet-private-key>
```
**Step 5: Verify deployment (optional)**
Visit `https://sepolia.etherscan.io/address/<CONTRACT_ADDRESS>` to confirm deployment.
---
## Running Tests
```bash
cd blockchain
npx hardhat test
```
Test file: `blockchain/test/DocumentRegistry.test.ts`
---
## Deployed Contract Information
After deploying, record your contract address here for team reference:
| Network | Contract Address | Deployer | Deployed At |
|---------|-----------------|---------|-------------|
| Sepolia | `0x...` | `0x...` | — |
| Hardhat (dev) | Auto-deployed | Account #0 | Per session |

View File

@@ -0,0 +1,611 @@
# 06 — Deployment Guide: OpenStack VPS
This guide covers the complete deployment of LexiChain on a **private OpenStack VPS** running Ubuntu 22.04, using Docker, Nginx as a reverse proxy, and Ethereum Sepolia as the blockchain network.
**Estimated setup time:** 6090 minutes (first time)
---
## Architecture Overview
```
Internet
[Nginx] ── TLS termination ── port 443/80
[Docker: lexichain-app] ── port 3000 (internal)
├──► [PostgreSQL] ── port 5432 (internal or external)
├──► [Clerk API] ── external HTTPS
├──► [UploadThing] ── external HTTPS
├──► [Gemini API] ── external HTTPS
├──► [Mistral API] ── external HTTPS
└──► [Ethereum Sepolia RPC] ── external HTTPS
```
---
## Prerequisites
Before starting, ensure you have:
- [ ] OpenStack VPS with **Ubuntu 22.04 LTS** (minimum: 2 vCPU, 4 GB RAM, 40 GB disk)
- [ ] SSH access to the VPS
- [ ] A **PostgreSQL** database (on the same VPS or a managed DB service)
- [ ] All external service accounts set up (Clerk, UploadThing, Gemini, Mistral)
- [ ] A Sepolia ETH wallet with some test ETH (see [Smart Contract docs](./05-smart-contract.md))
- [ ] The `DocumentRegistry` contract deployed to Sepolia (see [Smart Contract docs](./05-smart-contract.md))
---
## Part 1: VPS Initial Setup
### 1.1 Connect and update the VPS
```bash
ssh ubuntu@<VPS_IP>
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git unzip ufw
```
### 1.2 Configure the firewall (UFW)
```bash
# Allow SSH (important: do this FIRST to avoid locking yourself out)
sudo ufw allow OpenSSH
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable firewall
sudo ufw enable
# Verify
sudo ufw status
```
> If you are using OpenStack Security Groups, also open ports 80, 443, and 22 in the Security Group rules on the OpenStack dashboard.
---
## Part 2: Install Docker
```bash
# Install Docker
curl -fsSL https://get.docker.com | sudo sh
# Add your user to the docker group (avoids needing sudo for docker commands)
sudo usermod -aG docker $USER
# Log out and back in for the group change to take effect
exit
# ... reconnect via SSH ...
# Verify
docker --version
docker compose version
```
---
## Part 3: Set Up PostgreSQL
**Option A: PostgreSQL on the same VPS (recommended for simplicity)**
```bash
sudo apt install -y postgresql postgresql-contrib
# Start and enable PostgreSQL
sudo systemctl start postgresql
sudo systemctl enable postgresql
# Create database and user
sudo -u postgres psql <<EOF
CREATE USER lexichain WITH PASSWORD 'your_strong_password_here';
CREATE DATABASE lexichain OWNER lexichain;
GRANT ALL PRIVILEGES ON DATABASE lexichain TO lexichain;
EOF
```
Test the connection:
```bash
psql -U lexichain -d lexichain -h localhost -c "SELECT version();"
```
Your `DATABASE_URL` will be:
```
postgresql://lexichain:your_strong_password_here@localhost:5432/lexichain
```
**Option B: Use a managed PostgreSQL service**
If your organization provides a managed DB, use the connection string provided by that service.
---
## Part 4: Build the Docker Image
### 4.1 Clone the repository on the VPS
```bash
git clone https://github.com/your-org/lexichain.git /opt/lexichain
cd /opt/lexichain
```
Or transfer the code via `scp` / `rsync`:
```bash
# From your local machine:
rsync -avz --exclude='.git' --exclude='node_modules' --exclude='.next' \
./ ubuntu@<VPS_IP>:/opt/lexichain/
```
### 4.2 Build the Docker image
```bash
cd /opt/lexichain
docker build -t lexichain:latest .
```
This will:
1. Install npm dependencies
2. Generate Prisma client
3. Build the Next.js production bundle
4. Create a minimal runner image with a non-root user
> The build takes **38 minutes** on first run. Subsequent builds use Docker layer cache and are faster.
---
## Part 5: Configure Environment Variables
Create the production environment file:
```bash
sudo mkdir -p /etc/lexichain
sudo nano /etc/lexichain/production.env
```
Fill in all values:
```bash
# ── Application ──────────────────────────────────────
NODE_ENV=production
APP_URL=https://yourdomain.com
# If you don't have a domain yet, use http://<VPS_IP>
# APP_URL=http://<VPS_IP>
# ── Clerk Authentication ──────────────────────────────
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_...
CLERK_SECRET_KEY=sk_live_...
CLERK_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard
# ── Database ──────────────────────────────────────────
DATABASE_URL=postgresql://lexichain:your_strong_password_here@localhost:5432/lexichain
# ── File Storage (UploadThing) ────────────────────────
UPLOADTHING_TOKEN=your_uploadthing_token
UPLOADTHING_APP_ID=your_uploadthing_app_id
# ── AI — Gemini (Primary) ─────────────────────────────
AI_API_KEY1=AIza...
AI_API_KEY2=AIza... # optional second key for rotation
AI_MODEL_PRIMARY=gemini-2.5-flash-preview-04-17
AI_EMBEDDING_MODEL=text-embedding-004
# ── AI — Mistral (Fallback) ───────────────────────────
MISTRAL_API_KEY=your_mistral_api_key
AI_MODEL_FALLBACK=mistral-large-latest
AI_MODEL_MISTRAL_VISION=pixtral-large-latest
AI_MODEL_MISTRAL_OCR=mistral-ocr-latest
# ── Blockchain (Sepolia Testnet) ──────────────────────
BLOCKCHAIN_NETWORK=sepolia
BLOCKCHAIN_RPC_URL=https://rpc.sepolia.org
BLOCKCHAIN_PRIVATE_KEY=0x...
BLOCKCHAIN_CONTRACT_ADDRESS=0x...
# ── Email (SMTP) ──────────────────────────────────────
EMAIL_HOST=smtp-relay.brevo.com
EMAIL_PORT=587
EMAIL_SECURE=false
EMAIL_USER=your_brevo_smtp_user
EMAIL_PASS=your_brevo_smtp_password
MAIL_FROM=LexiChain <no-reply@yourdomain.com>
```
Secure the file:
```bash
sudo chmod 600 /etc/lexichain/production.env
```
---
## Part 6: Run Database Migrations
Before starting the app, run Prisma migrations:
```bash
docker run --rm \
--env-file /etc/lexichain/production.env \
--network host \
lexichain:latest \
npx prisma migrate deploy
```
> `--network host` allows the container to reach PostgreSQL on `localhost`.
> This command is safe to run on every deployment — it only applies pending migrations.
---
## Part 7: Start the Application
```bash
docker run -d \
--name lexichain \
--restart unless-stopped \
--env-file /etc/lexichain/production.env \
--network host \
-p 3000:3000 \
lexichain:latest
```
Verify the container is running:
```bash
docker ps
docker logs lexichain --tail 50
```
Test that the app responds:
```bash
curl http://localhost:3000/api/health
# Expected: {"status":"ok"}
```
---
## Part 8: Set Up Nginx Reverse Proxy
### 8.1 Install Nginx
```bash
sudo apt install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
```
### 8.2 Configure Nginx
```bash
sudo nano /etc/nginx/sites-available/lexichain
```
**Without TLS (temporary — use if you don't have a domain yet):**
```nginx
server {
listen 80;
server_name _; # Matches any hostname or IP
# Increase upload limits for contract PDFs
client_max_body_size 35M;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
}
```
**With TLS (recommended — requires a domain):**
```nginx
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
# Redirect all HTTP to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Increase upload limits for contract PDFs
client_max_body_size 35M;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
}
```
Enable the site:
```bash
sudo ln -s /etc/nginx/sites-available/lexichain /etc/nginx/sites-enabled/
sudo nginx -t # Test configuration
sudo systemctl reload nginx
```
### 8.3 Get TLS Certificate (if you have a domain)
```bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Follow the prompts
# Auto-renew (runs twice daily)
sudo systemctl enable certbot.timer
```
---
## Part 9: Configure Clerk Webhooks
For user sync to work in production, configure your Clerk webhook:
1. Go to [Clerk Dashboard](https://dashboard.clerk.com) → your app → **Webhooks**
2. Add a new endpoint:
- **URL**: `https://yourdomain.com/api/webhooks/clerk`
- **Events**: `user.created`, `user.updated`, `user.deleted`
3. Copy the **Signing Secret** → set as `CLERK_WEBHOOK_SECRET` in your env file
4. Restart the container after updating the env:
```bash
docker stop lexichain && docker rm lexichain
# Re-run the docker run command from Part 7
```
---
## Part 10: Verify the Deployment
Run through this checklist:
```bash
# 1. App responds
curl https://yourdomain.com/api/health
# 2. View app logs
docker logs lexichain -f
# 3. Check Nginx logs
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
```
**Manual UI verification:**
- [ ] Sign-up / sign-in flow works
- [ ] Upload a PDF contract → analysis runs
- [ ] Blockchain proof registered (check `/blockchain` page)
- [ ] Email notification received after analysis
- [ ] Dashboard stats populated
---
## Part 11: Updates & Rollbacks
### Deploy a new version
```bash
cd /opt/lexichain
# Pull latest code
git pull origin main
# Build new image
docker build -t lexichain:latest .
# Run migrations (safe — only applies new ones)
docker run --rm \
--env-file /etc/lexichain/production.env \
--network host \
lexichain:latest \
npx prisma migrate deploy
# Replace running container
docker stop lexichain && docker rm lexichain
docker run -d \
--name lexichain \
--restart unless-stopped \
--env-file /etc/lexichain/production.env \
--network host \
-p 3000:3000 \
lexichain:latest
```
### Rollback to a previous version
Tag your images before deploying to enable rollback:
```bash
# Before deploying new version, tag current as backup
docker tag lexichain:latest lexichain:backup
# If the new deployment fails, rollback:
docker stop lexichain && docker rm lexichain
docker run -d --name lexichain --restart unless-stopped \
--env-file /etc/lexichain/production.env \
--network host -p 3000:3000 \
lexichain:backup
```
---
## Part 12: Monitoring & Maintenance
### View application logs
```bash
# Live logs
docker logs lexichain -f
# Last 100 lines
docker logs lexichain --tail 100
# Filter for errors
docker logs lexichain 2>&1 | grep -i error
```
### Monitor container health
```bash
docker inspect --format='{{json .State.Health}}' lexichain | python3 -m json.tool
```
### Database maintenance
```bash
# Connect to PostgreSQL
sudo -u postgres psql -d lexichain
# Check database size
\l+
# Vacuum analyze (optimize queries)
VACUUM ANALYZE;
```
### Disk space management
```bash
# Remove unused Docker images
docker image prune -f
# Check disk usage
df -h
du -sh /var/lib/docker/
```
---
## Part 13: Environment Variable Reference
Complete reference for all variables used in production:
| Variable | Required | Description |
|----------|----------|-------------|
| `NODE_ENV` | ✅ | Must be `production` |
| `APP_URL` | ✅ | Full public URL of the app |
| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | ✅ | Clerk publishable key |
| `CLERK_SECRET_KEY` | ✅ | Clerk secret key |
| `CLERK_WEBHOOK_SECRET` | ✅ | Clerk webhook signing secret |
| `NEXT_PUBLIC_CLERK_SIGN_IN_URL` | ✅ | `/sign-in` |
| `NEXT_PUBLIC_CLERK_SIGN_UP_URL` | ✅ | `/sign-up` |
| `NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL` | ✅ | `/dashboard` |
| `NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL` | ✅ | `/dashboard` |
| `DATABASE_URL` | ✅ | PostgreSQL connection string |
| `UPLOADTHING_TOKEN` | ✅ | UploadThing auth token |
| `UPLOADTHING_APP_ID` | ✅ | UploadThing app ID |
| `AI_API_KEY1` | ✅ | Gemini API key (primary) |
| `AI_API_KEY2` | ❌ | Gemini API key (rotation) |
| `AI_API_KEY3` | ❌ | Gemini API key (rotation) |
| `AI_MODEL_PRIMARY` | ✅ | Gemini model name |
| `AI_EMBEDDING_MODEL` | ✅ | `text-embedding-004` |
| `MISTRAL_API_KEY` | ❌ | Mistral key (activates fallback) |
| `AI_MODEL_FALLBACK` | ❌ | `mistral-large-latest` |
| `AI_MODEL_MISTRAL_VISION` | ❌ | `pixtral-large-latest` |
| `AI_MODEL_MISTRAL_OCR` | ❌ | `mistral-ocr-latest` |
| `BLOCKCHAIN_NETWORK` | ✅ | `sepolia` |
| `BLOCKCHAIN_RPC_URL` | ✅ | Sepolia RPC endpoint |
| `BLOCKCHAIN_PRIVATE_KEY` | ✅ | Platform wallet private key |
| `BLOCKCHAIN_CONTRACT_ADDRESS` | ✅ | DocumentRegistry address |
| `EMAIL_HOST` | ❌ | SMTP server hostname |
| `EMAIL_PORT` | ❌ | SMTP port (587 or 465) |
| `EMAIL_SECURE` | ❌ | `false` for STARTTLS |
| `EMAIL_USER` | ❌ | SMTP username |
| `EMAIL_PASS` | ❌ | SMTP password |
| `MAIL_FROM` | ❌ | From address for emails |
---
## Troubleshooting
### Container won't start
```bash
docker logs lexichain
# Look for: DATABASE_URL connection refused, missing env vars, etc.
```
Common causes:
- `DATABASE_URL` is wrong or PostgreSQL is not running
- A required env var is missing
- Port 3000 is already in use: `sudo lsof -i :3000`
### 502 Bad Gateway from Nginx
The app is not running or not listening:
```bash
docker ps # Is the container running?
curl localhost:3000 # Does it respond locally?
docker logs lexichain --tail 20
```
### Blockchain not working
```bash
# Test RPC connectivity
curl -X POST https://rpc.sepolia.org \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# Verify your wallet has Sepolia ETH
# Check: https://sepolia.etherscan.io/address/<YOUR_WALLET_ADDRESS>
```
### AI analysis failing
- Verify `AI_API_KEY1` is valid at https://aistudio.google.com
- Check if Gemini model name is correct (model names change — check Google AI docs)
- If all Gemini keys are exhausted, verify `MISTRAL_API_KEY` is set for fallback
### Email not sending
- Without `EMAIL_HOST`, emails are silently dropped in production
- Test SMTP credentials with: `npx nodemailer-test` or Brevo's SMTP tester
- Check Brevo sending quota
---
## Security Hardening Checklist
- [ ] Production env file has `chmod 600`
- [ ] PostgreSQL password is strong (20+ random characters)
- [ ] Blockchain wallet is dedicated (not holding real ETH)
- [ ] Clerk webhooks endpoint is HTTPS only
- [ ] UFW firewall enabled with only required ports
- [ ] TLS certificate installed and auto-renewing
- [ ] `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` starts with `pk_live_` (not `pk_test_`)
- [ ] `NODE_ENV=production` set
- [ ] No `.env` file committed to git

View File

@@ -1,590 +0,0 @@
# AI Features Documentation
## 1. Overview
This document explains all AI-powered capabilities currently implemented in the BFSI contract analysis application, how data flows through the system, what resilience mechanisms are in place, and how explainability is surfaced to users.
### 1.1 AI Flow for Juniors (Start Here)
If you are new to the codebase, this is the exact AI lifecycle from upload to UI proof:
1. User uploads a document and opens it in dashboard details.
2. Analyze action validates ownership and marks status as PROCESSING.
3. AI prevalidation checks if the file is a real contract.
4. Main extraction runs with primary model; fallback model is used if needed.
5. Output is parsed, repaired when malformed, normalized to strict shape, and validated.
6. Results are persisted in DB (title, dates, premium, summary, key points, explainability evidence, extracted text).
7. Continuous learning metadata (aiMeta) is stored in keyPoints for future adaptive prompts.
8. UI shows extracted fields and proof icons next to each critical field.
9. Clicking a proof icon opens Field Proof modal:
- tries to map evidence snippet to exact line(s) in extracted text using normalized fuzzy matching,
- runs deterministic field-aware checks first (exact snippet/date/value line) before fuzzy scoring,
- falls back to snippet evidence when precise line mapping is not possible.
11. Premium amount keeps source currency semantics:
- AI is instructed to return numeric premium without conversion,
- AI also returns premiumCurrency (for example TND, USD, EUR),
- UI displays premium using detected source currency (no forced EUR formatting).
10. Q&A and reminders reuse the persisted AI output.
### 1.2 Where to Read in Code
- Orchestration: `lib/actions/contract.action.ts`
- AI core + retries + validation: `lib/services/ai.service.ts`
- Prompt contracts: `lib/services/ai/analysis.prompt.ts`
- Parser + normalizer: `lib/services/ai/analysis.parser.ts`, `lib/services/ai/analysis.normalizer.ts`
- UI proof rendering: `components/views/dashboard/contracts-list.tsx`
The AI subsystem is centered on:
- Contract prevalidation (contract vs non-contract detection)
- Contract analysis and structured field extraction
- Multi-model fallback and JSON repair
- Normalization and validation hardening
- Explainability evidence for extracted fields
- Multilingual contract Q&A
- AI-derived deadline reminders
- Field-level proof modal with line-context evidence mapping
- Snippet text search inside extracted snippets
- Continuous learning context from previous analyses (without schema migration)
## 2. Tech and Configuration
### 2.1 Core Components
- Next.js server actions for orchestration
- Gemini via @google/generative-ai for extraction and Q&A
- Prisma for persistence
- Clerk for authenticated user context
- React client UI for details modal, field-proof modal, and chat
### 2.2 Models
- Primary model: gemini-2.5-flash
- Optional secondary Gemini model: AI_MODEL_SECONDARY_GEMINI
- Fallback model provider: Mistral AI (default: mistral-large-latest, vision: pixtral-large-latest)
- Gemini models are de-duplicated and iterated in order before Mistral fallback
- Mistral extraction fallback supports both text and image inputs via Pixtral vision; JSON repair and Q&A fallback are text-based
### 2.3 Environment Variables
- AI_API_KEY (or AI_API_KEY2 / AI_API_KEY3 fallback)
- AI_MODEL_PRIMARY (optional override)
- AI_MODEL_SECONDARY_GEMINI (optional override)
- AI_MODEL_SECONDARY (legacy alias supported for compatibility)
- AI_MODEL_FALLBACK (optional override)
- MISTRAL_API_KEY
- AI_MODEL_MISTRAL_VISION (optional, default: pixtral-large-latest)
## 3. AI Capability Matrix
| Capability | Trigger | Output | Main File |
| ----------------------------- | --------------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| Prevalidation | Analyze action | isValidContract, confidence, reason | lib/services/ai.service.ts |
| Structured extraction | Analyze action | title/type/provider/policy/dates/premium/summary/key points | lib/services/ai.service.ts |
| Premium currency preservation | Analyze + normalize + UI display | premium + premiumCurrency with no currency conversion | lib/services/ai/analysis.prompt.ts + lib/services/ai/analysis.normalizer.ts + components/views/dashboard/contracts-list.tsx |
| Explainability extraction | Structured extraction prompt | field-level why + snippet + hints | lib/services/ai/analysis.prompt.ts |
| JSON repair | Parse failure | corrected JSON | lib/services/ai.service.ts |
| Emergency extraction | Repair failure | minimal valid analysis JSON | lib/services/ai.service.ts |
| Normalization | Post-parse | canonical, bounded, safe analysis object | lib/services/ai/analysis.normalizer.ts |
| Contract validity assertion | Post-normalization | pass/fail with invalid-contract reason | lib/services/ai.service.ts |
| Contract Q&A | Ask action | multilingual business/legal-oriented answer | lib/services/ai.service.ts |
| Deadline reminders | Contract save after AI completion | DEADLINE notifications at 30/15/7 days | lib/services/notification.service.ts |
| Explainability UI | Details modal | field-level proof icon, line-context modal, fuzzy evidence mapping | components/views/dashboard/contracts-list.tsx |
| Evidence quick copy | Details modal | one-click clipboard copy of compliance evidence bundle | components/views/dashboard/contracts-list.tsx |
| Snippet search | Details modal | text/field search inside extracted snippets | components/views/dashboard/contracts-list.tsx |
| Continuous learning context | Every completed analysis | adaptive context enriched from historical aiMeta/evidence | lib/actions/contract.action.ts + lib/services/ai.service.ts |
## 4. Feature Details and Sequence Diagrams
---
## 4.1 AI Contract Analysis End-to-End
### What it does
When a user clicks Analyze, the system validates ownership, marks contract as PROCESSING, performs AI prevalidation and extraction, validates results, saves structured output, and returns success or failure.
### Key resilience points
- Ownership checks before all sensitive operations
- Invalid-contract short-circuit based on AI confidence and heuristics
- Multi-pass retry with correction hints
- Multi-model fallback
### Sequence Diagram
```mermaid
sequenceDiagram
autonumber
participant U as User
participant UI as Contracts UI
participant SA as contract.action analyzeContractAction
participant CS as ContractService
participant NS as NotificationService
participant AIS as AIService
participant G as Gemini
participant DB as Prisma DB
U->>UI: Click Analyze
UI->>SA: analyzeContractAction(contractId)
SA->>CS: getById + ownership check
SA->>CS: updateStatus(PROCESSING)
SA->>NS: create ANALYSIS_STARTED notification
SA->>AIS: analyzeContract(fileUrl, userId, fileName)
AIS->>G: prevalidation prompt + file
G-->>AIS: {isValidContract, confidence, reason}
AIS->>G: analysis prompt + file
G-->>AIS: analysis JSON/raw text
AIS->>AIS: parse, repair if needed, normalize, assert validity
AIS-->>SA: NormalizedAnalysis
SA->>CS: updateWithAIResults(COMPLETED)
CS->>DB: Persist extracted fields + keyPoints + extractedText
CS->>NS: checkUpcomingDeadlines(userId)
SA->>NS: create ANALYSIS_SUCCESS notification
SA-->>UI: success + analyzed contract payload
```
---
## 4.2 Contract Prevalidation Gate
### What it does
Before expensive extraction, AI classifies whether the uploaded document is actually a contract in any language.
### Decision rules
- Rejects obvious non-contract files (invoices, IDs, blank pages, random images)
- If parse of prevalidation JSON fails, system defaults to permissive moderate confidence to avoid false negatives due malformed precheck output
### Sequence Diagram
```mermaid
sequenceDiagram
autonumber
participant AIS as AIService
participant G1 as Gemini Primary
participant G2 as Gemini Secondary (optional)
AIS->>G1: buildPrevalidationPrompt + inline file
alt Primary succeeds
G1-->>AIS: JSON precheck
else Primary fails
AIS->>G2: same precheck request (if configured)
G2-->>AIS: JSON precheck
end
AIS->>AIS: parse precheck JSON
alt parse failed
AIS-->>AIS: Assume valid with moderate confidence
else parsed
AIS-->>AIS: Return isValidContract/confidence/reason
end
```
---
## 4.3 Multi-Model Extraction + JSON Repair + Emergency Fallback
### What it does
If extraction output is malformed or incomplete, the service tries progressively stronger recovery paths.
### Recovery layers
1. Primary/Fallback model extraction with strict JSON mime type
2. Lenient generation (no forced responseMimeType JSON)
3. JSON repair pass with schema guidance
4. Emergency field extraction from raw text patterns
### Sequence Diagram
```mermaid
sequenceDiagram
autonumber
participant AIS as AIService
participant GP as Gemini Primary
participant GS as Gemini Secondary (optional)
participant MR as Mistral AI Fallback
AIS->>GP: generate analysis (strict JSON)
alt GP success with usable output
GP-->>AIS: text
else GP fails
AIS->>GS: generate analysis (strict JSON)
alt GS success
GS-->>AIS: text
else GS fails
AIS->>GP: lenient generation attempt
alt lenient success
GP-->>AIS: raw text
else lenient fails
AIS->>MR: generate analysis (strict JSON)
MR-->>AIS: text
end
end
end
AIS->>AIS: parseJsonResponse
alt parse failed
AIS->>MR: repairMalformedJson(originalText, parseError)
alt repair success
MR-->>AIS: repaired JSON text
AIS->>AIS: parse repaired JSON
else repair failed
AIS->>AIS: emergencyExtractFields(rawText)
AIS->>AIS: parse emergency JSON
end
end
```
---
## 4.4 Normalization, Validation, and Persistence
### What it does
Raw model output is converted into a strict normalized contract object and validated before DB write.
### Normalization highlights
- Contract type alias mapping into supported enum
- Date coercion to YYYY-MM-DD
- Safe string truncation and null handling
- Premium normalization and bounds
- Explainability normalization with bounded field lengths and confidence clamping
- Extracted text cap at 12000 chars
### Sequence Diagram
```mermaid
sequenceDiagram
autonumber
participant AIS as AIService
participant N as analysis.normalizer
participant V as assertValidContract
participant SA as contract.action
participant CS as ContractService
participant DB as Prisma DB
AIS->>N: normalizeAnalysis(parsed)
N-->>AIS: NormalizedAnalysis
AIS->>V: assertValidContract(raw, normalized)
alt valid
AIS-->>SA: normalized analysis
SA->>CS: updateWithAIResults
CS->>DB: update contract to COMPLETED
else invalid
V-->>SA: INVALID_CONTRACT error
SA->>CS: markFailed
end
```
---
## 4.5 Explainability Pipeline and UI Interaction
### What it does
The model is instructed to provide extraction evidence per field. The UI renders a compact proof icon near each extracted field and opens a dedicated Field Proof modal with source snippet, metadata, and line-context evidence.
### Explainability object shape
- field
- why
- sourceSnippet
- sourceHints.page
- sourceHints.section
- sourceHints.confidence
### UI enhancements implemented
- Field-level proof icon beside core extracted fields (title/provider/policy/dates/premium)
- Field Proof modal with fixed professional layout (stable regardless of content size)
- Normalized fuzzy line matching for snippet-to-line mapping in extracted text
- Fallback to extracted field value when explicit explainability snippet is absent
- Confidence/page/section metadata surfaced in proof summary chips
- Line-context panel with explicit quality state (resolved vs fallback evidence)
### Sequence Diagram
```mermaid
sequenceDiagram
autonumber
participant AI as Gemini Extraction
participant N as analysis.normalizer
participant DB as Prisma DB
participant UI as Contracts Details Modal
participant User as User
AI-->>N: keyPoints.explainability[]
N->>N: validate/sanitize/trim explainability items
N->>DB: persist explainability in keyPoints JSON
UI->>DB: fetch contract details (includes keyPoints)
DB-->>UI: explainability array
User->>UI: Click field proof icon
UI->>UI: map field to explainability evidence
UI->>UI: normalized fuzzy search in extracted text lines/windows
alt line mapping found
UI->>UI: show line number + context window
else mapping unavailable
UI->>UI: show fallback snippet evidence with quality badge
end
```
---
## 4.8 Continuous Learning Pipeline (Safe, No Schema Migration)
### What it does
The system now gets smarter after each completed analysis by persisting learned metadata into `keyPoints.aiMeta`, then reusing it in `buildAdaptiveContext` for future analyses.
### Why this design is safe
- No Prisma schema changes required
- Uses existing JSON storage (`keyPoints`)
- Backward compatible with older records
- If aiMeta is missing, system gracefully falls back to previous behavior
### Learning signals currently used
- Dominant learned languages
- Frequent key roles (from extracted key people)
- Most evidenced extracted fields (from explainability)
- Average explainability confidence score
- Existing prior signals already used: top contract types/providers/policy patterns/summary length
### Sequence Diagram
```mermaid
sequenceDiagram
autonumber
participant SA as analyzeContractAction
participant AIS as AIService
participant CS as ContractService
participant DB as Prisma DB
SA->>AIS: analyzeContract(...)
AIS-->>SA: normalized analysis + explainability + language/people/contacts
SA->>SA: merge aiMeta into keyPoints
SA->>CS: updateWithAIResults(keyPoints.aiMeta)
CS->>DB: persist COMPLETED contract
Note over AIS,DB: Next analysis for same user
AIS->>DB: fetch last completed examples with keyPoints
AIS->>AIS: derive adaptive learning signals from aiMeta + explainability
AIS->>AIS: inject enriched adaptive context into next analysis prompt
```
---
## 4.6 Multilingual Contract Q&A
### What it does
Users ask follow-up questions about a selected contract. The AI answers in the contract language using extracted fields, key points, and extracted text context.
### Behavior highlights
- Language-aware response instruction (en, fr, de, es, it, pt, nl, pl, ja, zh, ar)
- Contract-type-specific guidance for domain emphasis
- Output sanitization strips markdown artifacts
- Fallback across configured model list
### Sequence Diagram
```mermaid
sequenceDiagram
autonumber
participant U as User
participant UI as Ask Modal
participant SA as askContractQuestionAction
participant CS as ContractService
participant AIS as AIService
participant G as Gemini
U->>UI: Ask question
UI->>SA: askContractQuestionAction(contractId, question)
SA->>CS: getById + ownership check
SA->>AIS: askAboutContract(question, contractContext)
AIS->>AIS: determine language + type guidance
AIS->>G: Q&A prompt with metadata, summary, keyPoints, extracted text
G-->>AIS: answer text
AIS->>AIS: sanitize formatting artifacts
AIS-->>SA: final answer
SA-->>UI: answer
```
---
## 4.7 AI-Derived Deadline Notifications
### What it does
After successful AI extraction and save, reminder notifications are generated from extracted contract end date.
### Reminder policy
- 30 days: CRITICAL
- 15 days: WARNING
- 7 days: URGENT
- Duplicate prevention based on recent existing reminder action type
### Sequence Diagram
```mermaid
sequenceDiagram
autonumber
participant SA as analyzeContractAction
participant CS as ContractService
participant NS as NotificationService
participant DB as Prisma DB
SA->>CS: updateWithAIResults(COMPLETED)
CS->>NS: checkUpcomingDeadlines(userId)
NS->>DB: find COMPLETED contracts with endDate
loop each contract
NS->>NS: compute daysUntilExpiration
alt day is 30/15/7 and no duplicate today
NS->>DB: create DEADLINE notification
end
end
NS-->>CS: created count summary
```
## 5. Data Contracts
### 5.1 Normalized Analysis (core)
- title
- type
- provider
- policyNumber
- startDate
- endDate
- premium
- summary
- extractedText
- keyPoints (guarantees, exclusions, franchise, importantDates, explainability)
- language
- keyPeople
- contactInfo
- importantContacts
- relevantDates
### 5.2 Explainability Item
- field: extracted field identifier
- why: concise reasoning sentence
- sourceSnippet: quoted support from document
- sourceHints: page/section/confidence for audit context
## 6. Security and Guardrails
- Ownership validation before analyze and ask operations
- Contract validity checks to reject unrelated uploads
- Bounded extracted text and structured truncation to reduce prompt and storage risk
- Retry and fallback paths to reduce failure rate without unsafe assumptions
- Missing-notification-table safe handling in notification service
## 7. Failure Modes and Handling
### 7.1 Non-contract file
- Outcome: analysis fails with INVALID_CONTRACT code
- User feedback: explicit invalid contract reason
### 7.2 Malformed AI JSON
- Outcome: repair pass, then emergency extraction fallback
- User impact: improved completion rate with bounded quality fallback
### 7.3 Model/API/key issues
- Outcome: explicit error messages for API key/model configuration
### 7.4 Notification table missing
- Outcome: notification operations degrade gracefully without blocking core contract workflow
## 8. UX Features for Explainability and Compliance
- Proof icon per extracted field for one-click transparency
- Professional Field Proof modal with fixed sections and stable dimensions
- Fuzzy snippet-to-line mapping to reduce unresolved line cases
- Deterministic field-specific matching before fuzzy mode (especially for dates)
- Fallback evidence mode when OCR/formatting prevents exact line resolution
- Confidence/page/section metadata chips for compliance readability
- Extracted snippets section with search and field reference tags
## 9. Test Plan (Step-by-Step)
### 9.1 Field Proof Resolution
1. Upload and analyze a contract with clear dates/amounts.
2. Open Details modal.
3. Click proof icon next to `Title`, `End Date`, or `Premium`.
4. Verify Field Proof modal opens with line/page/section/confidence chips.
5. Verify line context appears with numbered rows and a marker on matched line.
### 9.2 Snippet Search Box
1. In the `Extracted Text Snippets` section, type a keyword (for example `premium`, `TND`, `2044`, `endDate`).
2. Verify only matching snippets remain visible.
3. Clear the search and verify all snippets return.
### 9.3 Fallback Evidence Mode
1. Test with a contract where OCR quality is noisy or formatting is table-heavy.
2. Click field proof icon for a difficult field.
3. Verify modal still shows exact source snippet with a fallback quality badge.
4. Verify user still receives proof even when exact line number is unavailable.
### 9.4 Layout Consistency
1. Open field proof for short and very long snippets.
2. Verify modal section heights remain visually consistent.
3. Verify metadata chips keep a stable grid layout across content lengths.
### 9.5 Continuous Learning (AI Gets Smarter Over Time)
1. Analyze at least 3 contracts from the same provider or domain.
2. Analyze a 4th similar contract.
3. Verify extraction quality improves in consistency for:
- provider naming style
- policy number patterns
- detected language and role patterns
- evidence confidence on common fields
4. In server logs, confirm adaptive context includes learned indicators (languages/evidenced fields/roles/confidence).
### 9.6 Multilingual Q&A Consistency
1. Analyze a non-English contract (for example French).
2. Ask a question in Ask modal.
3. Verify answer is in contract language and aligned to extracted context.
## 10. Suggested Operational Checks
- Run build after AI prompt or normalizer changes
- Spot-check at least one document per supported major language
- Verify explainability has non-empty source snippets for key fields
- Verify deadline notifications for synthetic end dates at 30/15/7 days
- Validate ask flow stays in detected contract language
## 11. File Index
- lib/actions/contract.action.ts
- lib/services/ai.service.ts
- lib/services/ai/analysis.prompt.ts
- lib/services/ai/analysis.normalizer.ts
- lib/services/ai/analysis.types.ts
- lib/services/contract.service.ts
- lib/services/notification.service.ts
- components/views/dashboard/contracts-list.tsx
- types/contract.types.ts

View File

@@ -1,274 +0,0 @@
# Complete Dashboard Redesign - Implementation Summary
## 🎯 Architecture Overview
The dashboard has been reorganized into two distinct routes with a persistent navigation sidebar:
### Route Structure
```
/dashboard → Analytics Hub (Stats & Charts)
/contacts → Contracts Manager (Upload & Management)
```
---
## 📊 New /dashboard Route Features
### 1. **Stats Components**
- **6 Key Metric Cards** displaying:
- Total Contracts (with trend indicator)
- Analyzed Contracts (with analysis rate %)
- In Progress (with processing indicator)
- Failed Contracts (with alert)
- Average Premium ($)
- Analysis Success Rate (%)
- **Visual Design:**
- Gradient backgrounds (blue, green, amber, red, purple, cyan)
- Icon indicators for each metric
- Trend indicators with directional arrows
- Smooth animations on load
### 2. **Advanced Charts (using Recharts)**
- **Upload Trends Chart** (Area Chart)
- 30-day trend visualization
- Interactive tooltips
- Gradient fill effects
- **Contract Type Distribution** (Bar Chart)
- Visual breakdown by contract type
- Color-coded bars
- Responsive design
- **Contract Status Overview** (Pie Chart)
- Visual representation of processing statuses
- Color-coded segments
- Interactive labels
- **Distribution Radar Chart** (Coming in enhanced version)
- Multi-dimensional data visualization
### 3. **Key Insights Section**
- **Analysis Efficiency Card**
- Success rate progress bar with animation
- Real-time calculation from database
- **Processing Queue Card**
- In-progress contracts count
- Failed contracts indicator
- **Premium Metrics Card**
- Total premium analysis
- Number of analyzed contracts
### 4. **Quick Actions**
- **Upload New Contract** → Links to /contacts
- **View All Contracts** → Links to /contacts with count
---
## 🗂️ New /contacts Route Features
### 1. **Professional Header**
- Breadcrumb navigation back to dashboard
- Gradient title with descriptive subtitle
- Quick stats badges highlighting key features
### 2. **Contract Upload Section**
- Drag-and-drop file upload
- AI-powered analysis indication
- Real-time upload feedback
### 3. **Contracts List & Management**
- Existing contracts display with new styling
- Analysis status indicators
- Ask questions feature (existing, now integrated)
- Contract details modal
---
## 🎨 Design System Enhancements
### Visual Elements
- **Animated Gradient Backgrounds**
- Floating blob animations in background
- Smooth color transitions
- Dark mode optimized
- **Color Palette**
- Primary: Blue (#3B82F6)
- Accent: Gradient colors
- Semantic colors for status indicators
- **Typography**
- Bold headlines with gradient text
- Clear visual hierarchy
- Responsive font sizing
- **Animations**
- Fade-in effects on page load
- Smooth transitions between states
- Motion/Framer Motion integration
- Staggered card animations
### Components
- Shadcn/UI for consistent design
- Custom stat cards with gradients
- Backdrop blur effects
- Border styling with transparency
---
## 🔧 Technical Implementation
### New Files Created
1. **Services**
- `lib/services/stats.service.ts` → Database queries for analytics
- `lib/actions/stats.action.ts` → Server action wrapper
2. **Components**
- `components/views/dashboard/stat-cards.tsx` → Metric cards
- `components/views/dashboard/charts.tsx` → Recharts integration
- `components/views/dashboard/navigation.tsx` → Sidebar navigation
- `components/views/dashboard/contacts-header.tsx` → Contacts page header
3. **Routes**
- `app/(dashboard)/contacts/layout.tsx` → Contacts route layout
- `app/(dashboard)/contacts/page.tsx` → Contacts page with upload & list
4. **Updated Files**
- `app/(dashboard)/layout.tsx` → Sidebar integration
- `app/(dashboard)/dashboard/page.tsx` → New analytics dashboard
---
## 📈 Data & Analytics
### Stats Service Features
```typescript
{
stats: {
totalContracts: number
analyzedContracts: number
processingContracts: number
failedContracts: number
analysisRate: percentage
},
chartData: {
byType: Array<{type, count}>
byStatus: Array<{status, count}>
trends: Array<{date, count}> // Last 30 days
},
premiumInfo: {
averagePremium: number
totalPremium: number
count: number
},
recentContracts: Array<{id, title, type, createdAt, premium}>
}
```
### Database Queries
- Aggregated counts by status, type, and date
- Premium statistics (avg, sum, count)
- 30-day trend analysis
- Recent contracts ranking
---
## 🎯 Navigation System
### Sidebar Features
- **Logo with brand identity**
- **Two main navigation items**
- Analytics (Dashboard)
- Contracts (Management)
- **Theme toggle** (Light/Dark mode)
- **Sign out button**
- **Responsive active states**
- **Smooth transitions and animations**
---
## 🚀 Performance & UX
### Optimizations
- Client-side state management for smooth interactions
- Server-side analytics computation
- Lazy loading of components
- Efficient database queries with aggregation
- Responsive design for all screen sizes
### Accessibility
- Semantic HTML structure
- ARIA labels on icons
- Clear visual hierarchy
- High contrast ratios
- Keyboard navigation support
---
## 📱 Responsive Design
- **Desktop (1024px+)**: Full sidebar + expanded content
- **Tablet (768px-1023px)**: Flexible grid layouts
- **Mobile**: Responsive charts and card layouts
---
## 🎬 Next Steps & Enhancements
### Future Improvements
1. **Export Reports** → PDF/Excel export functionality
2. **Advanced Filtering** → Filter contracts by date, type, status
3. **Custom Dashboards** → User-customizable dashboard layouts
4. **Real-time WebSocket Updates** → Live processing status
5. **Performance Optimization** → Data caching and infinite scroll
6. **Dark Mode Enhancements** → More sophisticated theme system
7. **Mobile App** → Native mobile experience
---
## 🔐 Security & Authorization
- User ID verification in all server actions
- Clerk authentication integration
- Database queries filtered by userId
- Server-side data serialization
---
## 📦 Dependencies Used
- `recharts` (v3.7.0) - Chart visualizations
- `motion` - Animations
- `lucide-react` - Icons
- `shadcn/ui` - UI components
- `@clerk/nextjs` - Authentication
---
## ✅ Testing Checklist
- [x] All TypeScript types compile correctly
- [x] No console errors on load
- [x] Navigation between routes works smoothly
- [x] Stats query returns valid data
- [x] Charts render with sample data
- [x] Responsive design on mobile/tablet
- [x] Dark mode toggle functions
- [x] Animations perform smoothly
- [x] Sidebar navigation is responsive
- [x] User authentication required

View File

@@ -1,103 +0,0 @@
# Deployment Guide (OpenStack + Docker)
This guide deploys the Next.js app as a Docker container on a private OpenStack environment.
## 1) Prerequisites
- OpenStack project with a VM (Ubuntu 22.04 or similar)
- Docker Engine installed on the VM
- A PostgreSQL database reachable from the VM
- A blockchain RPC endpoint (Sepolia or private chain)
- A deployed DocumentRegistry contract address
## 2) Build the Docker image (local or CI)
From the project root:
```
docker build -t lexichain-app:latest .
```
Optionally tag and push to your private registry.
## 3) Runtime environment variables
Create a file named `lexichain.env` on the VM with the required secrets.
Example (fill with your real values):
```
NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://USER:PASSWORD@HOST:PORT/DBNAME
CLERK_PUBLISHABLE_KEY=...
CLERK_SECRET_KEY=...
CLERK_WEBHOOK_SECRET=...
UPLOADTHING_SECRET=...
UPLOADTHING_APP_ID=...
GOOGLE_AI_API_KEY=...
BLOCKCHAIN_NETWORK=sepolia
BLOCKCHAIN_RPC_URL=https://...
BLOCKCHAIN_CONTRACT_ADDRESS=0x...
BLOCKCHAIN_PRIVATE_KEY=0x...
```
If you use a private chain, set `BLOCKCHAIN_NETWORK` accordingly.
## 4) Run the container on the VM
```
docker run -d \
--name lexichain-app \
--restart unless-stopped \
--env-file /path/to/lexichain.env \
-p 3000:3000 \
lexichain-app:latest
```
## 5) Database migration (first deploy)
Run migrations from the container image (or from CI) before first launch:
```
docker run --rm \
--env-file /path/to/lexichain.env \
lexichain-app:latest \
npx prisma migrate deploy
```
## 6) OpenStack security group / firewall
Allow inbound traffic to port 3000 from your internal network or from the reverse proxy.
## 7) Optional: reverse proxy
Place Nginx or HAProxy in front of the app for TLS termination and HTTP/2.
## 8) Health check
Open `http://<vm-ip>:3000` and validate:
- Sign-in flow
- Upload + AI analysis
- Blockchain explorer stats
- Document verification
## 9) Update / rollout
- Build a new image and push to your registry.
- Pull on the VM and restart the container:
```
docker pull registry.example.com/lexichain-app:latest
docker stop lexichain-app
docker rm lexichain-app
docker run -d \
--name lexichain-app \
--restart unless-stopped \
--env-file /path/to/lexichain.env \
-p 3000:3000 \
registry.example.com/lexichain-app:latest
```

View File

@@ -1,506 +0,0 @@
# 🔔 Notification System Implementation - Complete Guide
## ✨ What Was Implemented
You've successfully enabled Option 2: **Renewal and Deadline Assistant** with comprehensive notification system.
### 🎯 Key Features
1. **Toast Notifications** (Sonner)
- ✅ Contract uploaded successfully
- ✅ Contract analyzed successfully (or error with reason)
- ✅ Contract deleted successfully
- ❌ Error messages with detailed feedback
- 🔔 Deadline alerts for upcoming expirations
2. **Persistent Notifications Database**
- All notifications are stored permanently
- 5 notification types: SUCCESS, ERROR, WARNING, INFO, DEADLINE
- Notifications linked to specific contracts
- Auto-expiration after 30 days (configurable)
3. **Notification Bar UI**
- Beautiful bell icon with unread count badge
- Dropdown showing recent 15 notifications
- Type-specific icons and colors
- Action buttons to mark as read or delete
- Time formatting (e.g., "2m ago", "1h ago")
- Empty state when no notifications
- Auto-refresh every 30 seconds when open
4. **Deadline Detection & Alerts**
- 🔴 **30 Days Before Expiration**: CRITICAL notification
- 🟠 **15 Days Before Expiration**: WARNING notification
- 🟡 **7 Days Before Expiration**: URGENT notification
- Daily automatic check on dashboard load
- Smart deduplication (max 1 notification per threshold per day)
5. **Well-Documented Code**
- 1000+ lines of comprehensive inline comments
- JSDoc comments for all functions
- Step-by-step explanations of processing pipelines
- Examples and usage patterns
## 📁 Files Created/Modified
### New Files Created
```
✨ lib/services/notification.service.ts (580 lines) - Core notification logic
✨ lib/actions/notification.action.ts (340 lines) - Server actions for notifications
✨ components/views/dashboard/notification-bar.tsx (490 lines) - Notification UI component
✨ hooks/useNotifications.ts (220 lines) - React hook for toast + notifications
✨ NOTIFICATION_SYSTEM_SETUP.md (400 lines) - Detailed setup guide
✨ setup-notifications.sh (30 lines) - Automated setup script
```
### Files Modified
```
📝 prisma/schema.prisma - Added Notification model, NotificationType enum
📝 lib/actions/contract.action.ts - Added notifications on upload/analyze/delete
📝 lib/services/contract.service.ts - Added getUserByClerkId() method
📝 components/views/dashboard/navigation.tsx - Added NotificationBar component
📝 app/(dashboard)/dashboard/page.tsx - Added checkDeadlineNotifications() call
```
## 🚀 Quick Start
### 1. Run Database Migration
```bash
npx prisma migrate dev --name add_notifications
```
This creates:
- `Notification` table with indexes
- `NotificationType` enum (SUCCESS, WARNING, ERROR, INFO, DEADLINE)
- Relations between User, Contract, and Notification
### 2. Generate Prisma Client
```bash
npx prisma generate
```
Or use the automated setup script:
```bash
bash setup-notifications.sh
```
### 3. Start Development Server
```bash
npm run dev
```
## 📊 Architecture Overview
### Notification Flow
```
User Action (upload/analyze/delete)
Contract Server Action
├─ Execute operation (save/analyze/delete)
├─ Create Sonner toast (immediate UI feedback)
└─ Create database notification (persistent)
Notification Service
├─ Store in database
├─ Assign expiration time
└─ Link to contract
Notification Bar
├─ Display bell icon with unread count
├─ Show in dropdown when clicked
└─ Allow user interaction (mark read, delete)
```
### Deadline Notification Flow
```
Dashboard Page Load
checkDeadlineNotifications() called
Notification Service
├─ Query all user contracts with endDate
├─ Calculate days until expiration
├─ Check if 30, 15, or 7 days away
├─ Avoid duplicate notifications
└─ Create deadline notifications
Stored in database
Display in Notification Bar
```
## 💻 Usage Examples
### Example 1: Upload Contract
**User Action**: Click upload button, select file
**Flow**:
1. File uploaded to UploadThing
2. `saveContract()` server action triggered
3. Toast appears: "📄 Contract Uploaded"
4. Notification created and stored in database
5. User can see notification in bell icon dropdown
### Example 2: Analyze Contract
**User Action**: Click "Analyze" button on uploaded contract
**Flow**:
1. Status changes to PROCESSING with spinner
2. Toast appears: "⏳ Analyzing Contract"
3. AI analyzes the file
4. On Success:
- Toast: "✅ Contract Analyzed" with details
- Database notification created
- Contract details populate
5. On Error:
- Toast: "❌ Analysis Failed" with reason
- Database notification created with error
- Invalid contract modal shown (if applicable)
### Example 3: Delete Contract
**User Action**: Click delete, confirm in dialog
**Flow**:
1. Delete confirmation modal appears
2. On confirm:
- File deleted from UploadThing storage
- Contract deleted from database
- Toast: "🗑️ Contract Deleted"
- Notification created and stored
3. Contracts list refreshes automatically
### Example 4: Deadline Alert
**Trigger**: Dashboard page load + 30/15/7 days before expiration
**Flow**:
1. System queries all user contracts with endDate
2. Calculates days until each expiration
3. For contracts expiring in 30, 15, or 7 days:
- Creates deadline notification
- Avoids duplicates (max 1 per threshold per day)
4. Notifications appear in bell icon dropdown
5. Toast displayed if first time that day
## 🔔 Notification Types & Colors
| Type | Color | Icon | Use Case |
| -------- | --------- | ------------- | ------------------------------------ |
| SUCCESS | Green ✅ | CheckCircle2 | Contract uploaded, analyzed, deleted |
| ERROR | Red ❌ | AlertCircle | Upload failed, analysis failed |
| WARNING | Yellow ⚠️ | AlertTriangle | File taking long, low quality |
| INFO | Blue | Info | Processing started, general info |
| DEADLINE | Red 🕐 | Clock | Contract expiring soon |
## 🎛️ Notification Bar Features
### When Closed
- Shows bell icon
- Displays badge with unread count
- Pulses when unread notification arrives
### When Open
- Dropdown panel (w-96 max)
- Shows up to 15 most recent notifications
- Each notification shows:
- Type-specific icon and color
- Title and message
- Time (e.g., "2m ago")
- Contract link if available
- Unread indicator (red dot)
- Action buttons (✓ mark as read, 🗑️ delete)
- "Mark all as read" button
- Empty state if no notifications
### Auto-Refresh Behavior
- Refreshes every 30 seconds when dropdown is open
- Checks for deadline notifications daily (24 hours)
- Silent refresh (doesn't show loading if already open)
## 🔐 Security & Authorization
All operations include authentication and authorization:
1. **Clerk Authentication**: All actions verify user is logged in
2. **User Verification**: Notifications belong to authenticated user
3. **Contract Ownership**: Users only see their own contract notifications
4. **Server-Side Enforcement**: All operations run on server (no client manipulation)
5. **Database Constraints**: Foreign keys prevent orphaned records
## ⚙️ Configuration
### Modify Deadline Thresholds
Edit `lib/services/notification.service.ts`:
```typescript
if (daysUntilExpiration === 7) {
// Change 7 to any number
shouldNotify = true;
level = "URGENT";
}
```
### Change Default Expiration
Edit `lib/services/notification.service.ts`:
```typescript
const expiresAt = input.expiresIn
? new Date(Date.now() + input.expiresIn)
: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000); // Change 30 to any days
```
### Adjust Polling Interval
Edit `components/views/dashboard/notification-bar.tsx`:
```typescript
const pollInterval = setInterval(fetchNotifications, 30000); // 30 seconds, change to any ms
```
## 📱 Database Schema
### Notification Table
```sql
CREATE TABLE "Notification" (
id TEXT PRIMARY KEY,
userId TEXT NOT NULL, -- Link to User
contractId TEXT, -- Link to Contract (optional)
type NotificationType, -- SUCCESS, WARNING, ERROR, INFO, DEADLINE
title VARCHAR(255), -- e.g., "Contract Uploaded"
message TEXT, -- e.g., "insurance.pdf uploaded successfully"
icon VARCHAR(100), -- Lucide icon name for UI
actionType VARCHAR(100), -- e.g., "UPLOAD_SUCCESS", "RENEWAL_CRITICAL"
actionData JSONB, -- Additional metadata
read BOOLEAN DEFAULT false, -- Read status for badge
createdAt TIMESTAMP, -- When created
expiresAt TIMESTAMP, -- When notification expires
FOREIGN KEY (userId) REFERENCES "User"(id) ON DELETE CASCADE,
FOREIGN KEY (contractId) REFERENCES "Contract"(id) ON DELETE SET NULL
);
-- Indexes for fast queries
CREATE INDEX idx_userId ON "Notification"(userId);
CREATE INDEX idx_contractId ON "Notification"(contractId);
CREATE INDEX idx_type ON "Notification"(type);
CREATE INDEX idx_read ON "Notification"(read);
CREATE INDEX idx_createdAt ON "Notification"(createdAt DESC);
```
## 🧪 Testing the System
### Manual Tests
1. **Upload Notification**
- Go to /contacts
- Upload a contract
- Should see green toast: "📄 Contract Uploaded"
- Check notification bar - dot should appear
2. **Analysis Notification**
- Click "Analyze" on uploaded contract
- Should see loading toast
- After 5-10 seconds, see success or error toast
- Check notification bar for detailed message
3. **Delete Notification**
- Click delete on any contract
- Confirm in modal
- Should see toast: "🗑️ Contract Deleted"
4. **Deadline Notification**
- Create a contract with endDate in 10 days
- Go to dashboard
- System automatically checks and creates notification
- See 🟡 URGENT notification in bell icon
5. **Notification Bar Features**
- Click bell icon to open dropdown
- Click ✓ to mark individual as read
- Click 🗑️ to delete notification
- Click "Mark all as read" button
- Should auto-refresh when open
## 🐛 Troubleshooting
### Migration Fails
```bash
# Solution 1: Check database connection
echo $DATABASE_URL
# Solution 2: Reset migrations (dev only)
npx prisma migrate reset
# Solution 3: Manually deploy
npx prisma migrate deploy
```
### Notifications Not Showing
```bash
# Check 1: Verify notifications table exists
npx prisma db push
# Check 2: Check database connection in server
# Open browser DevTools → Network tab
# Look for failed API calls to notification endpoints
# Check 3: Verify Prisma client is generated
npx prisma generate
# Check 4: Rebuild project
npm run build
```
### Deadline Notifications Not Triggering
```
Check 1: Contract has endDate (not null)
Check 2: Contract status is "COMPLETED" (not UPLOADED/PROCESSING)
Check 3: Date is calculated correctly (midnight UTC)
Check 4: Manually trigger: await checkDeadlineNotifications()
```
### TypeScript Errors After Update
```bash
npm run build
npx prisma generate
npm run dev
```
## 📚 Code Examples
### Create Custom Notification in Server Action
```typescript
import { NotificationService } from "@/lib/services/notification.service";
const result = await NotificationService.create({
userId: user.id,
type: "SUCCESS",
title: "Custom Title",
message: "Custom message content",
contractId: contract.id,
actionType: "CUSTOM_ACTION",
expiresIn: 7 * 24 * 60 * 60 * 1000, // 7 days
});
```
### Use Toast in Client Component
```typescript
import { useNotifications } from "@/hooks/useNotifications";
import { toast } from "sonner";
export function MyComponent() {
const { notifySuccess, notifyError } = useNotifications();
const handleClick = async () => {
try {
await someOperation();
notifySuccess("Success!", "Operation completed");
} catch (error) {
notifyError("Error!", error.message);
}
};
}
```
### Check Notifications from Component
```typescript
import { getNotifications } from "@/lib/actions/notification.action";
export async function NotificationPreview() {
const result = await getNotifications(10);
if (result.success) {
console.log(result.data); // Array of notifications
}
}
```
## 🎓 Learning Resources
1. **Sonner Documentation**: https://sonner.emilkowal.ski/
2. **Prisma Documentation**: https://www.prisma.io/docs/
3. **Next.js Server Actions**: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
4. **Shadcn/ui Components**: https://ui.shadcn.com/
## 🚀 Future Enhancements
Potential features to add:
- [ ] Email notifications for deadline alerts
- [ ] Push notifications (Web/Mobile)
- [ ] Notification preferences (user can disable types)
- [ ] Snooze feature (temporarily hide notifications)
- [ ] Advanced filtering (by type, date, contract)
- [ ] Bulk operations (mark all, delete all)
- [ ] Export notification history (CSV)
- [ ] Recurring reminders if ignored
- [ ] Notification sounds/vibrations
- [ ] Smart digest (combine similar notifications)
## 📞 Support
For issues or questions:
1. Check error console (browser DevTools)
2. Review NOTIFICATION_SYSTEM_SETUP.md
3. Check notification-bar.tsx for UI implementation
4. See lib/services/notification.service.ts for core logic
5. Review contracts-list.tsx for toast integration examples
## ✅ Checklist - Setup Verification
After setup, verify:
- [ ] Database migration completed successfully
- [ ] Prisma client generated
- [ ] No TypeScript errors in build
- [ ] NotificationBar visible in dashboard sidebar
- [ ] Upload creates notification toast
- [ ] Analysis creates notification toast
- [ ] Delete creates notification toast
- [ ] Notification bar bell icon shows unread count
- [ ] Notification dropdown opens/closes smoothly
- [ ] Can mark notifications as read/delete
- [ ] Deadline notifications appear for contracts expiring in 30/15/7 days
- [ ] Auto-refresh works when dropdown is open
## 🎉 You're All Set!
The notification system is now fully integrated with:
- ✅ Sonner toast notifications for immediate feedback
- ✅ Persistent database notifications for history
- ✅ Beautiful notification bar UI with unread badge
- ✅ Automatic deadline detection and alerts
- ✅ Well-documented, production-ready code
Start uploading contracts and watch the notifications come to life!

View File

@@ -1,386 +0,0 @@
# 🔔 Notification System Setup Guide
## Overview
The notification system has been implemented to notify users about:
-**Action Notifications**: When users upload, analyze, or delete contracts
- 🕐 **Deadline Notifications**: When contracts are expiring (30, 15, 7 days)
- 📱 **Toast Notifications**: Immediate UI feedback for all actions
- 🔔 **Notification Center**: Persistent notification history accessible from the dashboard
## Database Migration
### Step 1: Update Your Database Schema
Run the following Prisma command to create the necessary database tables:
```bash
npx prisma migrate dev --name add_notifications
```
This will:
1. Create the `Notification` table
2. Create the `NotificationType` enum
3. Add the `notifications` relationship to the `User` model
4. Add the `notifications` relationship to the `Contract` model
### Step 2: Database Schema Overview
The migration adds:
```sql
-- Notification table with indexes
CREATE TABLE "Notification" (
id TEXT PRIMARY KEY,
userId TEXT NOT NULL,
contractId TEXT,
type "NotificationType" NOT NULL,
title VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
icon VARCHAR(100),
actionType VARCHAR(100),
actionData JSONB,
read BOOLEAN DEFAULT false,
createdAt TIMESTAMP DEFAULT now(),
expiresAt TIMESTAMP,
FOREIGN KEY (userId) REFERENCES "User"(id) ON DELETE CASCADE,
FOREIGN KEY (contractId) REFERENCES "Contract"(id) ON DELETE SET NULL
);
-- Notification Type Enum
CREATE TYPE "NotificationType" AS ENUM (
'SUCCESS',
'WARNING',
'ERROR',
'INFO',
'DEADLINE'
);
```
## Architecture Overview
### 1. **Notification Service** (`lib/services/notification.service.ts`)
Core service handling all notification operations:
- Create notifications
- Fetch unread/all notifications
- Mark as read
- Delete notifications
- Check for upcoming deadlines
- Cleanup expired notifications
**Key Methods:**
- `create(input)` - Create new notification
- `getUnread(userId, limit)` - Fetch unread notifications
- `getUnreadCount(userId)` - Get badge count
- `checkUpcomingDeadlines(userId)` - Scan contracts and create deadline notifications
- `cleanupExpired()` - Remove expired notifications (run periodically)
### 2. **Notification Actions** (`lib/actions/notification.action.ts`)
Server actions for client-side notification management:
- `getNotifications()` - Fetch unread notifications
- `getAllNotifications()` - Fetch notification history
- `getUnreadNotificationCount()` - Get badge count
- `markNotificationAsRead(id)` - Mark single as read
- `markAllNotificationsAsRead()` - Mark all as read
- `deleteNotification(id)` - Delete notification
- `checkDeadlineNotifications()` - Check and create deadline notifications
### 3. **Notification Component** (`components/views/dashboard/notification-bar.tsx`)
Beautiful notification UI dropdown with:
- Bell icon with unread count badge
- Notification list with type-specific icons and colors
- Action buttons (mark as read, delete)
- Time formatting (e.g., "2m ago")
- Empty state
- Auto-refresh every 30 seconds when open
- Daily deadline check
### 4. **useNotifications Hook** (`hooks/useNotifications.ts`)
Custom React hook wrapping Sonner toast + persistent notifications:
- `notifySuccess()` - Green success toast + persistent notification
- `notifyError()` - Red error toast + persistent notification
- `notifyWarning()` - Yellow warning toast + persistent notification
- `notifyInfo()` - Blue info toast + persistent notification
- `notifyDeadline()` - Red deadline toast + persistent notification
## Integration Points
### 1. **Contract Actions** (`lib/actions/contract.action.ts`)
Updated to create notifications on:
-**Upload**: "Contract uploaded successfully"
-**Analysis**: "Contract analyzed successfully" or error message
-**Delete**: "Contract deleted successfully"
-**Ask Question**: Error notification if Q&A fails
### 2. **Dashboard** (`app/(dashboard)/dashboard/page.tsx`)
- Calls `checkDeadlineNotifications()` on page load
- Checks for contracts expiring in 30, 15, 7 days
- Creates notifications automatically
### 3. **Navigation** (`components/views/dashboard/navigation.tsx`)
- Added `NotificationBar` component to sidebar
- Positioned next to theme toggle in account section
- Accessible from all dashboard pages
## Usage Examples
### Creating a Notification in Server Actions
```typescript
import { NotificationService } from "@/lib/services/notification.service";
// In a server action
const user = await ContractService.getUserByClerkId(clerkId);
await NotificationService.create({
userId: user.id,
type: "SUCCESS",
title: "Contract Uploaded",
message: 'Your file "insurance.pdf" is ready for analysis',
contractId: contractId,
actionType: "UPLOAD_SUCCESS",
icon: "FileCheck",
expiresIn: 7 * 24 * 60 * 60 * 1000, // 7 days
});
```
### Using Toast Notifications in Client Components
```typescript
import { useNotifications } from "@/hooks/useNotifications";
export function MyComponent() {
const { notifySuccess, notifyError, notifyDeadline } = useNotifications();
const handleUpload = async () => {
try {
await uploadFile();
notifySuccess("Upload Complete", "Your file has been uploaded");
} catch (error) {
notifyError("Upload Failed", error.message);
}
};
const handleDeadline = () => {
notifyDeadline({
title: "🔴 Contract Expiring Soon",
message: "Insurance Auto from ACME expires in 7 days",
contractId: "contract123",
actionType: "RENEWAL_URGENT",
});
};
return (
<>
<button onClick={handleUpload}>Upload</button>
<button onClick={handleDeadline}>Test Deadline</button>
</>
);
}
```
## Notification Types
### SUCCESS (Green - ✅)
Used for:
- Contract uploaded
- Analysis completed
- Contract deleted
- Settings saved
### ERROR (Red - ❌)
Used for:
- Upload failed
- Analysis failed
- Network errors
- Invalid contract
### WARNING (Yellow - ⚠️)
Used for:
- File analysis slow
- Low quality extraction
- Missing permissions
### INFO (Blue - )
Used for:
- Analysis started
- Processing updates
- General information
### DEADLINE (Red - 🕐)
Used for:
- Contract expiring in 30 days (CRITICAL 🔴)
- Contract expiring in 15 days (WARNING 🟠)
- Contract expiring in 7 days (URGENT 🟡)
## Scheduled Tasks
### Daily Deadline Check
The system checks for upcoming deadlines:
- **When**: Daily at any time (triggered on dashboard load)
- **What**: Scans all user contracts with endDate
- **Actions**:
- Creates CRITICAL notification for 30-day threshold
- Creates WARNING notification for 15-day threshold
- Creates URGENT notification for 7-day threshold
- Avoids duplicate notifications (max 1 per threshold per day)
### Running Deadline Checks Manually
```typescript
import { checkDeadlineNotifications } from "@/lib/actions/notification.action";
// Client-side
const result = await checkDeadlineNotifications();
console.log(`Created ${result.data.count} deadline notifications`);
```
### Cleanup Task (Recommended)
For production, set up a cron job to clean expired notifications:
```typescript
import { NotificationService } from "@/lib/services/notification.service";
// Example: Vercel Cron (serverless function every day at midnight)
export async function GET(request: Request) {
const authHeader = request.headers.get("authorization");
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response("Unauthorized", { status: 401 });
}
const result = await NotificationService.cleanupExpired();
return Response.json(result);
}
// Route: api/cron/cleanup-notifications
// Set Cron Job: 0 0 * * * (daily at midnight)
```
## Configurable Parameters
### Default Notification Expiration
```typescript
// In NotificationService.create()
const expiresAt = input.expiresIn
? new Date(Date.now() + input.expiresIn)
: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000); // 30 days default
```
### Deadline Thresholds
Located in `NotificationService.checkUpcomingDeadlines()`:
- 30 days: CRITICAL level
- 15 days: WARNING level
- 7 days: URGENT level
To modify, edit these lines in `notification.service.ts`:
```typescript
if (daysUntilExpiration === 7) {
/* ... */
} else if (daysUntilExpiration === 15) {
/* ... */
} else if (daysUntilExpiration === 30) {
/* ... */
}
```
### Notification Bar Polling
```typescript
// In notification-bar.tsx
const pollInterval = setInterval(fetchNotifications, 30000); // 30 seconds
const dailyCheckInterval = setInterval(
() => {
checkDeadlineNotifications();
},
24 * 60 * 60 * 1000,
); // 24 hours
```
## Security & Authorization
All notification operations include authorization checks:
1. **User Verification**: Each action verifies the user owns the notification
2. **Contract Ownership**: Deadline checks only process user's contracts
3. **Input Validation**: Notification content isn't sanitized (all text)
4. **Server-Side Enforcement**: All operations run server-side (no client-side manipulation)
## Troubleshooting
### Migrations Don't Apply
```bash
# Reset migrations (for development only)
npx prisma migrate reset
# Or manually apply pending migrations
npx prisma migrate deploy
```
### Notifications Not Showing
1. Check database connection
2. Verify user exists in User table
3. Check browser console for errors
4. Verify `checkDeadlineNotifications` was called
### Deadline Notifications Not Triggering
1. Ensure contract has `endDate` set
2. Verify contract status is "COMPLETED"
3. Check date calculation (today at midnight)
4. Run manual check: `await checkDeadlineNotifications()`
## Future Enhancements
Potential improvements:
1. **Email Notifications**: Send deadline alerts via email
2. **Batch Operations**: Bulk mark/delete notifications
3. **Notification Preferences**: Let users disable certain types
4. **Snooze Feature**: Temporarily hide notifications
5. **Advanced Filtering**: Filter by type, date range, contract
6. **Export History**: Download notification log as CSV
7. **Push Notifications**: Web/mobile push for critical alerts
8. **Recurring Reminders**: Repeat deadline notifications if ignored
## Support
For issues or questions:
1. Check the notification service comments for implementation details
2. Review contracts-list.tsx for toast integration examples
3. Check notification-bar.tsx for UI implementation
4. See hooks/useNotifications.ts for hook usage

View File

@@ -1,208 +0,0 @@
# Project Architecture & Technology Stack
**Project:** LexiChain (BFSI Contract Intelligence Platform)
**Date:** March 8, 2026
**Scope:** Rationale for choosing Next.js, current stack snapshot, and end-to-end communication architecture.
## 1) Why We Chose Next.js
We selected **Next.js** because it aligns with the exact technical and product needs of this project:
1. **Full-stack in one framework**
The project combines UI, backend logic, and API endpoints in a single codebase (`app` routes, server actions, route handlers). This reduces context switching and speeds up delivery.
2. **App Router structure for product domains**
Route groups like `(auth)` and `(dashboard)` map directly to business areas, making navigation and ownership clear.
3. **Server Actions for secure business operations**
Operations such as saving contracts, analysis triggers, and fetching statistics are executed server-side (`"use server"`), which keeps privileged logic off the client.
4. **Built-in route handlers for integrations**
Integrations such as Clerk webhooks and UploadThing endpoints are implemented natively in `app/api/*`, with no separate backend server required.
5. **Strong authentication integration**
Clerk works naturally with Next.js server functions (`auth()`), middleware/proxy route protection, and auth UI pages.
6. **Performance and UX benefits**
Next.js supports hybrid rendering and optimized routing while allowing rich client interactivity where needed (dashboard, charts, upload flows).
7. **Excellent TypeScript compatibility**
The project uses strict TypeScript with shared models and service layers, improving reliability in a data-sensitive BFSI context.
---
## 2) Current Stack (As Implemented)
### Core Platform
- **Next.js:** `16.1.6`
- **React:** `19.2.3`
- **TypeScript:** `5.x` (strict mode)
- **Node/NPM scripts:** standard `dev`, `build`, `start`, `lint`
### UI & Frontend
- **Tailwind CSS** + `tailwindcss-animate`
- **shadcn/ui** (New York style) built on **Radix UI** primitives
- **Lucide React** icons
- **Motion** (`motion/react`) for animations
- **Recharts** for analytics visualizations
- **Sonner** for toast notifications
- **next-themes** for dark/light mode
### Authentication & Access Control
- **Clerk** (`@clerk/nextjs`, `@clerk/themes`)
- Route protection through `proxy.ts` using Clerk middleware
- Auth flows with Clerk `SignIn` and `SignUp` pages
- Webhook verification using **Svix** for secure user lifecycle sync
### Data Layer
- **PostgreSQL** via **Prisma ORM** (`@prisma/client`, `prisma`)
- Main entities: `User` and `Contract`
- Enum-based domain modeling (`ContractType`, `ContractStatus`)
### File Ingestion & Storage
- **UploadThing** (`uploadthing`, `@uploadthing/react`)
- Controlled file constraints and authenticated upload middleware
- Upload completion callback integrated with contract persistence
### AI & Contract Intelligence
- **Google Generative AI** SDK (`@google/generative-ai`)
- Gemini model (`gemini-2.5-flash`) for:
- contract extraction,
- structured summary generation,
- key-point generation,
- contract Q&A.
### Validation / Forms / Utility
- **react-hook-form**, **zod**, `@hookform/resolvers`
- Utility stack: `clsx`, `class-variance-authority`, `tailwind-merge`, etc.
---
## 3) Architecture Overview
The app follows a **layered Next.js architecture** with clear responsibilities:
1. **Presentation Layer (Client Components / Views)**
- Route UI in `app/*`
- Reusable view modules in `components/views/*`
- Design-system components in `components/ui/*`
2. **Application Layer (Server Actions)**
- `lib/actions/*`
- Entry point for authenticated server-side operations initiated by the UI
3. **Domain/Service Layer**
- `lib/services/*`
- Encapsulates business logic (contracts, AI analysis, stats, storage helpers)
4. **Persistence Layer**
- `lib/db/prisma.ts` + `prisma/schema.prisma`
- Database operations and schema modeling
5. **Integration Layer (External Systems)**
- Route handlers in `app/api/*` (UploadThing, Clerk webhooks)
- External providers: Clerk, UploadThing, Gemini API
### High-Level Component Map
- **Public Marketing Experience:** `app/page.tsx` + `components/views/Home/*`
- **Authenticated Workspace:** `app/(dashboard)/*` + dashboard navigation/layout
- **Document Operations:** upload form, contract list, AI actions, analytics charts
---
## 4) How Each Part Communicates
### A. Authentication and Access
1. User requests a protected page.
2. `proxy.ts` (Clerk middleware) checks route rules and enforces authentication.
3. Inside server layouts/actions, `auth()` verifies user identity again for operation-level security.
4. Clerk webhook events (`app/api/webhooks/clerk/route.ts`) synchronize user records into PostgreSQL.
**Result:** route-level and operation-level protection, plus identity consistency between Clerk and local DB.
### B. Contract Upload and Persistence
1. User uploads a file from `ContractUploadForm` (client).
2. Upload is sent to UploadThing endpoint (`/api/uploadthing`).
3. UploadThing middleware validates authenticated user.
4. On completion, client calls server action `saveContract`.
5. Server action delegates to `ContractService.create`.
6. Service resolves local user via `clerkId` and inserts `Contract` record with status lifecycle.
7. Paths are revalidated so UI refreshes with latest data.
**Result:** secure file ingestion + persistent contract metadata in one flow.
### C. Contract Analysis (AI Enrichment)
1. User clicks “Analyze” in contracts list.
2. Client triggers `analyzeContractAction` (server action).
3. Action validates auth, fetches contract, sets status to `PROCESSING`.
4. `AIService` downloads file URL and sends content to Gemini.
5. AI JSON output is validated and normalized.
6. `ContractService.updateWithAIResults` saves extracted fields (`summary`, `keyPoints`, type, dates, premium, etc.) and marks status `COMPLETED`.
7. Failures set status to `FAILED`.
**Result:** contract moves from raw upload to structured intelligence record.
### D. Analytics and Dashboard Data
1. Dashboard UI calls `getStatsAction`.
2. Action validates user and calls `stats.service`.
3. Service runs Prisma aggregations/groupings.
4. Data is returned as dashboard KPIs + chart-ready payloads.
5. Recharts renders trend/type/status analytics on the client.
**Result:** real-time operational visibility from server-computed metrics.
### E. Contract Q&A
1. User asks question in contract context.
2. Client calls `askContractQuestionAction`.
3. Server action fetches contract + analysis context.
4. `AIService.askAboutContract` sends prompt + metadata/extracted content to Gemini.
5. Sanitized answer returns to chat UI.
**Result:** contextual AI assistant grounded in analyzed contract data.
---
## 5) Runtime Communication Diagram
```mermaid
flowchart TD
U[User Browser] --> UI[Next.js App Router UI]
UI -->|Server Actions| SA[lib/actions]
SA --> SVC[lib/services]
SVC --> DB[(PostgreSQL via Prisma)]
UI -->|Upload| UT[UploadThing]
UT -->|Upload Callback Data| SA
SVC -->|Analyze / Q&A| AI[Google Gemini API]
Clerk[Clerk Auth] -->|Session/Auth| UI
Clerk -->|Webhooks via Svix| WH[app/api/webhooks/clerk]
WH --> DB
Proxy[proxy.ts Clerk Middleware] --> UI
```
---
## 6) Architecture Characteristics
### Strengths
- **Single cohesive full-stack codebase** with clear file-system boundaries
- **Fast feature delivery** using App Router + server actions
- **Good security baseline** (middleware + server auth checks + webhook verification)
- **Strong type safety** across UI, actions, services, and data models
- **Integration-ready design** for AI/document workflows
### Current Maturity Notes
- AI execution is implemented server-side and can be triggered from user workflow.
- Existing comments already indicate a future path for queue-based background orchestration in production-scale scenarios.
---
## 7) Conclusion
Next.js is the right foundation for this BFSI platform because it enables secure, full-stack product development in one architecture: rich UI, authenticated server operations, API integrations, and data persistence.
The current stack is modern, production-oriented, and well-aligned with the project goals: **contract ingestion, AI enrichment, analytics visibility, and secure user-scoped access**.

48
docs/README.md Normal file
View File

@@ -0,0 +1,48 @@
# LexiChain — Documentation
> **Version:** 1.0.0 · **Stack:** Next.js 16 · React 19 · TypeScript · PostgreSQL · Solidity
Welcome to the LexiChain documentation. This folder contains everything needed to understand, develop, and deploy the platform.
---
## Table of Contents
| Document | Description |
|----------|-------------|
| [01 — Project Overview](./01-project-overview.md) | What LexiChain is, its features, architecture, and user flows |
| [02 — Services Reference](./02-services.md) | Every internal service: AI, Blockchain, Email, Notifications, RAG, etc. |
| [03 — Database Schema](./03-database-schema.md) | Full Prisma schema, models, relationships, and index rationale |
| [04 — API Reference](./04-api-reference.md) | All Next.js route handlers and key server actions |
| [05 — Smart Contract](./05-smart-contract.md) | DocumentRegistry.sol: design, functions, ABI, deployment |
| [06 — Deployment Guide](./06-deployment-openstack.md) | Step-by-step OpenStack VPS deployment with Docker, Nginx, and Sepolia |
---
## Quick Start (Development)
```bash
# 1. Install dependencies (auto-generates Prisma client via postinstall)
npm install
# 2. Copy and fill environment variables
cp .env.example .env
# 3. Run database migrations
npx prisma migrate dev
# 4. Start development server (includes local Hardhat blockchain)
npm run dev
```
The dev server starts at **http://localhost:3000**.
The local Hardhat blockchain starts at **http://localhost:8545**.
---
## Quick Links
- [Environment Variables Reference](./.env.example)
- [Prisma Schema](../prisma/schema.prisma)
- [Smart Contract Source](../blockchain/contracts/DocumentRegistry.sol)
- [Deployment Guide](./06-deployment-openstack.md)

View File

@@ -1,45 +0,0 @@
# API & Routing Endpoints
## API Endpoints
### 1. Clerk Webhook
- **Path:** `/api/webhooks/clerk`
- **Method:** `POST`
- **Purpose:** Handles Clerk webhook events (authentication, user sync, etc.)
### 2. File Upload (UploadThing)
- **Path:** `/api/uploadthing`
- **Methods:** `GET`, `POST`
- **Purpose:** Handles file uploads (contracts, images) with authentication
---
## Protected App Routes (Require Login)
Defined in middleware ([proxy.ts](../proxy.ts)):
- `/dashboard` and all sub-pages
- `/contracts` and all sub-pages
- `/chat` and all sub-pages
- `/claims` and all sub-pages
- `/blockchain` and all sub-pages
- `/settings` and all sub-pages
- `/api/contracts` and all sub-pages
- `/api/chat`
- `/api/claims`
---
## Feature API Actions (Server Actions)
These are called from the frontend, not as REST endpoints:
- `/features/contracts/api/contract.action.ts` (contract CRUD, AI analysis)
- `/features/analytics/api/stats.action.ts` (dashboard stats)
- `/features/notifications/api/notification.action.ts` (notifications)
- `/features/auth/api/user.action.ts` (user sync)
---
**Note:**
- All `/dashboard`, `/contracts`, `/chat`, `/claims`, `/blockchain`, `/settings` routes are protected and require authentication.
- API endpoints under `/api/` may also be protected by middleware.
- For more details, see the middleware configuration in [proxy.ts](../proxy.ts).

View File

@@ -1,33 +0,0 @@
# FSD & SOLID Refactoring Report
## 1. What I Did (Project-Wide Structural Migration)
1. **Abolished Global "Bucket" Folders:** I completely migrated all files out of generic structural folders (`/components/views` and `/lib/actions`).
2. **Designed a Domain-Driven Architecture (FSD):** Created an entire structural blueprint separating components by their core business area into a new `/features/` directory architecture.
3. **Decentralized Backend Logistics:** I took top-level database `server_actions` (`contract.action.ts`, `notification.action.ts`, etc.) and relocated them entirely under the purview of their specific domain (e.g., `/features/contracts/api/contract.action.ts`).
4. **Abstracted Shared Layouts:** I isolated global UI architecture (Sidebars & Top Navigations) into a dedicated generic `/components/layout/` directory.
5. **Applied the Single Responsibility Principle:** Eliminated massive chunks of code from the "God File" (`contracts-list.tsx`). Abstracted over 300+ lines of monolithic JSX code defining the complicated **Chatbot Assessment Modal** and **Field Proof Verification Modal**.
6. **Encapsulated Complex State:** Stripped out isolated React states (`question`, `isAsking`, `messages`) from `contracts-list.tsx`'s scope into `ContractChatModal`.
## 2. Why I Did It
The project was structured by technological type (`views`, `actions`, `pages`) instead of business domains (Contracts, Notifications, Analytics).
**The consequence of tech-centric folders:**
- When a developer wanted to change how a single chart works, they had to hop between `/app/dashboard/page.tsx` (Route), `/components/views/dashboard/charts.tsx` (UI), and `/lib/actions/stats.action.ts` (Database logic).
- Changing `contracts-list.tsx` was incredibly dangerous; it had ballooned to 2,000 lines because all database actions, list management, and distinct heavy UI Modals were bundled recursively. This caused excessive Time To Interactive (TTI) Virtual DOM lag, where opening the chatbot inside the list triggered state updates scaling to all 100 rendered table rows repeatedly.
## 3. The Developer Benefits
### 1. Immense Performance Gains (Virtual DOM Efficiency)
Because internal UI state (like typing inside the chat) is isolated strictly to the new `ContractChatModal` component wrapper, keystrokes no longer force the virtual DOM to evaluate data bound to the contracts table. TTI is radically lower.
### 2. High Cohesion & Loose Coupling
Under the new `/features/` domains, every business unit is entirely self-sufficient.
If an engineer needs to overhaul the Analytics feature to use a different database provider, they perform 100% of their coding inside `/features/analytics`. They will never accidentally break routing on `/features/contracts`, because they physically aren't interacting with shared central files.
### 3. Maximum Reusability (Open/Closed Principle)
Since Modals and Actions are now completely unchained from specific parent hierarchies, you can reuse the complex UI flows anywhere natively. If a Mobile App route needs access to `Contract Status charts`, it imports them from `/features/analytics/components/charts.tsx` with zero duplication.
### 4. Zero Merge Conflicts
Multiple developers can reliably build completely different modules simultaneously without fighting over massive shared state stores in generic global files.

View File

@@ -1,675 +0,0 @@
# 🔗 Blockchain Module — Complete Documentation
> **LexiChain BFSI Platform — Chapter: Blockchain Integration**
>
> This document explains everything about the blockchain module:
> what it does, how it works, how the code is organized, and how to run it.
> Written for beginners with no prior blockchain knowledge.
---
## Table of Contents
1. [What is Blockchain and Why Do We Need It?](#1-what-is-blockchain-and-why-do-we-need-it)
2. [What Does Our Blockchain Module Do?](#2-what-does-our-blockchain-module-do)
3. [Architecture Overview](#3-architecture-overview)
4. [Smart Contract: DocumentRegistry.sol](#4-smart-contract-documentregistrysol)
5. [Server-Side Integration: BlockchainService](#5-server-side-integration-blockchainservice)
6. [Database Schema: Storing Proof Data](#6-database-schema-storing-proof-data)
7. [Server Actions: The API Layer](#7-server-actions-the-api-layer)
8. [Frontend: Blockchain Explorer Page](#8-frontend-blockchain-explorer-page)
9. [Complete Data Flow](#9-complete-data-flow)
10. [How to Run Locally](#10-how-to-run-locally)
11. [Deploying to Sepolia Testnet](#11-deploying-to-sepolia-testnet)
12. [Technology Choices & Rationale](#12-technology-choices--rationale)
13. [File Reference](#13-file-reference)
---
## 1. What is Blockchain and Why Do We Need It?
### The Problem (in simple terms)
When a client sends an insurance claim or uploads a contract, they need **proof** that they submitted it on a specific date. Without proof:
- The insurance company could claim "we never received it"
- Deadlines could be disputed
- There's no transparency
### The Solution: Blockchain as a Notary
A **blockchain** is like a public, tamper-proof notebook. Once you write something in it, **nobody can erase or modify it** — not even the person who wrote it.
We use the blockchain as a **digital notary**:
1. We take the uploaded contract PDF
2. We create a unique **fingerprint** (hash) of that file
3. We write that fingerprint into the blockchain with a timestamp
4. Now there's permanent, verifiable proof that this exact document existed at this exact time
> **Key insight**: We don't store the actual document on the blockchain (that would be expensive). We only store its **fingerprint** (64 characters). If the document ever changes, even by one byte, the fingerprint would be completely different — proving tampering.
### What is a Smart Contract?
A **smart contract** is a program that runs on the blockchain. Think of it as a vending machine:
- You put in a coin (send a transaction)
- The machine executes its programmed logic
- The result is permanent and visible to everyone
Our smart contract (`DocumentRegistry.sol`) has two main functions:
- **Register**: Store a document fingerprint with a timestamp
- **Verify**: Check if a fingerprint exists and when it was stored
---
## 2. What Does Our Blockchain Module Do?
### Features Implemented
| Feature | Description |
| ------------------------- | --------------------------------------------------------------------------- |
| **Auto-Registration** | After AI analyzes a contract, its hash is automatically registered on-chain |
| **Manual Registration** | Users can register unregistered contracts via the Blockchain Explorer |
| **Document Verification** | Paste any document hash to check if it exists on-chain |
| **Transaction Explorer** | View all blockchain transactions with details |
| **Network Stats** | Live stats: verified documents, latest block, network status |
| **Proof Badges** | Contract list shows which contracts are blockchain-verified |
### What Happens When a User Uploads a Contract?
```
User uploads PDF → AI analyzes it → Blockchain registers the hash
```
The entire flow is automatic. The user doesn't need:
- ❌ MetaMask or any wallet
- ❌ Cryptocurrency knowledge
- ❌ To pay anything
Everything runs **server-side** with a platform wallet.
---
## 3. Architecture Overview
### High-Level Flow
```mermaid
flowchart TD
subgraph "User Browser"
UI[Next.js Frontend]
end
subgraph "Next.js Server"
SA[Server Actions<br/>blockchain.action.ts]
BS[BlockchainService<br/>blockchain.service.ts]
CA[Contract Action<br/>contract.action.ts]
end
subgraph "Data Layer"
DB[(PostgreSQL<br/>Prisma ORM)]
UT[UploadThing<br/>File Storage]
end
subgraph "Blockchain Network"
SC[Smart Contract<br/>DocumentRegistry.sol]
HN[Hardhat Local Node<br/>or Sepolia Testnet]
end
UI -->|"1. Upload contract"| CA
CA -->|"2. AI analyzes"| CA
CA -->|"3. Hash + register"| BS
BS -->|"4. Download PDF"| UT
BS -->|"5. SHA-256 hash"| BS
BS -->|"6. Send transaction"| SC
SC -->|"7. Store on-chain"| HN
BS -->|"8. Save proof"| DB
UI -->|"View /blockchain"| SA
SA -->|"Read transactions"| DB
SA -->|"Verify on-chain"| SC
```
### Network Modes
| Mode | When | URL | Cost |
| ----------- | ----------------- | ----------------------- | -------------- |
| **Hardhat** | Development | `http://127.0.0.1:8545` | Free (local) |
| **Sepolia** | Demo/Presentation | Via Alchemy/Infura RPC | Free (testnet) |
The mode is controlled by a single env variable: `BLOCKCHAIN_NETWORK`.
---
## 4. Smart Contract: DocumentRegistry.sol
**Location**: `blockchain/contracts/DocumentRegistry.sol`
### What It Does
The smart contract is written in **Solidity** (the programming language for Ethereum). It stores document fingerprints on the blockchain.
### Data Structures
```solidity
struct DocumentRecord {
uint256 timestamp; // When the document was registered
address depositor; // Who registered it (our server wallet)
string fileName; // Original file name
bool exists; // Whether this record is valid
}
```
### Core Functions
```mermaid
flowchart LR
subgraph "Write Operations (costs gas)"
R[registerDocument<br/>bytes32 hash, string fileName]
end
subgraph "Read Operations (free)"
V[verifyDocument<br/>bytes32 hash]
T[getTimestamp<br/>bytes32 hash]
D[getDocumentsByDepositor<br/>address]
end
R --> |"Stores hash + timestamp"| BC[(Blockchain State)]
BC --> V
BC --> T
BC --> D
```
#### `registerDocument(bytes32 _docHash)`
- **Purpose**: Store a document hash on-chain
- **Access**: Only the contract owner (our server wallet)
- **Guard**: Prevents duplicate registration (same hash can't be registered twice)
- **Event**: Emits `DocumentRegistered` for off-chain indexing
#### `verifyDocument(bytes32 _docHash)`
- **Purpose**: Check if a hash exists and get its details
- **Cost**: Free (read-only, no gas)
- **Returns**: `(exists, timestamp, depositor)`
### How the Hash Works
```mermaid
flowchart LR
PDF[Contract PDF<br/>2.4 MB] -->|SHA-256| HASH[0x7f83b165...4e2a<br/>32 bytes]
HASH -->|Store on-chain| BC[Blockchain]
PDF2[Same PDF] -->|SHA-256| HASH2[0x7f83b165...4e2a<br/>Identical hash!]
PDF3[Modified PDF<br/>1 byte changed] -->|SHA-256| HASH3[0xa1b2c3d4...9z8y<br/>Completely different!]
```
> **SHA-256** is a one-way function. You can't reconstruct the document from the hash, but the same document always produces the same hash.
### Testing
14 tests cover all functionality:
```
✓ should set the deployer as owner
✓ should start with zero documents
✓ should register a document and emit event
✓ should store correct timestamp
✓ should increment totalDocuments counter
✓ should prevent duplicate registration
✓ should allow different users to register different documents
✓ should verify a registered document
✓ should return false for unregistered document
✓ should track all documents by a depositor
✓ should return correct document count
✓ should transfer ownership
✓ should prevent non-owner from transferring ownership
✓ should prevent transfer to zero address
```
---
## 5. Server-Side Integration: BlockchainService
**Location**: `lib/services/blockchain.service.ts`
### Why Server-Side?
Most blockchain dApps require users to install MetaMask and sign transactions. This is bad UX for a BFSI enterprise platform because:
- Users shouldn't need crypto knowledge
- The platform manages documents, not individual users
- Server-side signing is more reliable
Instead, we use a **server wallet**: a private key stored in `.env` that the server uses to sign transactions automatically.
### How It Connects to the Blockchain
```mermaid
sequenceDiagram
participant S as Server Action
participant BS as BlockchainService
participant P as ethers.js Provider
participant W as ethers.js Wallet
participant C as Smart Contract
S->>BS: hashAndRegister(fileUrl, fileName)
BS->>BS: Download PDF from UploadThing
BS->>BS: Compute SHA-256 hash
BS->>P: Connect to RPC (Hardhat/Sepolia)
BS->>W: Sign transaction with private key
W->>C: registerDocument(hash)
C-->>W: Transaction receipt
W-->>BS: txHash, blockNumber, blockTimestamp
BS-->>S: BlockchainProof object
```
### Key Methods
| Method | Purpose | Gas Cost |
| ------------------------------------ | ------------------------------- | ---------------- |
| `hashDocument(fileUrl)` | Download file + compute SHA-256 | None (off-chain) |
| `registerOnChain(hash, fileName)` | Send tx to smart contract | ~50,000 gas |
| `verifyOnChain(hash)` | Read-only check | Free |
| `hashAndRegister(fileUrl, fileName)` | Combined: hash + register | ~50,000 gas |
| `getNetworkStats()` | Get block number, total docs | Free |
| `isConfigured()` | Check if env vars are set | None |
### Graceful Degradation
If blockchain is not configured (env vars missing), the service returns `isConfigured() = false` and all blockchain features are silently disabled. The rest of the app works normally.
---
## 6. Database Schema: Storing Proof Data
**Location**: `prisma/schema.prisma`
### Contract Model (updated fields)
```prisma
model Contract {
// ... existing fields ...
// Blockchain proof-of-deposit
documentHash String? // SHA-256 hash
txHash String? // Ethereum transaction hash
blockNumber Int? // Block number
blockTimestamp DateTime? // Block timestamp
blockchainNetwork String? // 'hardhat' | 'sepolia'
contractAddress String? // Smart contract address
}
```
### BlockchainTransaction Model (new)
```prisma
model BlockchainTransaction {
id String @id
userId String // Who triggered the registration
contractId String // Which contract was registered
documentHash String // SHA-256 hash
txHash String @unique // Ethereum tx hash
blockNumber Int // Block where tx was mined
blockTimestamp DateTime // Proof timestamp
network String // 'hardhat' | 'sepolia'
contractAddress String // Smart contract address
status String // PENDING, CONFIRMED, FAILED
createdAt DateTime
}
```
### Why Two Places?
- **Contract fields**: Quick access to proof data when displaying a single contract
- **BlockchainTransaction**: Separate table for the explorer page, supports querying all transactions for a user independently of contracts
---
## 7. Server Actions: The API Layer
**Location**: `features/blockchain/api/blockchain.action.ts`
### Actions Available
```mermaid
flowchart TD
subgraph "Blockchain Server Actions"
A1[registerContractOnBlockchain<br/>contractId → proof]
A2[verifyContractOnBlockchain<br/>contractId → verification]
A3[verifyDocumentHashOnBlockchain<br/>hash → exists/timestamp]
A4[getBlockchainTransactions<br/>→ transaction list]
A5[getBlockchainStats<br/>→ network stats]
end
subgraph "Called by"
UI1[Blockchain Explorer Page]
UI2[Contract List - Register Button]
UI3[Analysis Flow - Auto]
end
UI1 --> A3
UI1 --> A4
UI1 --> A5
UI2 --> A1
UI3 --> A1
```
### Auto-Registration Flow
In `features/contracts/api/contract.action.ts`, after AI analysis completes:
```typescript
// After AI analysis + RAG chunking...
try {
if (BlockchainService.isConfigured()) {
const proof = await BlockchainService.hashAndRegister(
contract.fileUrl,
contract.fileName
);
// Save proof to Contract + BlockchainTransaction
await prisma.contract.update({...});
await prisma.blockchainTransaction.create({...});
}
} catch (blockchainError) {
// Non-blocking: blockchain failure doesn't break analysis
console.warn("Blockchain registration skipped:", blockchainError);
}
```
> **Critical design decision**: Blockchain registration is wrapped in a try/catch. If the Hardhat node is down or there's a network issue, the AI analysis still completes successfully. Blockchain is an enhancement, not a dependency.
---
## 8. Frontend: Blockchain Explorer Page
**Location**: `app/(dashboard)/blockchain/page.tsx`
### Page Layout
```
┌─────────────────────────────────────────────────┐
│ 🔗 Blockchain Explorer [Refresh] │
├────────────┬────────────┬──────────┬────────────┤
│ Verified │ Latest │ Network │ Wallet │
│ Documents │ Block │ Status │ Address │
│ 12 │ #847 │ ● Live │ 0xf39F... │
├────────────┴────────────┴──────────┴────────────┤
│ ⚠️ 3 contracts not yet on blockchain │
│ ┌─ Insurance Auto [Register] ─┐ │
│ └─ Home Loan Policy [Register] ─┘ │
├──────────────────────┬──────────────────────────┤
│ Transaction History │ Verify Document │
│ ────────────────── │ ────────────────── │
│ ✓ Insurance Auto │ [Hash input field] │
│ Tx: 0x7f83... │ [Verify On-Chain] │
│ Block: #845 │ │
│ Time: Apr 19 │ ✓ Document Verified │
│ ────────────────── │ Timestamp: ... │
│ ✓ Home Loan │ Depositor: 0xf39F.. │
│ Tx: 0xa1b2... │ │
└──────────────────────┴──────────────────────────┘
```
### Navigation
The Blockchain page is accessible from the sidebar navigation at `/blockchain`, alongside Analytics and Contracts.
---
## 9. Complete Data Flow
### End-to-End: Upload → Proof
```mermaid
sequenceDiagram
actor U as User
participant UI as Browser
participant SA as Server Action
participant AI as AI Service
participant BS as BlockchainService
participant ES as EmailService
participant SC as Smart Contract
participant DB as PostgreSQL
U->>UI: Upload contract PDF
UI->>SA: saveContract(fileData)
SA->>DB: Create contract (UPLOADED)
SA->>SA: analyzeContractAction(id)
SA->>AI: Analyze document (Gemini)
AI-->>SA: AI results (title, dates, etc.)
SA->>DB: Update contract (COMPLETED)
Note over SA,SC: Blockchain Registration (automatic)
SA->>BS: hashAndRegister(fileUrl, fileName)
BS->>BS: Download PDF
BS->>BS: SHA-256 hash → 0x7f83b1...
BS->>SC: registerDocument(hash)
SC->>SC: Store hash + timestamp
SC-->>BS: Transaction receipt
BS-->>SA: BlockchainProof
SA->>DB: Save txHash, blockNumber, etc.
SA->>DB: Create BlockchainTransaction
SA->>ES: Send analysis + blockchain proof email
ES-->>U: Email received (or Ethereal preview in dev)
SA-->>UI: Success!
Note over U,UI: User visits /blockchain
U->>UI: Click "Blockchain" in sidebar
UI->>SA: getBlockchainTransactions()
SA->>DB: Fetch all transactions
DB-->>SA: Transaction list
SA-->>UI: Display in explorer
Note over U,UI: User verifies a document
U->>UI: Paste document hash
UI->>SA: verifyDocumentHashOnBlockchain(hash)
SA->>BS: verifyOnChain(hash)
BS->>SC: verifyDocument(hash)
SC-->>BS: (exists, timestamp, depositor)
BS-->>SA: Verification result
SA-->>UI: "✓ Document Verified"
```
---
## 10. How to Run Locally
### Prerequisites
- Node.js installed
- The Next.js app running (`npm run dev`)
### Step 1: Start the Hardhat Node
Open a **new terminal** and run:
```bash
cd blockchain
npx hardhat node
```
This starts a local Ethereum blockchain at `http://127.0.0.1:8545` with 20 pre-funded accounts (10,000 ETH each).
> ⚠️ **Keep this terminal open!** The node must be running for blockchain features to work.
### Step 2: Deploy the Smart Contract
In another terminal:
```bash
cd blockchain
npx hardhat run scripts/deploy.ts --network localhost
```
Copy the contract address and put it in your `.env`:
```env
BLOCKCHAIN_CONTRACT_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3
```
### Step 3: Start the Next.js App
```bash
npm run dev
```
### Step 4: Test the Flow
1. Upload a contract PDF
2. Wait for AI analysis to complete
3. Check the blockchain icon/badge on the contract
4. Visit `/blockchain` to see the transaction in the explorer
5. Copy a document hash and paste it in the verification panel
### Important Notes
- If you restart the Hardhat node, you need to **redeploy** the contract (step 2) because the local blockchain state is reset
- The Hardhat node logs every transaction in real-time — you can watch the blockchain activity live
- All blockchain features gracefully degrade: if the node is offline, the app still works normally without blockchain
---
## 11. Deploying to Sepolia Testnet
For your PFE presentation, you can deploy to the real Ethereum Sepolia testnet to get actual Etherscan links.
### Step 1: Get a Free RPC URL
1. Go to [alchemy.com](https://alchemy.com) (free account)
2. Create a new app → select "Ethereum Sepolia"
3. Copy the HTTPS URL
### Step 2: Get Free Sepolia ETH
1. Go to [sepoliafaucet.com](https://sepoliafaucet.com) or [faucets.chain.link](https://faucets.chain.link)
2. Paste your wallet address
3. Receive 0.5 Sepolia ETH (enough for hundreds of transactions)
### Step 3: Update .env
```env
BLOCKCHAIN_NETWORK=sepolia
BLOCKCHAIN_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY
BLOCKCHAIN_PRIVATE_KEY=your_sepolia_wallet_private_key
BLOCKCHAIN_CONTRACT_ADDRESS= # Will be filled after deployment
```
### Step 4: Deploy to Sepolia
```bash
# Set env vars for hardhat
set SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY
set DEPLOYER_PRIVATE_KEY=your_private_key
cd blockchain
npx hardhat run scripts/deploy.ts --network sepolia
```
### Step 5: Verify on Etherscan
After deploying, transactions will have real Etherscan links:
```
https://sepolia.etherscan.io/tx/0x...
```
---
## 12. Technology Choices & Rationale
| Technology | Why We Chose It |
| ------------------------ | ----------------------------------------------------------------- |
| **Solidity 0.8.24** | Latest stable version with built-in overflow protection |
| **Hardhat** | Industry standard for Solidity development, free local blockchain |
| **ethers.js v6** | Modern, lightweight, TypeScript-native Ethereum library |
| **SHA-256** | Standard cryptographic hash, deterministic, collision-resistant |
| **Server-side wallet** | Users don't need MetaMask; enterprise-grade UX |
| **Sepolia testnet** | Official Ethereum testnet, free, has Etherscan explorer |
| **Graceful degradation** | Blockchain is optional; app works perfectly without it |
### Why NOT Web3j / Java?
The original project spec suggested Web3j (Java library). We chose ethers.js instead because:
1. Our backend is **Next.js/TypeScript**, not Spring Boot
2. ethers.js has **better TypeScript support** and is more actively maintained
3. Both libraries do the same job — interact with Ethereum — but ethers.js is native to our stack
---
## 13. File Reference
### Smart Contract Layer
| File | Purpose |
| ------------------------------------------- | ----------------------- |
| `blockchain/contracts/DocumentRegistry.sol` | Solidity smart contract |
| `blockchain/test/DocumentRegistry.test.ts` | 14 comprehensive tests |
| `blockchain/scripts/deploy.ts` | Deployment script |
| `blockchain/hardhat.config.ts` | Hardhat configuration |
| `blockchain/package.json` | Hardhat dependencies |
### Service Layer
| File | Purpose |
| ------------------------------------ | ---------------------------- |
| `lib/services/blockchain.service.ts` | Core blockchain interactions |
| `lib/services/blockchain.types.ts` | TypeScript type definitions |
### Server Actions
| File | Purpose |
| ---------------------------------------------- | ------------------------------ |
| `features/blockchain/api/blockchain.action.ts` | Blockchain server actions |
| `features/contracts/api/contract.action.ts` | Updated with auto-registration |
### Frontend
| File | Purpose |
| --------------------------------------- | ---------------------------- |
| `app/(dashboard)/blockchain/page.tsx` | Blockchain Explorer page |
| `app/(dashboard)/blockchain/layout.tsx` | Page metadata |
| `components/layout/navigation.tsx` | Updated with blockchain link |
### Database
| File | Purpose |
| ---------------------- | ------------------------------ |
| `prisma/schema.prisma` | Updated with blockchain fields |
### Configuration
| File | Purpose |
| -------------- | ----------------------------- |
| `.env` | Blockchain env vars |
| `.env.example` | Template for new developers |
| `.gitignore` | Blockchain artifacts excluded |
---
## Glossary
| Term | Definition |
| -------------------- | -------------------------------------------------------------------- |
| **Hash** | A fixed-size fingerprint of data. Same input → same output. |
| **SHA-256** | A specific hash algorithm producing 256-bit (32-byte) outputs |
| **Smart Contract** | A program stored on the blockchain that executes automatically |
| **Gas** | The fee for executing operations on Ethereum (free on testnet) |
| **Block** | A batch of transactions grouped together on the blockchain |
| **Transaction (Tx)** | A single operation on the blockchain (e.g., registering a hash) |
| **Tx Hash** | A unique identifier for a transaction (like a receipt number) |
| **Block Number** | The sequential number of the block containing a transaction |
| **Block Timestamp** | The time the block was created (proof of when the tx happened) |
| **Private Key** | Secret key used to sign transactions (like a password) |
| **Address** | Public identifier derived from the private key (like a username) |
| **ABI** | Application Binary Interface — the "API spec" of a smart contract |
| **Hardhat** | Development tool for writing, testing, and deploying smart contracts |
| **Sepolia** | Ethereum test network for free experimentation |
| **ethers.js** | JavaScript library for interacting with the Ethereum blockchain |
| **Faucet** | A service that gives free test ETH for development |

View File

@@ -1,34 +0,0 @@
# LexiChain — Blockchain Module Overview
## 🔗 What does the Blockchain do here?
In the LexiChain BFSI platform, the blockchain acts as a **Digital Notary**. Its primary purpose is to provide **Proof of Existence** and **Proof of Integrity** for sensitive financial and insurance contracts.
### 1. Proof of Existence
When a contract is uploaded, its unique digital fingerprint (SHA-256 hash) is recorded on the blockchain. Because the blockchain is immutable, it provides indisputable proof that the document existed at a specific point in time.
### 2. Tamper Evidence
We don't store the actual PDF on the blockchain (for privacy and cost). We store its **Hash**. If even a single character in the PDF is changed, the hash will change, and the platform will flag the document as invalid or modified.
### 3. Zero-Knowledge Proof
Users can prove they have the original document to any third party (regulators, lawyers) by comparing the file's hash against the public blockchain record, without ever revealing the private contents of the document itself.
---
## 🛠️ The Blockchain Stack
| Technology | Role | Why we used it? |
|:---|:---|:---|
| **Solidity (0.8.24)** | **Smart Contract** | The industry-standard language for Ethereum. It allows us to write the "logic" of the registry (registration, verification, ownership) directly into the blockchain. |
| **Hardhat** | **Development Framework** | Provides a local Ethereum environment. It allows us to test transactions instantly for free and simulate real-world blockchain behavior on a developer machine. |
| **Ethers.js (v6)** | **Integration Library** | A powerful and lightweight library that bridges our Next.js backend with the Ethereum network. It handles the complex math of signing transactions and talking to the smart contract. |
| **Next.js Server Actions** | **Backend Bridge** | We use server-side logic to handle blockchain interactions. This means **users don't need MetaMask** or crypto-wallets; the platform handles the "gas fees" and signing automatically. |
| **Sepolia Testnet** | **Deployment Target** | A public Ethereum test network. It allows us to show the jury a "real" deployment on a global network with real block explorers (Etherscan) without using real money. |
| **SHA-256 Hashing** | **Security Standard** | A cryptographic algorithm that turns any file into a unique 64-character string. It is the "gold standard" for ensuring document integrity. |
---
## 🏆 Key Benefits
* **Trustless**: You don't have to trust the database administrator; you trust the math.
* **Transparent**: Transactions are visible to auditors via the Blockchain Explorer.
* **Privacy-First**: No personal data or document text ever touches the public blockchain.

View File

@@ -1,309 +0,0 @@
# Blockchain Integration — LexiChain BFSI Platform
## Goal
Add a **fully functional, 100% free** blockchain module to the existing LexiChain platform. This module provides:
1. **Proof of Deposit** — SHA-256 hash of each contract document is stored on-chain with a timestamp, making submission dates provable and tamper-proof.
2. **On-chain Verification** — Anyone can verify that a document existed at a specific time.
3. **Blockchain Explorer UI** — A new `/blockchain` page showing all on-chain transactions + per-contract verification status.
---
## User Review Required
> [!IMPORTANT]
> **Zero cost guaranteed.** The entire implementation uses:
> - **Hardhat local node** for development (free, instant, unlimited)
> - **Ethereum Sepolia testnet** for demo/presentation (free test ETH from faucets)
> - No MetaMask required for end-users — all blockchain operations run **server-side** via a backend wallet
> [!WARNING]
> **Server-side wallet approach**: Instead of requiring users to install MetaMask and sign transactions, the server holds a private key and signs transactions on behalf of the platform. This is the right UX for a BFSI enterprise platform (users shouldn't need crypto knowledge). The private key is stored in `.env` and never exposed to the client.
> [!IMPORTANT]
> **Dual-mode architecture**:
> - `NODE_ENV=development` → Hardhat local node (`http://127.0.0.1:8545`)
> - `NODE_ENV=production` or env flag → Sepolia testnet (via free Alchemy/Infura RPC)
>
> You can switch between modes with a single env variable change.
---
## Proposed Changes
### Component 1: Smart Contract (Hardhat + Solidity)
Creates a standalone `blockchain/` directory at the project root with a Hardhat project for developing, testing, and deploying the smart contract.
#### [NEW] [blockchain/contracts/DocumentRegistry.sol](file:///c:/Stage/Project-PFE/bfsi-project/blockchain/contracts/DocumentRegistry.sol)
Solidity smart contract with:
- `registerDocument(bytes32 docHash, string calldata fileName)` — stores hash + metadata on-chain
- `verifyDocument(bytes32 docHash)` — checks if a hash exists and returns timestamp + depositor
- `getDocumentsByDepositor(address depositor)` — lists all docs registered by an address
- Events: `DocumentRegistered(bytes32 indexed docHash, uint256 timestamp, address indexed depositor, string fileName)`
- Modifier to prevent duplicate registrations
#### [NEW] [blockchain/hardhat.config.ts](file:///c:/Stage/Project-PFE/bfsi-project/blockchain/hardhat.config.ts)
Hardhat config with:
- Local Hardhat network (default, free)
- Sepolia network config (reads RPC URL + private key from env)
- Solidity 0.8.24 compiler
#### [NEW] [blockchain/test/DocumentRegistry.test.ts](file:///c:/Stage/Project-PFE/bfsi-project/blockchain/test/DocumentRegistry.test.ts)
Comprehensive tests:
- Register a document and verify timestamp
- Prevent duplicate registration
- Verify non-existent document returns zero
- Multiple documents by same depositor
#### [NEW] [blockchain/scripts/deploy.ts](file:///c:/Stage/Project-PFE/bfsi-project/blockchain/scripts/deploy.ts)
Deployment script that outputs the contract address for use in `.env`.
#### [NEW] [blockchain/package.json](file:///c:/Stage/Project-PFE/bfsi-project/blockchain/package.json)
Separate package.json for the Hardhat project (keeps blockchain dependencies isolated from the Next.js app).
---
### Component 2: Next.js Blockchain Service Layer
Server-side service that connects to the blockchain from Next.js server actions. No browser wallet needed.
#### [NEW] [lib/services/blockchain.service.ts](file:///c:/Stage/Project-PFE/bfsi-project/lib/services/blockchain.service.ts)
Core blockchain service:
- `hashDocument(fileUrl: string): Promise<string>` — downloads contract PDF and computes SHA-256
- `registerOnChain(documentHash: string, fileName: string): Promise<{ txHash, blockNumber, blockTimestamp }>` — sends transaction to smart contract
- `verifyOnChain(documentHash: string): Promise<{ exists, timestamp, depositor }>` — reads on-chain data
- Uses `ethers.js v6` with `JsonRpcProvider` + `Wallet` (server-side, no MetaMask)
- Auto-detects network mode from env vars
#### [NEW] [lib/services/blockchain.types.ts](file:///c:/Stage/Project-PFE/bfsi-project/lib/services/blockchain.types.ts)
TypeScript types for blockchain data:
```typescript
interface BlockchainProof {
documentHash: string;
txHash: string;
blockNumber: number;
blockTimestamp: Date;
network: 'hardhat' | 'sepolia';
contractAddress: string;
explorerUrl: string | null; // Sepolia etherscan link
}
```
---
### Component 3: Server Actions & Integration
#### [NEW] [features/blockchain/api/blockchain.action.ts](file:///c:/Stage/Project-PFE/bfsi-project/features/blockchain/api/blockchain.action.ts)
New server actions:
- `registerContractOnBlockchain(contractId: string)` — hashes + registers + saves proof to DB
- `verifyContractOnBlockchain(contractId: string)` — verifies on-chain status
- `getBlockchainTransactions()` — fetches all blockchain proofs for the authenticated user
#### [MODIFY] [features/contracts/api/contract.action.ts](file:///c:/Stage/Project-PFE/bfsi-project/features/contracts/api/contract.action.ts)
After successful AI analysis, **automatically trigger** blockchain registration:
- In `analyzeContractAction()`, after `ContractService.updateWithAIResults()`, call `BlockchainService.hashAndRegister()`
- Save `documentHash`, `txHash` to the contract record
- This means every analyzed contract gets an automatic on-chain proof
---
### Component 4: Database Schema Update
#### [MODIFY] [prisma/schema.prisma](file:///c:/Stage/Project-PFE/bfsi-project/prisma/schema.prisma)
Expand the existing blockchain placeholder fields on `Contract`:
```diff
// Blockchain (later)
- documentHash String?
- txHash String?
- ipfsUrl String?
+ documentHash String?
+ txHash String?
+ blockNumber Int?
+ blockTimestamp DateTime?
+ blockchainNetwork String? // 'hardhat' | 'sepolia'
+ contractAddress String? // smart contract address used
```
Add a new `BlockchainTransaction` model for the explorer view:
```prisma
model BlockchainTransaction {
id String @id @default(cuid())
userId String
user User @relation(...)
contractId String
contract Contract @relation(...)
documentHash String
txHash String @unique
blockNumber Int
blockTimestamp DateTime
network String // 'hardhat' | 'sepolia'
contractAddress String
status String @default("CONFIRMED") // PENDING, CONFIRMED, FAILED
createdAt DateTime @default(now())
}
```
---
### Component 5: Frontend — Blockchain Explorer Page
#### [NEW] [app/(dashboard)/blockchain/page.tsx](file:///c:/Stage/Project-PFE/bfsi-project/app/(dashboard)/blockchain/page.tsx)
New dashboard page at `/blockchain` with:
- **Header stats**: Total verified contracts, latest block, network status
- **Transaction table**: All blockchain proofs with txHash, contract name, timestamp, verification status
- **Verification panel**: Paste a document hash to check its on-chain status
- **Network indicator**: Shows whether connected to Hardhat (local) or Sepolia
#### [NEW] [features/blockchain/components/blockchain-explorer.tsx](file:///c:/Stage/Project-PFE/bfsi-project/features/blockchain/components/blockchain-explorer.tsx)
Main explorer component with:
- Animated blockchain-themed cards
- Transaction list with expandable details
- Real-time verification status badges
- Network health indicator
#### [NEW] [features/blockchain/components/verify-document.tsx](file:///c:/Stage/Project-PFE/bfsi-project/features/blockchain/components/verify-document.tsx)
Standalone verification widget:
- File upload → compute hash → check on-chain
- Shows proof details if found (timestamp, block, depositor)
- Visual "Verified ✓" / "Not Found ✗" result
#### [NEW] [features/blockchain/components/blockchain-proof-badge.tsx](file:///c:/Stage/Project-PFE/bfsi-project/features/blockchain/components/blockchain-proof-badge.tsx)
Small badge component to show on contract cards:
- 🟢 "On-Chain Verified" (with txHash link)
- 🟡 "Pending" (registration in progress)
- ⚫ "Not Registered" (no blockchain proof yet)
---
### Component 6: Navigation & Integration Updates
#### [MODIFY] [components/layout/navigation.tsx](file:///c:/Stage/Project-PFE/bfsi-project/components/layout/navigation.tsx)
Add new nav item:
```typescript
{
href: "/blockchain",
label: "Blockchain",
icon: <Link2 className="w-5 h-5" />,
description: "On-chain proofs",
}
```
#### [MODIFY] [types/contract.types.ts](file:///c:/Stage/Project-PFE/bfsi-project/types/contract.types.ts)
Add blockchain fields to the Contract interface:
```typescript
blockNumber: number | null;
blockTimestamp: Date | null;
blockchainNetwork: string | null;
contractAddress: string | null;
```
#### [MODIFY] [.env.example](file:///c:/Stage/Project-PFE/bfsi-project/.env.example)
Add blockchain env vars:
```env
# Blockchain
BLOCKCHAIN_PRIVATE_KEY= # Server wallet private key (Hardhat default for dev)
BLOCKCHAIN_RPC_URL= # RPC endpoint (empty = Hardhat local)
BLOCKCHAIN_CONTRACT_ADDRESS= # Deployed DocumentRegistry address
BLOCKCHAIN_NETWORK=hardhat # 'hardhat' or 'sepolia'
SEPOLIA_RPC_URL= # Free Alchemy/Infura Sepolia RPC
```
---
## Architecture Diagram
```mermaid
flowchart TD
U[User Browser] --> UI[Next.js App Router]
UI -->|Server Action| BA[blockchain.action.ts]
BA --> BS[BlockchainService]
BS -->|ethers.js v6| BC[Smart Contract on Blockchain]
BS -->|Hash document| PDF[Contract PDF from UploadThing]
BA --> DB[(PostgreSQL - BlockchainTransaction)]
UI -->|Server Action| CA[contract.action.ts]
CA -->|After AI analysis| BA
subgraph "Local Dev"
HN[Hardhat Node :8545]
end
subgraph "Demo/Production"
SN[Sepolia Testnet]
end
BC -.-> HN
BC -.-> SN
```
---
## Implementation Order
| Step | Component | Estimated Effort |
|------|-----------|-----------------|
| 1 | Hardhat project + Smart Contract + Tests | ~30 min |
| 2 | Deploy to local Hardhat node | ~5 min |
| 3 | `BlockchainService` (server-side ethers.js) | ~30 min |
| 4 | Prisma schema update + migration | ~10 min |
| 5 | Server actions (`blockchain.action.ts`) | ~20 min |
| 6 | Integration into `analyzeContractAction` | ~10 min |
| 7 | Blockchain Explorer page + components | ~45 min |
| 8 | Navigation update + proof badges | ~15 min |
| 9 | Deploy to Sepolia testnet (optional, for demo) | ~15 min |
**Total: ~3 hours of implementation**
---
## Open Questions
> [!IMPORTANT]
> **1. Auto-register vs. Manual button?**
> The plan currently auto-registers contracts on the blockchain after AI analysis completes. Alternatively, we could add a manual "Register on Blockchain" button per contract. Which do you prefer? (I recommend **both**: auto-register + manual re-register option)
> [!IMPORTANT]
> **2. Sepolia for presentation?**
> Do you want me to also set up the Sepolia testnet deployment for your PFE presentation/jury? This gives you real Etherscan links to show. You'll just need to grab free Sepolia ETH from a faucet (takes 2 minutes). We can start with Hardhat local and add Sepolia later.
> [!IMPORTANT]
> **3. IPFS integration?**
> Your schema has an `ipfsUrl` field. Do you want to also store contract files on IPFS (using a free service like Pinata with 1GB free tier)? This would give you decentralized file storage + on-chain hash. Or should we skip this to keep things simpler?
---
## Verification Plan
### Automated Tests
1. **Smart contract tests**`cd blockchain && npx hardhat test` (tests register, verify, duplicate prevention)
2. **Integration test** — Upload a contract → AI analysis → verify blockchain fields are populated in DB
3. **Service test** — Call `BlockchainService.hashDocument()` + `registerOnChain()` directly
### Manual Verification
1. Start Hardhat node → deploy contract → upload a contract in the app → check `/blockchain` page shows the transaction
2. Use the verification panel to re-verify a document hash
3. Check the contract detail view shows the "On-Chain Verified" badge
4. If Sepolia is configured: verify the txHash on [Sepolia Etherscan](https://sepolia.etherscan.io/)

View File

@@ -1,80 +0,0 @@
# LexiChain: Intelligent BFSI Contract Management System
## 🌟 The Platform Vision
**LexiChain** is a state-of-the-art enterprise platform designed specifically for the **BFSI** (Banking, Financial Services, and Insurance) sector. The core objective is to solve the historical problem of "Information Silos" and "Trust Gaps" in contract management.
In the traditional world, insurance policies and bank loans are long, complex, and opaque. LexiChain uses **Generative AI** to make these documents "conversational" and **Blockchain Technology** to make them "tamper-proof."
---
## 🏗️ System Architecture
The platform follows a **Modular Full-Stack Architecture** designed for scalability, security, and high performance. It is divided into three distinct layers:
### 1. The Presentation Layer (Frontend)
Built with **React and Next.js**, the interface provides a "Premium Executive" experience. It is fully responsive, theme-aware, and designed for high-density information display. It uses **Server Components** for fast loading and **Client Components** for interactive elements like the AI Chat and Blockchain Explorer.
### 2. The Intelligence & Processing Layer (Backend)
This is the "Brain" of LexiChain. It handles:
* **Authentication**: Managed by **Clerk**, providing enterprise-grade security and multi-factor authentication.
* **File Orchestration**: Securely handling document uploads and cloud storage.
* **AI Pipeline**: Converting raw PDF data into structured knowledge.
* **Blockchain Bridge**: Acting as a middleware between the web app and the decentralized network.
### 3. The Persistence Layer (Database)
We use a **PostgreSQL** database managed by **Prisma ORM**. This stores all user metadata, contract details, and the historical "Audit Trail" of blockchain transactions.
---
## 🤖 Core Pillar 1: AI & Retrieval-Augmented Generation (RAG)
LexiChain doesn't just "read" your contracts; it "understands" them. We implement a pattern called **RAG (Retrieval-Augmented Generation)**.
### How it works:
1. **Ingestion & Parsing**: When a contract is uploaded, our AI service (powered by **Google Gemini**) breaks the document down into small "semantic chunks."
2. **Vector Indexing**: These chunks are indexed based on their meaning.
3. **Contextual Retrieval**: When you ask a question like *"Does this policy cover water damage?"*, the system doesn't search for keywords. It searches for **Concepts**.
4. **Informed Response**: The AI retrieves the relevant sections of your contract and uses them as "facts" to generate a precise, grounded answer. This eliminates "hallucinations" and ensures 100% accuracy based on your actual document.
---
## 🔗 Core Pillar 2: The Blockchain Trust Layer
In the BFSI industry, "when" and "what" was signed is everything. LexiChain uses an **Ethereum-based Smart Contract** to establish absolute trust.
### The Problem it Solves:
If a user and a bank have a dispute, the bank could theoretically change the digital contract in their database. LexiChain prevents this through **Immutable Proof-of-Deposit**.
### Key Concepts Implemented:
* **Cryptographic Fingerprinting (Hashing)**: We generate a unique SHA-256 hash of the contract. This fingerprint is mathematically tied to every single character in the document.
* **Smart Contract Execution**: The platform automatically sends this fingerprint to a **Solidity Smart Contract** on the blockchain.
* **Immutable Timestamping**: Once the transaction is "mined," it is given a permanent timestamp by the network. This provides an **indisputable proof** that the document existed in that exact state on that specific date.
* **Decentralized Verification**: Anyone with the file can verify it against the blockchain record. If even one comma is changed in the PDF, the verification will fail.
---
## 🔄 The Integrated Workflow (The App Journey)
1. **Upload**: The user securely uploads a contract (Insurance policy, Loan agreement, etc.).
2. **AI Extraction**: The AI immediately extracts key data points (Expiration date, Total value, Involved parties) to populate the dashboard.
3. **Semantic Indexing**: The document is prepared for the RAG-based Chat interface.
4. **On-Chain Registration**: Simultaneously, the system computes the document's hash and registers it on the blockchain.
5. **Interaction**: The user can now "Chat" with their document or verify its "Blockchain Status" via the Explorer.
---
## 🛠️ The Technology Stack
* **Frontend/Backend Framework**: Next.js 15+ (App Router).
* **Styling**: TailwindCSS with Custom Framer Motion animations.
* **Database**: PostgreSQL with Prisma ORM.
* **AI Engine**: Google Gemini Pro (Vision & Text).
* **Blockchain Environment**: Hardhat (Local) & Sepolia (Public Testnet).
* **Smart Contract Language**: Solidity 0.8.24.
* **Blockchain Integration**: Ethers.js v6.
* **File Storage**: UploadThing.
* **Security/Auth**: Clerk Auth.
---
## 📈 Software Engineering Principles Used
* **Separation of Concerns**: The AI, Blockchain, and Core Business logic are kept in separate services to prevent "God Objects."
* **Idempotency**: Blockchain registrations are designed to be idempotent (you can't register the same hash twice).
* **Graceful Degradation**: If the blockchain network is down, the AI and Core App features continue to work normally.
* **Data Integrity**: Using SHA-256 ensures that the data being audited is exactly the data that was signed.
* **Scalability**: The RAG architecture allows the system to handle thousands of documents without slowing down the AI responses.

View File

@@ -1,85 +0,0 @@
# LexiChain — Technical Platform Overview
## 1. Executive Summary: What is LexiChain?
**LexiChain** is an advanced intelligence platform specifically designed for the **BFSI** (Banking, Financial Services, and Insurance) sector. It transforms complex, opaque legal documents into interactive, actionable data using a combination of **Generative AI** and **Blockchain Technology**.
The core mission of LexiChain is to solve the "Black Box" problem in contracts: where clients and institutions often sign long documents without fully understanding the hidden risks, obligations, or deadlines.
---
## 2. The Core Problem & Solution
### The Problem
* **Cognitive Overload**: Insurance and banking contracts are filled with "Legalese"—dense, technical language that is difficult for non-experts to parse.
* **Lack of Trust**: There is no easy way to prove that a document hasn't been modified after signing.
* **Static Data**: Traditional PDFs are "dead" files. You cannot ask a PDF a question like *"What happens if I miss a payment by 3 days?"*
### The LexiChain Solution
LexiChain creates a **"Living Document"** environment. It uses AI to extract meaning and Blockchain to guarantee integrity, allowing users to converse with their contracts in natural language.
---
## 3. System Architecture
LexiChain is built using a modern **Distributed Architecture** composed of four primary layers:
### A. The Client Layer (Frontend)
Built with **Next.js 15** and **Tailwind CSS**. It focuses on **User Experience (UX)**, providing a dashboard that works seamlessly on both desktop and mobile. It handles the secure transmission of files to the backend.
### B. The Application Layer (Backend)
This is the "Brain" of the system, powered by **Next.js Server Actions**. It coordinates the flow of data between the user, the database, the AI models, and the blockchain network. It manages authentication, file storage, and the processing pipeline.
### C. The Intelligence Layer (AI & RAG)
This layer uses **Gemini 1.5 Pro** and **Mistral AI** for high-speed analysis. Instead of just "reading" text, it uses a **Vector Database** to perform Retrieval-Augmented Generation (RAG), ensuring the AI answers only based on the specific facts found in the uploaded contract.
### D. The Trust Layer (Blockchain)
A decentralized layer powered by **Ethereum/Hardhat**. It creates a unique cryptographic "fingerprint" (hash) for every contract. Once recorded, this fingerprint becomes an immutable proof of the document's existence and original state.
---
## 4. How the Application Works (The Pipeline)
1. **Intake**: The user uploads a contract (PDF/Image).
2. **OCR & Parsing**: The system converts the document into machine-readable text.
3. **Semantic Chunking**: The text is broken down into small "concepts" or chunks.
4. **AI Analysis**: The AI extracts key metadata (Dates, Parties, Obligations, Risks).
5. **Blockchain Certification**: The document hash is sent to a Smart Contract to lock in the "Proof of Deposit."
6. **RAG Indexing**: The chunks are stored in a specialized index for the Chat interface.
7. **Interaction**: The user can now ask questions, view the blockchain proof, or check their dashboard for upcoming contract deadlines.
---
## 5. Deep Dive: RAG (Retrieval-Augmented Generation)
### What is it?
In simple terms, RAG is like giving the AI a **"Open Book Exam."**
Most AI models rely on what they learned during training (which might be old or generic). With RAG, when you ask a question, the system first **searches** your specific contract for the relevant paragraphs, **retrieves** them, and then **gives** them to the AI to summarize.
### Why use it in BFSI?
* **Zero Hallucination**: The AI is forbidden from "guessing." If the answer isn't in your contract, it says "I don't know."
* **Contextual Accuracy**: It understands the difference between a "Home Loan" in 2010 vs. a "Car Insurance" in 2024 because it only looks at the specific context of your file.
---
## 6. Deep Dive: Blockchain & Trust
### The Digital Notary
In the BFSI world, dates and integrity are everything. If a claim is denied because of a "deadline," the user needs proof that they held the document on time.
### How it works technically:
1. **Hashing**: We turn your PDF into a 64-character string called a "Hash." Even changing a single comma in the PDF would result in a completely different hash.
2. **Immutability**: Once this hash is written into our **Solidity Smart Contract**, it can never be deleted or changed by anyone—not even the platform administrators.
3. **Verification**: At any time, a user can "Verify" their document. The system re-hashes the file and compares it to the blockchain. If they match, the document is **Genuine**.
---
## 7. The Technology Stack (Summary)
* **Frontend**: Next.js (React), Tailwind CSS, Lucide Icons, Framer Motion.
* **Backend**: TypeScript, Prisma ORM, Server Actions.
* **Database**: PostgreSQL (Neon) for metadata, Vector Storage for AI.
* **AI**: Google Gemini (Large Language Model), Mistral AI (Fallback with Pixtral Vision).
* **Blockchain**: Solidity (Smart Contracts), Hardhat (Local Node), Ethers.js (Integration).
* **Storage**: UploadThing (Secure File Hosting).
---
## 8. Conclusion
LexiChain is not just a document viewer; it is a **Decision Support System**. By combining the analytical power of AI with the structural trust of Blockchain, it bridges the gap between complex legal documents and clear, verifiable human understanding.