Kenya-first ยท AI-native ยท Offline-first accounting platform
Built for Kenyan SMEs, accounting firms, and enterprise partners.
Features โข Architecture โข Tech Stack โข Quick Start โข API โข Testing โข Deployment
JengaBooks is a multi-tenant accounting SaaS purpose-built for the Kenyan market. It treats M-Pesa as a first-class citizen, automates KRA eTIMS submissions, survives offline environments, and gamifies accounting to drive daily engagement.
๐ฏ The 7 Pillars
- ๐ก๏ธ Immutable Audit & Uniqueness โ Postgres RLS, eTIMS serial enforcement, fiscal period controls
- ๐ก Offline-First Sync โ Optimistic locking, NTP clock validation, token-scoped sync
- ๐ Adaptive Data Ingestion โ M-Pesa & Bank CSV parsing with column fingerprinting
- ๐ค Agentic AI โ 5 DeepSeek agents with auto-fallback to Suspense Account
- ๐ Fault-Tolerant APIs โ Sliding window circuit breaker for KRA eTIMS
- ๐๏ธ Tenant Isolation โ Dynamic statement timeouts,
SKIP LOCKEDqueries- ๐ค Human-in-the-Loop โ Centralized DLQ, Kanban dashboard, XP gamification
|
|
|
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ JengaBooks Platform โ
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ
โ ๐ Web App (Vite) โ ๐ฑ Mobile App (Expo/RN) โ
โ React 18 + Tailwind โ WatermelonDB + NativeWind โ
โ React Router ยท Axiosโ Offline-first ยท Socket.io โ
โ โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ๐ฆ Shared Package (@jengabooks/shared) โ
โ Types ยท Zod Schemas ยท RBAC Permissions ยท Theme Tokens โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ ๐ NestJS 10 API (Stateless ยท RLS-enabled) โ
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ โ Auth Module โ โ Ledger Moduleโ โ AI Module โ โ
โ โ JWT ยท Cookieโ โ Fiscal Periodโ โ 5 DeepSeek Agentsโ โ
โ โโโโโโโโโโโโโโโค โโโโโโโโโโโโโโโโค โโโโโโโโโโโโโโโโโโโโค โ
โ โ M-Pesa โ โ eTIMS Module โ โ HITL Module โ โ
โ โ CSV Import โ โ Circuit Brkr โ โ Kanban ยท Reviews โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Reconciliation โ โ Batch/QA โ โ
โ โ Matching Engine โ โ Nightly Fraud Detection โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ
โ ๐๏ธ PostgreSQL 15 โ โก Redis 7 (AOF ยท RDB) โ
โ pgvector ยท RLS โ BullMQ ยท Rate Limiting โ
โ โ Circuit Breaker State โ
โโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| Layer | Technology | Purpose |
|---|---|---|
| Runtime | Node.js 20+ | JavaScript runtime with TypeScript strict mode |
| Backend | NestJS 10 | Modular server framework with DI, guards, interceptors |
| Database | PostgreSQL 15 + pgvector | Primary data store with Row-Level Security |
| ORM | Prisma 5 | Type-safe database access & migrations |
| Cache & Queue | Redis 7 + BullMQ | Job queues, rate limiting, circuit breaker state |
| AI | DeepSeek V4 | 5 specialized AI agents (Pro + Flash models) |
| Web Frontend | React 18 + Vite + TailwindCSS | SPA dashboard with responsive design |
| Mobile | Expo 51 + NativeWind | Cross-platform mobile app |
| Offline DB | WatermelonDB | Local-first sync database for mobile |
| Real-time | Socket.io | Live notifications & sync events |
| Auth | JWT + httpOnly Cookies | Stateless auth with refresh token rotation |
| Monorepo | Turborepo | Workspace orchestration & caching |
| Testing | Jest 29 + Supertest | Unit, integration, and E2E testing |
jengabooks/
โ
โโโ apps/
โ โโโ api/ # ๐ NestJS Backend
โ โ โโโ prisma/ # Schema, migrations, seeds
โ โ โโโ src/
โ โ โโโ common/ # Decorators, filters, interceptors
โ โ โโโ config/ # Database, Redis configuration
โ โ โโโ modules/ # Feature modules (13 total)
โ โ โ โโโ auth/ # JWT auth, refresh, switch-company
โ โ โ โโโ ledger/ # Journal entries, accounts, periods, recurring
โ โ โ โโโ mpesa/ # CSV/PDF import, categorization, file parser
โ โ โ โโโ etims/ # KRA invoice submission, circuit breaker
โ โ โ โโโ ai/ # 5 DeepSeek AI agents + batch service
โ โ โ โโโ hitl/ # Human-in-the-Loop reviews
โ โ โ โโโ gamification/# XP, levels, badges, streaks, leaderboard
โ โ โ โโโ reports/ # P&L, Balance Sheet, Cash Flow, comparisons
โ โ โ โโโ reconciliation/ # Transaction matching engine
โ โ โ โโโ sync/ # Offline sync endpoints
โ โ โ โโโ tenants/ # Multi-tenant management
โ โ โ โโโ wizard/ # Onboarding wizard
โ โ โ โโโ health-score/ # Business health scoring
โ โ โ โโโ workflow/ # Workflow dashboard logic
โ โ โโโ prisma/ # Prisma service module
โ โ โโโ queues/ # BullMQ queue definitions
โ โ โโโ e2e/ # End-to-end integration tests
โ โ
โ โโโ web/ # ๐ Web Frontend
โ โ โโโ src/
โ โ โโโ components/ # UI components, forms, layout
โ โ โโโ pages/ # Route pages (13 routes)
โ โ โโโ hooks/ # React Query hooks
โ โ โโโ stores/ # Zustand state stores
โ โ โโโ lib/ # API client, types, utils
โ โ
โ โโโ mobile/ # ๐ฑ Mobile App
โ โโโ src/
โ โโโ app/ # Expo Router pages
โ โโโ components/ # Mobile UI components
โ โโโ hooks/ # Mobile hooks
โ โโโ stores/ # Mobile state stores
โ โโโ lib/ # API client, offline DB
โ
โโโ packages/
โ โโโ shared/ # ๐ฆ Shared Package
โ โโโ src/ # Types, Zod schemas, RBAC, theme, helpers
โ
โโโ plans/ # ๐ Architecture plans & audit docs
โโโ docker-compose.yml # ๐ณ Local dev (Postgres + Redis)
โโโ turbo.json # โก Turborepo configuration
โโโ package.json # ๐ Monorepo root
Choose your environment below.
Best for: Linux workstations, CI/CD runners, production servers.
| Tool | Version | Check |
|---|---|---|
| Node.js | >= 20.0.0 | node --version |
| npm | 11.x | npm --version |
| PostgreSQL | 15+ | psql --version |
| Redis | 7+ | redis-cli --version |
# 1. Clone & install
git clone https://github.com/Jpkoech30/jengabooks.git
cd jengabooks
npm install
# 2. Configure environment
cp .env.example apps/api/.env
# 3. Create the database
sudo -u postgres psql -c "CREATE DATABASE jengabooks;"
# 4. Run database migrations
cd apps/api && npx prisma migrate dev
# 5. Seed demo data
npx ts-node prisma/seed.ts
# 6. Start development (from root)
cd ../.. && npm run devConnection config (.env / apps/api/.env):
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/jengabooks?schema=public"
REDIS_HOST=localhost
REDIS_PORT=6379Best for: Windows workstations with Docker Desktop.
| Tool | Version | Check |
|---|---|---|
| Node.js | >= 20.0.0 | node --version |
| npm | 11.x | npm --version |
| Docker Desktop | Latest | docker --version |
# 1. Clone & install
git clone https://github.com/Jpkoech30/jengabooks.git
cd jengabooks
npm install
# 2. Configure environment
cp .env.example apps/api/.env
# 3. Start infrastructure (Docker)
docker-compose up -d
# 4. Run database migrations
cd apps/api && npx prisma migrate dev
# 5. Seed demo data
npx ts-node prisma/seed.ts
# 6. Start development (from root)
cd ../.. && npm run devConnection config (.env / apps/api/.env):
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/jengabooks?schema=public"
REDIS_HOST=localhost
REDIS_PORT=6379Docker Desktop on Windows maps container ports to
localhostby default โ no special config needed.
Best for: Windows workstations running services natively in WSL without Docker.
| Tool | Version | Check | Where |
|---|---|---|---|
| Node.js | >= 20.0.0 | node --version |
Windows |
| npm | 11.x | npm --version |
Windows |
| WSL distro | Ubuntu 24.04+ | wsl -l -v |
Windows |
| PostgreSQL | 15+ | psql --version |
WSL (inside distro) |
| Redis | 7+ | redis-cli --version |
WSL (inside distro) |
โ ๏ธ Important: Node.js runs on Windows, while PostgreSQL and Redis run inside WSL. This meanslocalhostfrom Node.js on Windows does not reliably forward to WSL services. You must use the WSL instance's network IP.
# Inside WSL โ Install PostgreSQL
sudo apt update
sudo apt install -y postgresql postgresql-client redis-server
# Start services
sudo service postgresql start
sudo service redis-server start
# Configure PostgreSQL for external connections
sudo sed -i "s/#listen_addresses = 'localhost'/listen_addresses = '*'/" /etc/postgresql/15/main/postgresql.conf
sudo sed -i "s/127.0.0.1\/32/0.0.0.0\/0/" /etc/postgresql/15/main/pg_hba.conf
sudo service postgresql restart
# Create the database
sudo -u postgres psql -c "CREATE DATABASE jengabooks;"# From Windows PowerShell
wsl -- ip addr | findstr "inet "
# Look for an address like 192.168.1.XXX (not 127.0.0.1 or inet6)# On Windows โ Clone & install
git clone https://github.com/Jpkoech30/jengabooks.git
cd jengabooks
npm install
# Configure .env with the WSL IP found above
# Edit .env and apps/api/.envConnection config (.env / apps/api/.env):
# โ Will NOT work:
# DATABASE_URL="postgresql://postgres:postgres@localhost:5432/jengabooks"
# โ
Use WSL's real IP โ disable SSL (local Postgres doesn't need it):
DATABASE_URL="postgresql://postgres:postgres@192.168.1.180:5432/jengabooks?schema=public&sslmode=disable"
REDIS_HOST=localhost
REDIS_PORT=6379Why
localhostfails: Windows' WSL2 port forwarding is unreliable on some configurations. The WSL instance gets a virtual IP that is stable within a session butlocalhostdoes not always forward correctly. Direct IP connection with SSL disabled is the confirmed working configuration.
cd apps/api
npx prisma migrate dev
npx ts-node prisma/seed.ts
cd ../..
npm run dev# From the project root โ tests both WSL IP and localhost
node scripts/test-conn2.js
# Expected output:
# โ WSL IP: [{"db":"jengabooks","ver":"PostgreSQL 18.4..."}]
# โ localhost: Can't reach database server at localhost:5432The dev launcher script handles everything automatically:
.\scripts\dev.ps1What it does:
- Starts WSL (if not running)
- Starts PostgreSQL and Redis in WSL
- Auto-detects the WSL IP and injects it into
DATABASE_URLat runtime - Waits for PostgreSQL and Redis to be ready (retries up to 15 times)
- Checks optional 3rd party API connectivity (DeepSeek, KRA eTIMS)
- Starts the JengaBooks dev server
Expected output:
=== JengaBooks Dev Environment ===
[1/5] Checking WSL status...
โ WSL is ready
[2/5] Starting PostgreSQL...
โ PostgreSQL already running
[3/5] Starting Redis...
โ Redis already running
[4/5] Detecting WSL IP and configuring connection...
โ DATABASE_URL configured with WSL IP
โ postgresql://postgres:postgres@192.168.1.180:5432/jengabooks?schema=public&sslmode=disable
[5/5] Verifying service connectivity...
โ PostgreSQL is ready
โ Redis is ready
- DeepSeek AI API: skipped (no API key configured)
- KRA eTIMS API: skipped (no KRA_API_URL configured)
โ
All services are ready! Starting application...
Options:
# Skip the service health check (faster startup)
.\scripts\dev.ps1 -SkipServiceCheck
# Skip WSL steps entirely (for Docker or Linux)
.\scripts\dev.ps1 -SkipWsl
# Specify a different WSL distro
.\scripts\dev.ps1 -WslDistro Ubuntu-22.04How IP injection works: The script runs
node scripts/wsl-ip.js --exportwhich outputs$env:DATABASE_URL="postgresql://...@<detected-ip>...". This env var overrides whatever is in the.envfile, so you never need to edit.envwhen the WSL IP changes.
WSL's IP can change after a reboot. If you're not using dev.ps1, find the new IP:
wsl -- ip addr | findstr "inet "Then update DATABASE_URL in both:
Or better, use the automated script:
# This detects the IP and exports the correct DATABASE_URL for the current session
$env:DATABASE_URL = "$(node scripts/wsl-ip.js --export)"
npm run dev| Role | Password | |
|---|---|---|
| Firm Owner | admin@jengabooks.com |
password123 |
The project has 234 tests across 24 test suites.
| Type | Count | What It Tests |
|---|---|---|
| Unit (pure logic) | ~120 | Static methods, DTO validation, calculations, level thresholds, file parsing |
| Integration (mocked DB) | ~100 | Services with mocked Prisma: auth, ledger, HITL, reports, reconciliation |
| E2E (HTTP + real DB) | 14 | Full request/response cycle: register, login, auth flows |
| Module | Tests | Key Features Tested |
|---|---|---|
| Auth | 16 | Login, register, refresh, profile, DTO validation |
| Ledger | 34 | Accounts CRUD, journal entries, trial balance, serial numbers, recurring entries, lockdown |
| eTIMS | 22 | Invoices, VAT, KRA PIN validation, submissions, circuit breaker |
| M-Pesa | 75 | CSV parsing, file formats, bank templates, AI agents, auto-post, bulk approve, upload validation |
| HITL | 7 | Create, assign, resolve with XP |
| Reports | 24 | P&L, Balance Sheet, Cash Flow, period comparison, duplicates, share tokens |
| Gamification | 20 | Level calculation, sync streaks, early bird, level-up detection |
| Tenants | 6 | CRUD, member management, invite |
| Wizard | 6 | Progress tracking, step completion |
| AI Batch | 5 | Nightly fraud detection |
| Exception Filter | 6 | Prisma errors, HTTP errors |
| Circuit Breaker | 6 | State transitions, timeout, reset |
| Confidence Tier | 8 | 3-tier confidence logic |
| Reconciliation | 11 | Matching engine (exact/fuzzy), status |
| Workflow | 5 | 5-phase progress calculation |
| Total | 234 |
# All unit + integration tests
cd apps/api && npm test
# Watch mode
cd apps/api && npm run test:watch
# With coverage
cd apps/api && npm run test:cov
# Specific module
cd apps/api && npx jest --verbose --testPathPattern="mpesa"
# E2E tests (requires database)
cd apps/api && npx jest --config jest-e2e.config.tsAll endpoints are prefixed with /api/v1 and protected with JWT authentication (except login & register).
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/auth/login |
Sign in with email + password (5 req/min) |
POST |
/api/v1/auth/register |
Create account + company (3 req/min) |
POST |
/api/v1/auth/refresh |
Refresh JWT token |
POST |
/api/v1/auth/logout |
Clear session |
GET |
/api/v1/auth/profile |
Get user profile + memberships |
POST |
/api/v1/auth/switch-company |
Switch active company |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/ledger/accounts |
List chart of accounts |
POST |
/api/v1/ledger/accounts |
Create account |
GET |
/api/v1/ledger/entries |
List journal entries |
POST |
/api/v1/ledger/entries |
Create journal entry |
POST |
/api/v1/ledger/transactions/income |
Quick income entry |
POST |
/api/v1/ledger/transactions/expense |
Quick expense entry |
GET |
/api/v1/ledger/trial-balance |
Trial balance report |
GET |
/api/v1/ledger/periods |
Fiscal periods |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/mpesa/import |
Import CSV/XLSX/PDF transactions |
GET |
/api/v1/mpesa |
List transactions |
POST |
/api/v1/mpesa/:txId/map |
Map to account |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/etims/invoices |
List invoices |
POST |
/api/v1/etims/invoices |
Create invoice |
POST |
/api/v1/etims/submissions/:id/submit |
Submit to KRA |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/ai/process |
Trigger AI processing |
POST |
/api/v1/ai/feedback |
Submit feedback |
POST |
/api/v1/ai/batch/fraud-detection |
Manual fraud batch run |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/hitl |
List reviews (with filters) |
POST |
/api/v1/hitl |
Create review |
POST |
/api/v1/hitl/:id/assign |
Claim task |
POST |
/api/v1/hitl/:id/resolve |
Resolve with action + XP |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/gamification/profile |
User XP, level, badges |
GET |
/api/v1/gamification/badges |
Earned & available badges |
GET |
/api/v1/gamification/leaderboard |
Company ranking |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/reports/profit-loss |
Profit & Loss statement |
GET |
/api/v1/reports/balance-sheet |
Balance sheet |
GET |
/api/v1/reports/trial-balance |
Trial balance |
GET |
/api/v1/reports/cash-flow |
Cash flow statement |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/workflow |
Monthly workflow progress (all 5 phases) |
| Level Range | Title | XP Required |
|---|---|---|
| 1โ5 | ๐ช Apprentice | 0 โ 1,000 |
| 6โ10 | ๐ Bookkeeper | 1,500 โ 4,500 |
| 11โ20 | ๐งฎ Accountant | 5,500 โ 19,000 |
| 21โ30 | ๐ผ Finance Pro | 21,000 โ 43,500 |
| 31โ50 | ๐ Business Master | 46,500 โ 122,500 |
| Badge | Trigger | XP |
|---|---|---|
| ๐ Accountant | Set up Chart of Accounts (5+ accounts) | 25 |
| ๐ฑ M-Pesa Connected | M-Pesa transactions exist | 25 |
| ๐ Data Driven | Import first M-Pesa CSV | 25 |
| ๐ฐ First Income | Record first income | 25 |
| ๐ณ First Expense | Record first expense | 25 |
| ๐ก๏ธ Tax Compliant | Submit first eTIMS invoice (ACCEPTED) | 50 |
| ๐ฅ Team Player | Invite a team member | 25 |
| ๐ Analyst | Generate first report (5+ entries) | 25 |
| ๐ค Trust the AI | Bulk approve 10+ AI-categorized transactions | 25 |
| Mechanic | Trigger | Reward |
|---|---|---|
| Sync Streak | Consecutive days of activity | Badge at 7/30/90 days |
| Early Bird | Submit reports before 5th of month | +50 XP |
| Flawless Finisher | Complete lockdown with 0 errors | Trophy badge |
| Role | Level | Description |
|---|---|---|
SUPER_ADMIN |
๐ด Platform | Full system access, DevOps |
FIRM_OWNER |
๐ฃ Partner | Accounting firm ownership |
TENANT_ADMIN |
๐ Admin | Tenant internal administration |
ACCOUNTANT |
๐ต Staff | Daily accounting operations |
SME_OWNER |
๐ข Business | SME business owner view |
AUDITOR |
๐ก External | Read-only audit access |
BANK_OFFICER |
โช Loan | Loan portfolio view |
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
โ | โ | PostgreSQL connection string |
PORT |
โ | 3000 |
API server port |
JWT_SECRET |
โ | โ | JWT signing secret |
REDIS_HOST |
โ | localhost |
Redis host |
REDIS_PORT |
โ | 6379 |
Redis port |
DEEPSEEK_API_KEY |
โ | Required for AI features | |
KRA_API_URL |
โ | โ | KRA eTIMS API endpoint (mock used if unset) |
KRA_CLIENT_ID |
โ | Required for eTIMS | |
CORS_ORIGIN |
โ | http://localhost:5173 |
Allowed CORS origin |
docker-compose -f docker-compose.prod.yml up -dVultr Load Balancer
โโโ Node.js VM 1 (API + Web)
โโโ Node.js VM 2 (API + Web)
โโโ Node.js VM n (Workers)
Vultr Managed PostgreSQL โ Replica set
Vultr Managed Redis โ Cluster
Vultr Object Storage โ Backups
# Required for production
NODE_ENV=production
JWT_SECRET=<strong-random-secret>
DATABASE_URL=postgresql://user:password@vultr-db:5432/jengabooks
# For AI features (optional, degrades gracefully if unset)
DEEPSEEK_API_KEY=sk-your-key
KRA_API_URL=https://kra-api.go.ke/v1
KRA_CLIENT_ID=your-client-id| Document | Location | Description |
|---|---|---|
| Audit Report | plans/jengabooks-comprehensive-audit.md |
Full project audit with 24 issues |
| Test Strategy | plans/jengabooks-test-strategy.md |
158-test plan across 5 phases |
| Workflow Spec | plans/acct-workflow-gap-analysis.md |
Kenyan accounting workflow specification |
| Gap Analysis | plans/acct-workflow-roadmap.md |
6-phase implementation roadmap |
| Pricing Spec | plans/accontingspecs.md |
Full accounting feature specification |
- Fork the repository
- Create a feature branch (
git checkout -b feat/amazing-feature) - Commit changes (
git commit -m 'feat: add amazing feature') - Push to branch (
git push origin feat/amazing-feature) - Open a Pull Request
Before submitting: Run the test suite and ensure all tests pass.
cd apps/api && npm testPrivate ยท JengaBooks Inc. ยฉ 2026
Built with ๐ for Kenyan businesses
Nairobi ยท Mombasa ยท Kisumu ยท Eldoret