From 9c7c7b286e527dc8481ba68bc3f02b738946d978 Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Fri, 3 Jul 2026 08:56:57 +0530 Subject: [PATCH] docs: Update readme --- README.md | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/README.md b/README.md index 4f85661..b9f9155 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,134 @@ [![Lint CI Status](https://github.com/sortedcord/alemno-payments/actions/workflows/lint.yml/badge.svg)](https://github.com/sortedcord/alemno-payments/actions/workflows/lint.yml) [![Docker CI Status](https://github.com/sortedcord/alemno-payments/actions/workflows/docker.yml/badge.svg)](https://github.com/sortedcord/alemno-payments/actions/workflows/docker.yml) [![Security CI Status](https://github.com/sortedcord/alemno-payments/actions/workflows/security.yml/badge.svg)](https://github.com/sortedcord/alemno-payments/actions/workflows/security.yml) + +An asynchronous transactional data cleaning, validation, and LLM powered categorization pipeline. + +## 🚀 Features + +- Reads multi format dates and handles missing transaction IDs by auto generating unique fallbacks, and parses messy amounts with currency signs and commas cleanly. +- Offloads validation, spend conversion, and analysis to a Celery background worker backed by Redis. +- Integrates with the Google GenAI SDK (`gemini-3.5-flash`) using structured output schemas to categorize transaction records into database-defined custom categories. +- Uses Redis caching with a 24-hour TTL to store live exchange rates, falling back to a hardcoded rate of `93.0` if offline. +- Statistical Anomaly Detection: + - Flags transactions exceeding 3 times the account's median spend as statistical outliers. + - Flags domestic transactions in USD currency. + - Flags high value transactions and transactions with fraud indicative keywords. + +## 🐳 Self Hosting & Deployment + +We publish production-ready images to **GitHub Container Registry (GHCR)**. You can pull them directly or run them via Docker Compose. + +### Option A: Docker Compose (Using Pre-built Images) + +Create a `docker-compose.yml` file to self-host the entire stack: + +```yaml +version: "3.8" + +services: + db: + image: postgres:16-alpine + container_name: alemno_db + ports: + - "5432:5432" + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: alemno_payments + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d alemno_payments"] + interval: 5s + timeout: 5s + retries: 5 + + redis: + image: redis:7-alpine + container_name: alemno_redis + ports: + - "6379:6379" + + web: + image: ghcr.io/sortedcord/alemno-payments/web:latest + container_name: alemno_web + ports: + - "3000:3000" + environment: + - POSTGRES_HOST=db + - POSTGRES_PORT=5432 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=alemno_payments + - REDIS_HOST=redis + - REDIS_PORT=6379 + - REDIS_DB=0 + - GEMINI_API_KEY=your-gemini-api-key + depends_on: + db: + condition: service_healthy + redis: + condition: service_started + + worker: + image: ghcr.io/sortedcord/alemno-payments/worker:latest + container_name: alemno_worker + environment: + - POSTGRES_HOST=db + - POSTGRES_PORT=5432 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=alemno_payments + - REDIS_HOST=redis + - REDIS_PORT=6379 + - REDIS_DB=0 + - GEMINI_API_KEY=your-gemini-api-key + depends_on: + db: + condition: service_healthy + redis: + condition: service_started + +volumes: + postgres_data: +``` + +Launch the stack: + +```bash +docker compose up -d +``` + +### Option B: Direct Pull (Manual Run) + +You can pull and run individual containers manually from GHCR: + +1. **Pull the images**: + + ```bash + docker pull ghcr.io/sortedcord/alemno-payments/web:latest + docker pull ghcr.io/sortedcord/alemno-payments/worker:latest + ``` + +2. **Run Web (FastAPI API Server)**: + + ```bash + docker run -d \ + --name alemno_web \ + -p 3000:3000 \ + -e POSTGRES_HOST=your-db-host \ + -e REDIS_HOST=your-redis-host \ + -e GEMINI_API_KEY=your-gemini-api-key \ + ghcr.io/sortedcord/alemno-payments/web:latest + ``` + +3. **Run Worker (Celery Processing Worker)**: + ```bash + docker run -d \ + --name alemno_worker \ + -e POSTGRES_HOST=your-db-host \ + -e REDIS_HOST=your-redis-host \ + -e GEMINI_API_KEY=your-gemini-api-key \ + ghcr.io/sortedcord/alemno-payments/worker:latest celery -A app.worker.celery_app worker --loglevel=info + ```