# Alemno Payments [![Python Version](https://img.shields.io/badge/python-3.14-blue?style=flat-square&logo=python)](file:///home/sortedcord/Projects/alemno_payments/pyproject.toml) [![FastAPI](https://img.shields.io/badge/FastAPI-0.139-009688?style=flat-square&logo=fastapi)](file:///home/sortedcord/Projects/alemno_payments/app/app.py) [![Test CI Status](https://github.com/sortedcord/alemno-payments/actions/workflows/tests.yml/badge.svg)](https://github.com/sortedcord/alemno-payments/actions/workflows/tests.yml) [![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-2.5-flash-lite` 75% cheaper than `gemini-3.5-flash-lite with no tangible decrease in performance) 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. Create a `docker-compose.yml` file to host the entire stack (or just clone the repo and directly run `docker compose up -d` : ```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 ```