Skip to content

willejs/mini-ledger

Repository files navigation

Mini-Ledger

This is just a fun project to demonstrate gitless gitops practices. A high-performance double-entry financial ledger built with Go, CockroachDB, and Redpanda.

Todo

  • Core ledger service with accounts and transactions
  • Kubernetes GitOps deployment with Flux CD
  • Integration tests with local Kafka and CockroachDB via test containers
  • e2e tests with account and transaction flows
  • Add Otel Telemetry and metrics + small LGTM stack in k8s
  • Documentation and examples
  • CI/CD pipeline to build, test and publish Docker and OCI artifacts
  • Abstract away platform components defined in kustomize (DB, messaging) to another repo, and use as a library
  • Dry up tiltfile, and include basic bootstrap tasks as a library
  • Production deployment guides

Features

  • Double-entry accounting with strict balance validation
  • CQRS + Event Sourcing architecture
  • Idempotent transactions via idempotency keys
  • Multi-ledger tenancy support
  • OpenAPI-first API design with generated types
  • Hexagonal architecture for testability and maintainability
  • Kubernetes-native deployment with GitOps via Flux CD
  • Runs locally with Tilt for rapid development - task k8s-up

Quick Start

Prerequisites

  • Go 1.23+
  • Docker & Docker Compose
  • Task - Task runner (replaces Make)
  • ctlptl - For managing local clusters
  • kind - Kubernetes in Docker
  • Tilt - Local Kubernetes development
  • Helm - Kubernetes package manager
  • Flux CLI - GitOps toolkit

Install Prerequisites (macOS)

brew install go docker kind tilt-dev/tap/tilt tilt-dev/tap/ctlptl helm go-task fluxcd/tap/flux

Verify Installation

task check  # Checks all prerequisites are installed

If you have any issues, refer to the .tool-versions file for specific version requirements.

Development

Option 1: Kubernetes (Recommended)

Run the full stack in a local Kind cluster with Tilt + Flux GitOps:

# Create cluster and start everything
task k8s:up

# Or step by step:
ctlptl apply -f ctlptl.yaml  # Create Kind cluster with local registry
tilt up                       # Bootstrap Flux and start GitOps

This will:

  1. Create a Kind cluster with a local container registry
  2. Install Flux CD via Helm
  3. Deploy manifests via OCI artifacts (GitOps)
  4. Deploy CockroachDB via HelmRelease
  5. Deploy Redpanda (Kafka-compatible) via HelmRelease
  6. Build and deploy the ledger service with live reload
  7. Run E2E tests automatically after deployment

Access:

  • Tilt UI: http://localhost:10350
  • Check Flux status: task flux:status
  • Force reconciliation: task flux:reconcile

Cleanup:

task k8s:down     # Stop Tilt
task k8s:delete   # Delete cluster and registry

Option 2: Local Binary (for development)

Run the service directly (requires external CockroachDB and Redpanda):

task build:ledger
./bin/ledger

Testing

# Run all tests
task test

# Run short tests (skip e2e)
task test:short

# Run E2E tests in Kubernetes
task test:e2e:k8s

# Generate coverage report
task test:coverage

API Usage

Create an Account

curl -X POST http://localhost:8080/v1/accounts \
  -H "Content-Type: application/json" \
  -d '{
    "ledger_id": "550e8400-e29b-41d4-a716-446655440000",
    "currency_code": "USD"
  }'

Create a Transaction

curl -X POST http://localhost:8080/v1/transactions \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "X-Client-ID: my-app" \
  -d '{
    "ledger_id": "550e8400-e29b-41d4-a716-446655440000",
    "currency": "USD",
    "legs": [
      {"account_id": "ACCOUNT_1_UUID", "direction": "DEBIT", "amount_minor": 10000},
      {"account_id": "ACCOUNT_2_UUID", "direction": "CREDIT", "amount_minor": 10000}
    ]
  }'

Health Checks

curl http://localhost:8080/health  # Liveness
curl http://localhost:8080/ready   # Readiness

Project Structure

mini-ledger/
├── api/
│   ├── openapi/          # OpenAPI spec (source of truth)
│   └── proto/            # gRPC protobuf definitions
├── cmd/
│   ├── ledger/           # Main service
│   └── projector/        # CQRS projector
├── internal/
│   ├── adapter/          # Infrastructure adapters
│   │   ├── http/         # HTTP handlers (OpenAPI generated)
│   │   ├── grpc/         # gRPC handlers
│   │   ├── repository/   # Database repositories
│   │   └── messaging/    # Kafka producers/consumers
│   ├── application/      # Application services
│   ├── domain/           # Domain entities and ports
│   └── config/           # Configuration
├── migrations/           # Database migrations
├── deploy/               # Kubernetes manifests
├── Tiltfile              # Tilt configuration
└── docker-compose.yml    # Docker Compose config

Documentation

  • Architecture - Detailed architecture documentation
  • RFC - Original design document
  • Deployment - Kubernetes GitOps deployment

Available Tasks

task --list

Common Tasks

Task Description
task check Check all prerequisites are installed
task build Build all binaries
task test Run all tests
task lint Run linter
task k8s:up Start local Kubernetes cluster with Tilt (checks prerequisites first)
task k8s:down Stop Tilt
task flux:status Show Flux GitOps status
task docker:build Build Docker image
task test:e2e:k8s Run E2E tests in Kubernetes

About

A simple distributed banking ledger that runs locally via Tilt using Gitless GitOps practices

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors