crystalbank

An open source core-banking system written in crystal

CrystalBank (CI)

crystalbank

CrystalBank is an open source, event-sourced multi-purpose ledger system built in Crystal. It is designed to serve as a solid foundation for financial applications — demonstrating how core banking concepts can be implemented cleanly on a minimal, self-contained infrastructure.

What it does

At its core, CrystalBank is an event-sourced ledger (powered by crystal-es) with first-class support for accounts, transfers, and customers. Every state change is recorded as an immutable event, making the full history of the system auditable and replayable.

The system is multi-tenant ready through an embedded roles and permissions model that provides fine-grained data scoping and ownership. Access rights and data visibility are controlled at the data level — not just at the API boundary.

Multi-layer approval workflows allow financial operations to be reviewed and approved across multiple levels before they take effect, making the system suitable for regulated environments where maker-checker controls are required.

The entire stack runs on PostgreSQL — the same database instance handles the event store, projections, and the outbox queue. This keeps the infrastructure footprint minimal while preserving flexibility across different deployment contexts.

A Svelte-based frontend dashboard provides a visual interface to the system, making it accessible to non-engineers and easier to demonstrate.

Capabilities

Domain Status Description
Accounts Full account lifecycle management including opening, blocking, and unblocking with stackable cause tracking
Payments SEPA credit transfer processing with approval workflow integration and automated ledger posting
Ledger Double-entry bookkeeping engine recording all money movements as immutable debit/credit entries
Customers Customer onboarding and profile management for natural persons and organisations
Users User management with role assignment and scope-based access control
API Keys Generation, rotation, and revocation of API keys for programmatic access
Authentication API key and credential-based authentication for both human users and machine clients
Approval Workflows Multi-layer maker-checker workflows allowing sensitive operations to be reviewed and approved across multiple levels
Roles & Permissions Fine-grained permission model with role grouping for controlling what each user can see and do
Scopes Hierarchical tenant and business unit isolation — controls data ownership and visibility across the ledger
Events Queryable audit trail exposing the full stream of domain events to authorised users

Roadmap

  • More refined and optimized frontend
  • Dedicated project website
  • Self sign-up to the platform
  • Full event replay to re-project state at any point in time (via crystal-es)
  • ISO 20022 connectors
  • ISO 8583 connectors

Project Structure

crystalbank/
├── app/
│   ├── frontend/       # Svelte-based SPA dashboard
│   │   ├── src/        # Svelte components and application logic
│   │   ├── package.json
│   │   └── vite.config.js
│   ├── public/         # Built frontend assets (generated by build-frontend)
│   ├── src/            # Crystal backend source
│   └── spec/           # Crystal specs
├── docker-compose.yml
└── Makefile

Setup

Prerequisites

Start the environment

$ make dev

This builds the Docker image (if not already present), starts the database, API server, and API documentation services, and opens a console in the running container.

All available make targets can be listed with:

$ make help

Seed the environment

In order to access the API, the initial API credentials need to be seeded. Run this inside the console:

$ crystal app/src/server/start.cr --seed

This will output credentials for two admin users — a Super Admin (initiator) and an Approver:

-----------------------------------------------------
--- Seed credentials Super Admin
client_id:     '0193cc51-cc9b-7955-82ca-7a6482587201'
client_secret: 'secret'
-----------------------------------------------------
-----------------------------------------------------
--- Seed credentials Approver
client_id:     '0193cc51-dd2e-8866-93db-8b7593698312'
client_secret: 'secret'
-----------------------------------------------------

Start the API server

$ crystal src/server/start.cr

The API is exposed on http://localhost:4000.

Build the Svelte frontend

The frontend is a Svelte SPA located in app/frontend/. It is built with Vite and outputs static assets into app/public/, which is served by the Crystal backend.

To build the frontend, run from the project root:

$ make build-frontend

This runs npm install && npm run build inside a node:22-alpine Docker container — no local Node.js installation required. The build produces:

  • app/public/app.js — bundled JavaScript
  • app/public/style.css — bundled CSS

To iterate on the frontend locally outside of Docker, use the Vite dev server directly:

$ cd app/frontend
$ npm install
$ npm run dev

Generate OpenAPI specs

To regenerate the API specification:

$ crystal src/server/start.cr -d -f openapi.json

The updated spec is automatically picked up by the running API documentation services.

View API documentation

Access the PostgreSQL database

postgres://<user>:<password>/eventstore@localhost:4010

Contributing

  1. Fork it (https://github.com/your-github-user/crystalbank/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

Repository

crystalbank

Owner
Statistic
  • 8
  • 1
  • 5
  • 0
  • 0
  • 5 days ago
  • October 23, 2024
License

MIT License

Links
Synced at

Mon, 13 Apr 2026 20:13:25 GMT

Languages