🌐 Open Web App or 💻 Download
---Open-source financial data platform for importing, processing, and analyzing bank statements
Quick Start • Features • Tech Stack • Architecture • Contributing
TL;DR
- Upload bank statements (PDF / CSV / XLSX / image) → auto-parse → deduplicate → AI-categorize
- Multi-tenant workspaces with RBAC, audit log, and one-click rollback
- Full stack running locally in one command:
make quick-devBuilt for finance teams, accountants, and developers who need to process and analyze bank statement data without proprietary SaaS lock-in.
⚠️ The demo GIF and screenshots are based on v1 and will be updated soon.
Lumio turns unstructured financial documents (PDFs, CSVs, email receipts) into clean, queryable data. Open-source, self-hosted, and built for teams that need control over their financial data pipeline.
Lumio is a full-stack financial operations platform built for teams that need to import, categorize, analyze, and collaborate on bank statement data.
- Multi-format Statement Import — PDF, CSV, XLSX, and image files. Native parsers for Kaspi Bank, Bereke Bank, and Bank Hapoalim / Isracard. Generic AI PDF parser for any other bank.
- OCR for Image Statements — Tesseract.js text extraction from scanned documents and photos.
- Idempotent Uploads — SHA-256 file hashing prevents duplicate imports.
- Transaction Deduplication — Fingerprint-based duplicate detection with confidence scoring, merge, and mark-as-duplicate workflows.
- AI Auto-Categorization — OpenAI-compatible local/provider endpoint with per-workspace learning rules.
- Multi-Tenant Workspaces — Unlimited workspaces with invitation flows and per-workspace data isolation.
- Granular RBAC — Roles: owner, admin, member, viewer. Per-user permission overrides.
- Dashboard & Reports — Cash flow, top categories, trends, custom report builder with CSV/XLSX export.
- Audit Log — Complete event trail with one-click rollback for supported operations.
- Webhooks — Outbound event delivery to subscribed endpoints with token-based authentication.
- API Keys — Programmatic access via
lum_-prefixed, SHA-256 hashed keys with revocation support. - Budgets — Budget tracking with manual spend recording and alerts.
- Subscriptions — Recurring billing detection and management with frequency-based tracking.
- Docker Ready — One-command deployment with Docker Compose.
Extended modules
- ML Categorization Rules —
CategoryLearningremembers per-workspace merchant→category patterns and applies them automatically on future imports. - AI Financial Insights — Automatically generated insights surfaced on the dashboard; dismissible per-user.
- Generic AI PDF Parser — an OpenAI-compatible endpoint extracts structured transaction data from any PDF when no native parser matches.
- IMAP Receipts — mailbox polling pulls email receipts, parses merchant/amount/tax/line-item data, links receipts to transactions.
- S3-compatible Storage — import and sync statement files with MinIO or another S3-compatible bucket.
- WebDAV Storage — import and sync statement files with Nextcloud or another WebDAV-compatible server.
- Workbook Import — export and import custom table data via XLSX, CSV, and ODS files.
- Telegram Bot — Scheduled financial reports delivered to a Telegram chat or channel.
- Auth Sessions — List and manage active login sessions per device. Revoke individual sessions or all at once.
- Workspace Invitations — Email invitation flow with token-based acceptance.
- Balance Sheet — Account-level balance tracking with historical snapshots and export.
- Accounts Payable — Pay-tab workflow for managing and tracking payable records.
- Custom Tables — User-defined data structures with typed columns, batch editing, formula support, and Sheets import.
- Manual Data Entry — Record cash expenses, income, and receipts manually with custom fields and file attachments.
- Categories — Hierarchical transaction categories with usage counts and enable/disable toggle.
- Reference Data — Tax rates, branches, and wallets for enriching transactions.
- Exchange Rates — Currency exchange rate tracking and management.
- File Storage — Document store with folders, tags, versioning, per-file permissions, and expiring shared links.
- In-App Notifications — Real-time feed with per-category preferences and unread badge count.
- WebSocket Support — Live updates via Socket.IO for notifications and import progress.
- Observability — Prometheus metrics endpoint (
/api/v1/metrics) with pre-built Grafana dashboards. - Guided Onboarding — 10 interactive feature tours in English, Russian, and Kazakh.
- Storybook — Component library with stories for every UI primitive; auto-built on every PR.
Setting expectations upfront:
- Not a bank integration — Lumio parses statement files you export from your bank. It does not connect to bank APIs or fetch transactions automatically.
- Not a full general ledger — There is no double-entry bookkeeping, chart of accounts, or journal entry workflow.
- Not a tax calculation engine — Tax rates are reference data for enriching transactions; Lumio does not compute tax returns or filings.
- Not an invoicing tool — There is no invoice creation, sending, or payment tracking.
- Not a replacement for accounting software — Think of Lumio as the import and analysis layer that feeds your existing workflow, not a replacement for QuickBooks, Xero, or 1C.
| Bank | Format | Parser |
|---|---|---|
| Kaspi Bank | KaspiParser — native table extraction |
|
| Bereke Bank (new format) | BerekeNewParser — native |
|
| Bereke Bank (legacy format) | BerekeOldParser — native |
|
| Bank Hapoalim / Isracard | HapoalimParser — native (Hebrew) |
|
| Any bank | CSV | CsvParser — generic delimiter detection |
| Any bank | XLSX / XLS | ExcelParser — generic |
| Any bank | GenericPdfParser — AI-assisted via OpenAI-compatible endpoint |
|
| Any bank | Image (PNG / JPG) | OCR pipeline via Tesseract.js |
| Layer | Technology |
|---|---|
| Framework | NestJS 11 |
| Language | TypeScript 5 (strict) |
| Database | PostgreSQL 14 via TypeORM 0.3 |
| Cache | Redis 7 via cache-manager |
| Auth | JWT (access 1 h / refresh 30 d), Passport.js, bcrypt |
| File Processing | pdf-parse, pdf-lib, tesseract.js v5, sharp, xlsx |
| AI / LLM | OpenAI-compatible HTTP endpoint (Ollama, LocalAI, vLLM) |
| SMTP via nodemailer + React Email templates | |
| Real-time | Socket.IO 4 + @nestjs/websockets |
| Scheduling | @nestjs/schedule (cron jobs for Telegram reports, Gmail sync) |
| Metrics | prom-client (Prometheus) |
| Validation | class-validator + class-transformer (DTOs) |
| API Docs | Swagger / OpenAPI at /api/docs |
| Linter | Biome |
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Runtime | React 19 |
| Language | TypeScript 5 |
| Styling | MUI v7 + Emotion |
| Icons | Lucide React |
| Tables | TanStack Table v8 + TanStack Virtual v3 |
| Charts | ECharts v5 + echarts-for-react |
| Drag & Drop | @dnd-kit/core + @dnd-kit/sortable |
| HTTP | Axios v1 |
| Real-time | socket.io-client v4 |
| i18n | Intlayer v7 + next-intlayer (English, Russian, Kazakh) |
| Onboarding | driver.js |
| PDF Viewer | react-pdf v10 |
| Animation | framer-motion v12 |
| Component Dev | Storybook v8 (webpack5) |
| Tests | Vitest v2 |
| Layer | Technology |
|---|---|
| Containerization | Docker + Docker Compose |
| Monitoring | Prometheus + Grafana |
| CI/CD | GitHub Actions (CI, CD, CodeQL, dependency-review, Scorecard, release-please, Storybook) |
lumio/
├── backend/ # NestJS API server
│ ├── src/
│ │ ├── modules/ # 36 feature modules
│ │ │ ├── api-keys/ # Programmatic API key management
│ │ │ ├── application-settings/ # Runtime system configuration
│ │ │ ├── auth/ # JWT auth, refresh tokens, session management
│ │ │ ├── users/ # User CRUD, avatars, permission overrides
│ │ │ ├── workspaces/ # Multi-tenant workspaces, RBAC, invitations
│ │ │ ├── statements/ # Bank statement upload & lifecycle management
│ │ │ ├── transactions/ # Transaction CRUD, search, deduplication
│ │ │ ├── categories/ # Hierarchical category management
│ │ │ ├── classification/ # AI auto-categorization + ML learning rules
│ │ │ ├── parsing/ # Multi-format file parsers (Kaspi, Bereke, Hapoalim, CSV, AI)
│ │ │ ├── dashboard/ # Dashboard stats, trends, cash flow
│ │ │ ├── reports/ # Financial reports, export (CSV/XLSX)
│ │ │ ├── balance/ # Balance sheet accounts & snapshots
│ │ │ ├── budgets/ # Budget tracking & alerts
│ │ │ ├── storage/ # File storage, versioning, shared links
│ │ │ ├── gmail/ # Legacy receipt sync & parsing
│ │ │ ├── google-drive/ # Legacy Drive migration compatibility
│ │ │ ├── google-sheets/ # Legacy Sheets migration compatibility
│ │ │ ├── dropbox/ # Legacy Dropbox migration compatibility
│ │ │ ├── exchange-rates/ # Currency exchange rate management
│ │ │ ├── telegram/ # Telegram bot, scheduled reports
│ │ │ ├── custom-tables/ # User-defined data structures
│ │ │ ├── data-entry/ # Manual expense/income entry
│ │ │ ├── notifications/ # In-app notifications & preferences
│ │ │ ├── insights/ # AI-generated financial insights
│ │ │ ├── audit/ # Audit log with rollback
│ │ │ ├── import/ # Import session tracking
│ │ │ ├── branches/ # Branch reference data
│ │ │ ├── wallets/ # Wallet reference data
│ │ │ ├── tax-rates/ # Tax rate reference data
│ │ │ ├── payables/ # Accounts payable workflow
│ │ │ ├── receipts/ # Receipt management & browser
│ │ │ ├── subscriptions/ # Recurring billing detection & management
│ │ │ ├── webhooks/ # Outbound event delivery to endpoints
│ │ │ ├── open-protocol-integrations/ # S3, WebDAV, IMAP protocol handlers
│ │ │ └── observability/ # Prometheus metrics endpoint
│ │ ├── entities/ # 59 TypeORM entities
│ │ ├── common/ # Guards, decorators, interceptors, filters
│ │ ├── config/ # App configuration
│ │ └── migrations/ # 90 database migrations (auto-applied on startup)
│ ├── scripts/ # Admin, seed, parse debug, storage repair
│ └── @tests/ # Unit and E2E test suites
├── frontend/ # Next.js application
│ ├── app/
│ │ ├── (auth)/ # Login, register pages
│ │ ├── (onboarding)/ # Onboarding flow
│ │ ├── (main)/ # Protected app routes
│ │ │ ├── statements/ # Statement list, detail, reports sub-routes
│ │ │ ├── receipts/ # Gmail receipt browser
│ │ │ ├── reports/ # Financial reports
│ │ │ ├── custom-tables/ # Custom table UI
│ │ │ ├── workspaces/ # Workspace management
│ │ │ └── supported-banks/ # Supported banks reference page
│ │ ├── categories/ # Category management
│ │ ├── data-entry/ # Manual data entry UI
│ │ ├── integrations/ # Integration hub (S3, WebDAV, IMAP, workbook import)
│ │ ├── storage/ # File storage browser
│ │ ├── settings/ # Profile, notifications, workspace, Telegram
│ │ ├── audit/ # Audit log viewer
│ │ ├── admin/ # Admin dashboard & user management
│ │ ├── transactions/ # Transaction list & detail
│ │ ├── upload/ # Statement upload flow
│ │ ├── components/ # Reusable React components
│ │ ├── hooks/ # Custom hooks (useAuth, etc.)
│ │ ├── tours/ # driver.js guided tour definitions
│ │ └── stories/ # Storybook stories (*.stories.tsx)
│ └── public/ # Static assets, bank logos
├── docs/
│ ├── plans/ # 38 feature design & implementation plans
│ ├── CI/ # CI/CD pipeline documentation
│ ├── security/ # CVE allowlists, license exceptions
│ └── statements-examples/ # Sample bank statement files for testing
├── electron/ # Electron desktop app wrapper
├── mcp-server/ # Claude MCP server integration
├── website/ # Marketing / documentation website
├── observability/ # Prometheus & Grafana configuration
├── scripts/ # Shell helper scripts
│ ├── generate-env.sh # Generate .env files with random secrets
│ ├── storybook-download.sh # Download Storybook from CI artifacts
│ ├── storybook-serve.sh # Serve downloaded Storybook locally
│ └── generate-changelog.mjs # Changelog generation script
├── docker-compose.yml # Production Docker config (4 services)
├── docker-compose.dev.yml # Development overrides with hot reload
├── docker-compose.observability.yml # Prometheus + Grafana monitoring stack
└── Makefile # All development commands
- Docker and Docker Compose (for Docker mode)
- Node.js 20+ (only required for local mode without Docker)
git clone https://github.com/symonbaikov/lumio.git
cd lumio
make quick-devmake quick-dev does everything: copies env files, generates JWT secrets, starts all Docker services (postgres, redis, backend, frontend), runs database migrations, and seeds a demo user. Then open your browser:
- Frontend: http://localhost:3000
- Backend API: http://localhost:3001/api/v1
- Swagger Docs: http://localhost:3001/api/docs
Demo credentials:
- Email:
demo@lumio.dev - Password:
demo123
git clone https://github.com/symonbaikov/lumio.git
cd lumio
# Start only PostgreSQL and Redis via Docker
make db-start
# Install dependencies
npm install --prefix backend
npm install --prefix frontend
# Apply migrations and seed demo data
cd backend && npm run migration:run && npm run seed:demo
# Start backend and frontend in separate terminals
cd backend && npm run start:dev # Terminal 1 — http://localhost:3001
cd frontend && npm run dev # Terminal 2 — http://localhost:3000No .env files are required in development. For production and optional integrations, see Configuration.
| Service | URL | Notes |
|---|---|---|
| Frontend | http://localhost:3000 | Next.js app |
| Backend API | http://localhost:3001/api/v1 | All REST endpoints |
| Swagger Docs | http://localhost:3001/api/docs | Interactive API explorer |
| Storybook | http://localhost:6006 | make storybook |
| Prometheus | http://localhost:9090 | make observability |
| Grafana | http://localhost:3002 | make observability · admin / admin |
No environment variables are required in development mode. The backend uses sensible defaults.
| Setting | Default Value |
|---|---|
DATABASE_URL |
postgresql://finflow:finflow@localhost:5432/finflow |
REDIS_HOST |
localhost |
REDIS_PORT |
6379 |
PORT |
3001 |
JWT_SECRET |
Built-in dev default (disabled in production) |
JWT_REFRESH_SECRET |
Built-in dev default (disabled in production) |
JWT_EXPIRES_IN |
30d |
JWT_REFRESH_EXPIRES_IN |
30d |
To override any value, create backend/.env. A minimal template is available in backend/.env.example.
Frontend overrides go in frontend/.env.local (frontend/.env.local.example for the template).
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
JWT_SECRET |
Secret for signing access tokens |
JWT_REFRESH_SECRET |
Secret for signing refresh tokens |
NEXT_PUBLIC_API_URL |
Backend API URL seen by the browser |
Generate secure secrets with:
openssl rand -base64 32
# or use the helper script which sets up all env files at once:
bash scripts/generate-env.shOpen Protocol Storage & Mail
Use open protocols and self-hostable services for file sync and receipt import.
Configure S3-compatible storage, WebDAV storage, and IMAP inboxes from Integrations. Server env variables are only a temporary fallback for bootstrap or migration.
AI Auto-Categorization & Generic PDF Parsing
Point Lumio at an OpenAI-compatible endpoint from Integrations → AI-compatible endpoint. AI_API_KEY may be omitted for local endpoints that do not require authentication. Env values remain supported only as server defaults.
Dependency Policy
Do not add closed SaaS SDKs for new integration work. Prefer OSS libraries that implement open protocols such as SMTP, IMAP, WebDAV, S3-compatible object storage, and OpenAI-compatible local inference.
Telegram Bot
Get a token from @BotFather, then save the bot token in Settings → Telegram. The token is stored encrypted; TELEGRAM_BOT_TOKEN is only a fallback server default.
Email (SMTP)
Used for workspace invitation emails. Configure SMTP from Integrations → SMTP email. If neither UI settings nor env fallback are configured, invitation links are returned in the API response but no email is sent.
make seed-demoCreates demo@lumio.dev with password demo123 and a sample workspace with demo transactions.
# Using Makefile (works with Docker or locally)
make admin email=admin@example.com password=admin123 name="Admin User"
# Using Docker exec directly
docker exec -it finflow-backend npm run create-admin -- admin@example.com admin123 "Admin User"
# Local (no Docker)
cd backend && npm run create-admin -- admin@example.com admin123 "Admin User"Admin users have access to the /admin dashboard with full user management and system stats.
All common tasks are available via make. Run make help to see the full list with descriptions.
Setup & Services
make quick-dev # Zero-config startup: dev mode + seed demo user (recommended entry point)
make setup # Copy env files and generate JWT secrets only
make install # Install npm dependencies locally (no Docker)
make dev # Start all services in development mode (hot reload)
make start # Start all services in production mode
make stop # Stop all services
make restart # Restart all services
make clean # Stop services and remove all Docker volumes
make reset # clean + setup + start (full environment reset)
make ps # Show running containers
make stats # Show container CPU/memory usage
make health # Check health of all servicesLogs
make logs # Tail logs from all services
make logs-backend # Backend logs only
make logs-frontend # Frontend logs only
make logs-db # PostgreSQL logs
make logs-redis # Redis logsDatabase
make migrate # Run pending migrations (Docker)
make migrate-revert # Revert last applied migration
make migrate-generate name=MyMigration # Generate new migration after entity changes
make db-start # Start PostgreSQL + Redis only (for local dev)
make db-shell # Open psql shell
make db-backup # Dump database to .sql file
make db-restore file=backup.sql # Restore database from backupTesting
make test # Run all tests (backend + frontend)
make test-backend # Backend unit tests only
make test-frontend # Frontend Vitest tests only
make test-watch # Backend tests in watch mode
make test-cov # Backend tests with coverage report
make test-e2e # End-to-end testsCode Quality
make lint # Run Biome linter with auto-fix
make lint-check # Check lint without auto-fix
make format # Format code with Biome
make type-check # TypeScript type checking
make build # Build backend + frontend for production
make build-docker # Build Docker imagesMonitoring
make observability # Start Prometheus + Grafana
make observability-stop # Stop monitoring stackStorybook
make storybook # Start Storybook dev server at http://localhost:6006
make storybook-build # Build static Storybook to frontend/storybook-static/
make storybook-serve # Serve Storybook from downloaded CI artifacts
make storybook-download # Download latest Storybook from GitHub ActionsUtilities
make shell-backend # Open bash shell in backend container
make shell-frontend # Open sh shell in frontend container
make shell-db # Open bash shell in database container
make docs # Open Swagger docs in browser
make seed-demo # Create demo user with sample data
make admin email=X password=X name=X # Create admin user
make update # Update npm dependenciesLumio uses TypeORM migrations exclusively (synchronize: false). Migrations run automatically on every startup unless RUN_MIGRATIONS=false is set. There are currently 90 migrations covering the entire schema history.
# Apply all pending migrations (Docker)
make migrate
# Apply all pending migrations (local)
cd backend && npm run migration:run
# Generate a new migration after changing an entity
make migrate-generate name=AddTransactionMerchantColumn
# or locally:
cd backend && npm run migration:generate -- AddTransactionMerchantColumn
# Revert the last applied migration
make migrate-revertcd backend
# Debug parsing output for a specific file
npm run parse:debug -- /path/to/statement.pdf
# Dump raw PDF table structure (useful for new bank formats)
npm run parse:tables -- /path/to/statement.pdf
# Compare parsing output between two files
npm run parse:diff -- /path/to/old.pdf /path/to/new.pdf
# Verify storage integrity (check for orphaned files)
npm run storage:verify
# Repair storage (remove orphaned files)
npm run storage:repair
# Clean up old Gmail receipt processing jobs
npm run cleanup:gmail-receiptsmake dev
# equivalent to:
docker compose -f docker-compose.yml -f docker-compose.dev.yml upSource file changes automatically reload both backend (ts-node watch) and frontend (Next.js HMR).
cd backend
npm test # All unit tests
npm run test:watch # Watch mode
npm run test:cov # With coverage report (goal: 80%+)
npm run test:e2e # End-to-end tests
npm run test:golden # Parser golden file tests (deterministic output verification)
npm run test:ci # Unit + E2E (sequential, used in CI)Coverage report is written to backend/coverage/lcov-report/index.html.
Test files live in backend/@tests/unit/ (unit) and backend/@tests/e2e/ (E2E), using the *.spec.ts naming convention.
cd frontend
npm test # Run all tests with VitestStorybook documents all UI components with interactive examples.
# Start development server
make storybook # or: cd frontend && npm run storybook
# Build static output
make storybook-build # output: frontend/storybook-static/
# Work with CI artifacts
make storybook-download # Download latest build from GitHub Actions
make storybook-serve # Serve the downloaded build locallyStories live in frontend/app/stories/ and follow the *.stories.tsx naming convention. Storybook is automatically built on every PR and push to main as a GitHub Actions artifact (7-day retention for PRs, 30-day for main).
Story categories: Components, Modals, Transactions, UI.
┌─────────────────────────────────────────────────────────────────┐
│ Browser / Client │
└────────────┬────────────────────────────────────┬───────────────┘
│ │
│ HTTP/WebSocket │ HTTP
│ │
┌────────────▼────────────┐ ┌────────────▼───────────────┐
│ Next.js Frontend │ │ External Integrations │
│ (Port 3000) │ │ - SMTP / IMAP │
│ │ │ - S3-compatible storage │
│ - App Router │ │ - WebDAV storage │
│ - React 19 │ │ - Workbook files │
│ - MUI + Emotion │ │ - Telegram Bot │
│ - Real-time updates │ │ - OpenAI-compatible AI │
└────────────┬────────────┘ └─────────────────────────────┘
│
│ REST API (/api/v1)
│ WebSocket (Socket.IO)
│
┌────────────▼─────────────────────────────────────────────────────┐
│ NestJS Backend (Port 3001) │
│ │
│ ┌─────────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Auth & RBAC │ │ Parsing │ │ Classification │ │
│ │ - JWT │ │ - Kaspi │ │ - AI Auto-Cat │ │
│ │ - Sessions │ │ - Bereke │ │ - ML Rules │ │
│ │ - Permissions │ │ - CSV/XLSX │ │ - Learning │ │
│ └─────────────────┘ │ - Generic │ └──────────────────┘ │
│ │ - OCR │ │
│ ┌─────────────────┐ └──────────────┘ ┌──────────────────┐ │
│ │ Transactions │ │ Workspaces │ │
│ │ - CRUD │ ┌──────────────┐ │ - Multi-tenant │ │
│ │ - Dedup │ │ Reports & │ │ - Invitations │ │
│ │ - Search │ │ Dashboard │ │ - RBAC │ │
│ └─────────────────┘ │ - Cash flow │ └──────────────────┘ │
│ │ - Export │ │
│ ┌─────────────────┐ └──────────────┘ ┌──────────────────┐ │
│ │ Audit Log │ │ Storage & │ │
│ │ - Events │ ┌──────────────┐ │ Files │ │
│ │ - Rollback │ │ Integrations │ │ - Versions │ │
│ └─────────────────┘ │ - Gmail │ │ - Shared links │ │
│ │ - Drive │ └──────────────────┘ │
│ │ - Sheets │ │
│ └──────────────┘ │
└──────────┬────────────────────────────┬─────────────────────────┘
│ │
│ │
┌──────────▼────────────┐ ┌──────────▼────────────┐
│ PostgreSQL 14 │ │ Redis 7 │
│ │ │ │
│ - 59 TypeORM entities│ │ - Session cache │
│ - 90 migrations │ │ - Rate limiting │
│ - Full-text search │ │ - Bull queues │
└───────────────────────┘ └───────────────────────┘
┌─────────────────────────┐
│ Observability │
│ │
│ - Prometheus (metrics) │
│ - Grafana (dashboards) │
└─────────────────────────┘
- All endpoints are prefixed
/api/v1 - Global
JwtAuthGuard— use@Public()decorator to opt out for public endpoints - Global
ThrottlerGuard— 100 req/hour unauthenticated, 500 req/min authenticated @RequirePermission()+PermissionsGuardfor fine-grained RBAC checks@Audit()decorator on mutating operations for automatic audit-log recording@CurrentUser()and@WorkspaceId()parameter decorators for clean controller code- Structured JSON logging with per-request correlation IDs
- Global validation pipe with
class-validatorDTOs on all inputs - Max upload size: 10 MB · PDF parsing timeout: 30 s · Max parallel file uploads: 5
- TypeORM with
synchronize: false— schema changes only via numbered migrations - Soft delete on statements via
deletedAttimestamp - SHA-256
fileHashon statements for idempotent re-upload detection Idempotency-Keyheader supported on upload endpoints (stored inIdempotencyKeyentity)- Transaction fingerprinting for cross-statement duplicate detection
- 59 TypeORM entities covering all domain objects (see
backend/src/entities/)
Upload request
→ SHA-256 hash check (idempotency)
→ ParserFactory (detects bank + file type)
├── KaspiParser (Kaspi Bank PDF)
├── BerekeNewParser (Bereke Bank new format PDF)
├── BerekeOldParser (Bereke Bank legacy PDF)
├── ExcelParser (XLSX / XLS)
├── CsvParser (CSV)
├── GenericPdfParser (AI-assisted: OpenAI-compatible endpoint)
└── OCR Pipeline (Tesseract.js for images)
→ ImportSession created (status: processing)
→ Transactions persisted
→ ClassificationService (AI categorization + ML rules)
→ DeduplicationService (fingerprint check)
→ ImportSession status: complete
- JWT access tokens (1 h) + refresh tokens (30 d) stored per-device in
AuthSession - Refresh token rotation on every use; old tokens invalidated
- Bcrypt password hashing (12 rounds)
- RBAC enforced at controller level via guards — workspace roles enforced on every request
- Audit log covers all mutating operations with rollback support for critical changes
- CVE allowlists and license exceptions documented in
docs/security/ - See SECURITY.md for the full security policy
- Controllers are thin — all business logic in Services
- DTOs with
class-validatordecorators for all inputs - TypeORM migrations only — never
synchronize: true file_hash(SHA-256) for idempotent file operations- Structured JSON logging with correlation IDs
- All code comments and commit messages in English
- Biome formatter: 2 spaces, single quotes, semicolons, 100-char line width
make observability # Start Prometheus + Grafana
make observability-stop # Stop monitoring stack| Tool | URL | Purpose |
|---|---|---|
| Prometheus | http://localhost:9090 | Metrics collection and querying |
| Grafana | http://localhost:3002 | Pre-configured dashboards, default admin / admin |
| Metrics endpoint | http://localhost:3001/api/v1/metrics | Raw Prometheus metrics |
Configuration files are in observability/:
prometheus.yml— scrape config (polls/api/v1/metricsevery 15 s)grafana/— Grafana datasource and dashboard JSON files
# Build and start all services
docker compose up -d --build
# Check service status
docker compose ps
# Tail logs
docker compose logs -f
# Stop everything
docker compose downDocker Compose runs four services: postgres (PostgreSQL 14-alpine), redis (Redis 7-alpine), backend (NestJS), and frontend (Next.js). Data is persisted in named volumes (postgres_data, redis_data, backend_uploads).
Lumio can be deployed to Railway with automatic migrations on every deploy:
- Push to GitHub
- Connect Railway to your repository
- Set required environment variables (see Configuration)
- Deploys automatically on push to
main
See RAILWAY.md for step-by-step instructions.
| File | Purpose |
|---|---|
docker-compose.yml |
Production configuration |
docker-compose.dev.yml |
Development overrides (hot reload, source mounts) |
docker-compose.observability.yml |
Prometheus + Grafana monitoring stack |
| Document | Description |
|---|---|
| CONTRIBUTING.md | How to contribute — workflow, code style, PR process |
| SECURITY.md | Security policy, vulnerability reporting, disclosure process |
| CODE_OF_CONDUCT.md | Community guidelines |
| CHANGELOG.md | Release history |
| RAILWAY.md | Railway deployment step-by-step |
| docs/plans/ | 38 feature design and implementation plan documents |
| docs/CI/ | CI/CD pipeline documentation |
| docs/security/ | CVE allowlists and license exceptions |
Interactive API documentation: http://localhost:3001/api/docs (when backend is running).
We welcome contributions from the community.
- Report bugs — use the bug report template
- Suggest features — use the feature request template
- Improve documentation — fix typos, clarify guides, add examples
- Submit pull requests — fix bugs, add features, write tests
- Add bank parsers — support new banks by implementing the parser interface
- Translate — help with English / Russian / Kazakh i18n content
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Make changes and write or update tests
- Run
make lintandmake test— both must pass - Commit using Conventional Commits:
feat(statements): add CSV import support fix(auth): handle expired refresh token correctly docs: update quick-start instructions test(parsing): add golden tests for Bereke new format refactor(classification): extract learning rule application logic - Push and open a Pull Request against
main
- TypeScript strict mode throughout
- Biome for linting and formatting (2 spaces, single quotes, semicolons)
- Run
make lint(andmake formatif needed) before committing - Follow existing module patterns: thin controllers, logic in services, DTOs for all inputs
For detailed guidelines, see CONTRIBUTING.md.
- GitHub Discussions — ask questions, share ideas, get help
- GitHub Issues — report bugs or request features
- Star this repo — helps others discover the project
Security is a top priority. Please read SECURITY.md for supported versions, the vulnerability disclosure process, and security best practices.
Found a security issue? Report it privately through GitHub Security Advisories, not in public issues.
This project is licensed under the MIT License — see the LICENSE file for details.
Built on great open-source foundations:
NestJS · Next.js · PostgreSQL · TypeORM · Redis · MUI · Emotion · TanStack Table · ECharts · Tesseract.js · Socket.IO · Intlayer · driver.js · Biome · Storybook · and many more.
Made with care by the Lumio community