Skip to content

sachncs/underwrite

Repository files navigation

Underwrite

Indian Lending Platform (Beta) — nano-service event-driven architecture with Ed25519 cryptographic attestation.

Python License CI PyPI Stars

A nano-service platform for Indian retail lending. Designed for RBI Digital Lending Guidelines compliance, with DPDPA 2023 data protection and 30+ independently deployable services connected by an event bus with Ed25519 cryptographic attestation.

Beta — not yet production-ready. Known gaps include stubbed PAN / Aadhaar / CKYC / CIBIL integrations, no video KYC, stubbed e-NACH / UPI Autopay mandate collection, basic RBAC only, undocumented disaster-recovery procedures, and rough developer experience (no prebuilt Docker images, no Helm charts, manual service wiring required). See Status below.

Features

  • 31 nano-services — KYC / AML (PAN + Aadhaar Verhoeff), CIBIL / Experian / Equifax credit bureau, CKYC registry, RBI rate-capped pricing, KFS generation, DPDPA consent + DSR, Razorpay PG, risk scoring, fraud detection, collections, recovery, notifications, governance
  • Event-driven — Typed events with Ed25519 signatures, saga orchestration, dead-letter queues, circuit breakers
  • Pluggable backends — Memory / filesystem / Postgres stores; local / SQS / Modal event bus; console / OTLP tracing
  • 1167 tests — Rate limiting, idempotency guards, PII redaction, Prometheus metrics
  • DPDPA 2023 + RBI DLG aligned — Per-product rate caps, all-in-cost APR, penal-interest cap, KFS cooling-off, consent lifecycle, DSR fulfillment, breach notification, auto-purge

Status

This is an early-stage beta. It is not production-ready. Known gaps:

  • Real API integrations for PAN (NSDL/ITD), Aadhaar (UIDAI), CKYC, CIBIL, and AML blocklists are stubbed — format validation only.
  • Video KYC provider integration is not yet implemented.
  • e-NACH / UPI Autopay mandate collection is stubbed (event definitions exist; Razorpay integration skeleton present).
  • No RBAC beyond basic access control.
  • No disaster recovery procedures documented.
  • Developer experience is rough — no pre-built Docker images, no Helm charts, manual service wiring required.

If you need a production-grade Indian lending platform today, underwrite is not the right choice.

Installation

From PyPI

pip install underwrite
pip install "underwrite[risk,serve,postgres,otlp,vault,aws]"

From source

git clone https://github.com/sachncs/underwrite.git
cd underwrite
./setup.sh
source .venv/bin/activate
pip install -e ".[dev,risk,serve,postgres,otlp,vault,aws]"
Extra Provides
risk NumPy, scikit-learn — ML risk models
serve Uvicorn, FastAPI — HTTP server
postgres psycopg2-binary — Postgres state store
otlp OpenTelemetry SDK — distributed tracing
vault hvac — HashiCorp Vault secrets
aws boto3 — SES, SQS, Secrets Manager
security bandit, pip-audit — vulnerability scanning
dev pytest, ruff, mypy, hypothesis, testcontainers

Prerequisites

  • Python 3.10+
  • PostgreSQL 14+ (optional — memory / filesystem backends work without it)
  • Docker (optional — for docker compose up with Postgres + Vault + OTLP)

Quick Start

git clone https://github.com/sachncs/underwrite.git
cd underwrite
./setup.sh
source .venv/bin/activate
python -m pytest tests/ --tb=short -q   # 1167 tests

To run an Indian lending scenario:

underwrite init
# edit underwrite.json to enable: mechanism,audit,risk,fraud,compliance,consent,credit_bureau,kfs,pricing,underwriter,decision
underwrite run mechanism audit risk fraud compliance consent credit_bureau kfs pricing underwriter decision
# In another terminal:
python docs/examples/indian_lending.py
# See docs/QUICKSTART.md for the full walkthrough

CLI

underwrite

Commands:
  init [PATH]              Create default config
  run <service>...         Start one or more services
  list                     List all 31 nano-services
  identity <service>       Generate Ed25519 keypair
  health                   System health status
  dlq [--replay] [--max N] Show or replay dead-letter queue
  metrics                  Metrics snapshot (Prometheus-format on /v1/metrics)
  migrate                  Run pending schema migrations
  serve                    Start HTTP daemon (requires [serve] extra)

HTTP API (with underwrite serve)

Endpoint Method Description
/healthz GET Liveness probe
/readyz GET Readiness probe
/v1/health GET Full system health
/v1/metrics GET Prometheus-format metrics
/v1/publish POST Publish a domain event

Authentication via Authorization: Bearer <token> when started with --require-auth.

Configuration

Configure via JSON file (created with underwrite init), env vars, or both (env vars override). See .env.example for every supported variable — including RBI pricing caps, AML thresholds, credit-bureau API keys, Razorpay credentials, and DPDPA retention periods.

Setting Env Variable Default Description
State backend UNDERWRITE_STORE_BACKEND memory memory / file / postgres
Store DSN UNDERWRITE_STORE_DSN e.g. postgresql://user:pass@localhost:5432/underwrite
Personal-loan rate cap UNDERWRITE_PERSONAL_LOAN_RATE_CAP 0.28 RBI cap
Penal interest cap UNDERWRITE_PENAL_INTEREST_CAP 0.24 RBI cap
Bearer auth UNDERWRITE_REQUIRE_AUTH false Require bearer token on /v1/*

Architecture

Each nano-service extends NanoService with a single handle(event: Event) -> None:

  1. Subscribe — declare interest in event types via config
  2. Dispatch — handler wrapped with authz, idempotency, tracing, metrics, timeout
  3. Emitself.emit(event) signs with Ed25519 and publishes to the bus
  4. Persist — state via Store (MemoryStore / FileStore / PostgresStore)

Cross-cutting concerns (authz, tracing, metrics, sagas, supervisor, circuit breaker) are injected by the bus and runtime — not inherited by services.

Principle Implementation
Event provenance Ed25519 signature on every event, verified before dispatch
Fault isolation DLQ with replay; per-subscriber circuit breaker; per-handler timeout
Security-first No str(default) in signing; joblib gated by env var; bearer auth; PII redaction
RBI compliance Per-product rate caps, all-in-cost APR, penal interest limit, KFS cooling-off
DPDPA compliance Consent lifecycle, DSR fulfillment, breach notification, auto-purge

API

Symbol Type Description
underwrite.NanoService ABC Base class; implement handle(event)
underwrite.__bus__ module Event bus — pub/sub, DLQ, rate limiter
underwrite.__store__ module State store — MemoryStore / FileStore / PostgresStore
underwrite.__saga__ module Saga orchestrator
underwrite.__authz__ module Access control + Ed25519 verification
underwrite.__identity__ module Ed25519 key management
underwrite.__events__ module 105+ event types
underwrite.__pii__ module PII redaction (Aadhaar, PAN, etc.)
underwrite.__config__ module Pydantic configuration (28 sections)
underwrite.__cli__:main function underwrite CLI entry
services.* packages 31 nano-services (mechanism, compliance, pricing, kfs, consent, dsr, credit_bureau, razorpay, risk, fraud, audit, npa, recovery, …)

Project Structure

underwrite/
├── underwrite/                    # Source (90+ modules, fully typed)
│   ├── __config__.py              # Pydantic configuration (28 sections)
│   ├── __bus__.py                 # Event bus — pub/sub, DLQ, rate limiter
│   ├── __store__.py               # State store — memory / file / postgres
│   ├── __saga__.py                # Saga orchestrator
│   ├── __authz__.py               # Access control & Ed25519 verification
│   ├── __identity__.py            # Ed25519 key management
│   ├── __events__.py              # 105+ event types
│   ├── __pii__.py                 # PII redaction (Aadhaar, PAN, etc.)
│   └── services/                  # 31 nano-services
│       ├── base.py                # NanoService ABC
│       ├── mechanism/             # Delegation state machine (core)
│       ├── compliance/            # KYC/AML — PAN category, Aadhaar Verhoeff, risk score
│       ├── pricing/               # RBI caps, APR, EMI, penal interest, foreclosure
│       ├── kfs/                   # Key Fact Statement generation
│       ├── consent/               # DPDPA consent lifecycle
│       ├── dsr/                   # Data Subject Rights fulfillment
│       ├── credit_bureau/         # CIBIL/Experian/Equifax + CKYC
│       ├── razorpay/              # Payment gateway integration
│       ├── risk/                  # ML risk scoring
│       ├── fraud/                 # Fraud detection
│       ├── audit/                 # Event ledger (PII-redacted)
│       ├── npa/                   # Asset classification (SMA/NPA/DLG)
│       ├── recovery/              # Default recovery (store-backed)
│       └── ...                    # 17 more services
├── tests/                         # 58 test files, 1167 tests
└── docs/                          # 9 updated docs for Indian market

Documentation Index

Area Documents
Getting Started Installation · Quickstart (Indian scenario) · Configuration · Env Vars
Architecture Overview · System Design · Domain Model · Design Decisions
Development Guide · Testing · Debugging · Code Style · Build
Operations Deployment · Operations · Observability · Security (DPDPA) · Performance
Reference API · Troubleshooting · FAQ · Glossary
Project Contributing · Maintenance · Roadmap

Development

pip install -e ".[dev,risk,serve,postgres,otlp,vault,aws]"
pytest tests/ --tb=short -q
ruff check underwrite/
ruff format underwrite/
mypy underwrite/
bandit -r underwrite/
pip-audit
mutmut run                     # mutation testing (optional)

Testing

pytest tests/ --tb=short -q
pytest tests/ -x --timeout=30
pytest --cov=underwrite --cov-report=term-missing

The suite contains 1167 tests across rate limiting, idempotency, PII redaction, RBAC, saga orchestration, and Prometheus metrics.

Build

pip install build
python -m build

Release

pytest && ruff check underwrite/ && mypy underwrite/ && bandit -r underwrite/
# Bump version (setuptools_scm derives the version from git tags)
git tag vX.Y.Z && git push origin vX.Y.Z
# .github/workflows/release.yml publishes to PyPI via trusted publishing

Tech Stack

Category Technology
Language Python ≥ 3.10
Cryptography cryptography (Ed25519)
CLI Typer
Config Pydantic
State store Memory / File / Postgres (psycopg2-binary)
Tracing OpenTelemetry SDK + OTLP
HTTP FastAPI + Uvicorn
Secrets HashiCorp Vault (hvac)
Cloud boto3 (AWS), google-cloud-storage (GCS), modal
ML risk NumPy, scikit-learn
Lint / format ruff
Type check mypy
Tests pytest, pytest-asyncio, pytest-cov, hypothesis, testcontainers
Security bandit, pip-audit
Mutation testing mutmut

Roadmap

  • v0.8.x — Current beta: 31 nano-services, 1167 tests, Ed25519 event provenance, RBI/DPDPA-aligned defaults.
  • v0.9.0 — Planned: real PAN (NSDL/ITD) and Aadhaar (UIDAI) integrations; CKYC live lookup; CIBIL production keys.
  • v1.0.0 — Planned: video KYC; e-NACH / UPI Autopay mandate collection; full RBAC; documented DR procedures; Docker images + Helm charts.

Contributing

See CONTRIBUTING.md.

Code of Conduct

This project follows the Contributor Covenant v2.1.

Security

Report vulnerabilities to sachncs@gmail.com — see SECURITY.md.

License

MIT © 2026 Sachin — not legal advice. Consult a qualified attorney before deploying in a regulated environment.

About

Event-driven delegated underwriting for unsecured lending, with typed signed events, saga orchestration, ML risk scoring, and production-ready observability.

Topics

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages