- Shell 63.9%
- HTML 27.2%
- Dockerfile 8.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .gitea/workflows | ||
| api/openapi | ||
| deploy | ||
| go-services | ||
| security | ||
| tools | ||
| .dockerignore | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile.webapp | ||
| gradle.properties | ||
| README.md | ||
Banking Platform
An event-driven banking reference platform. Seven backend services are implemented in Gotlin and compiled to static Go binaries. Database-owning services use isolated logical PostgreSQL databases on a shared instance. HTTP is used at the edge, protobuf gRPC is used for synchronous service-to-service calls, and NATS JetStream records business events.
Modules
| Module | Responsibility | Database |
|---|---|---|
go-services/services/accounts-service |
Customer accounts and available balances | accounts |
go-services/services/auth-service |
First-party sessions, OIDC, users, tokens, and JWKS | auth |
go-services/services/core-service |
Consistent internal account transfers and accepted-payment outbox | core |
go-services/services/transactions-service |
Immutable booking ledger and transaction history | transactions |
go-services/services/payments-service |
Payment initiation and orchestration | payments |
go-services/services/sepa-service |
SEPA transfer state and validation | sepa |
go-services/services/registration-service |
Customer registration and account provisioning | none |
go-services/apps/frontend |
Go-served customer and backoffice consoles | none |
Local development
Start infrastructure with docker compose up -d, generate contracts with go-services/generate-contracts.sh and go-services/generate-rpc.sh, then build a service with go-services/build-gotlin.sh accounts-service. Services validate JWTs issued by the custom auth-service.
Create an account through POST /accounts with a signed session cookie or bearer token, then use the frontend (or POST /payments) to initiate a EUR payment. Payments reserve funds synchronously over gRPC and publish banking.payment.initiated to JetStream. Registration also provisions users and accounts over gRPC. Transactions and SEPA consume payment events independently.
Registration provisions the account immediately and sends an IdM-owned email verification link. Banking login uses OIDC Authorization Code + PKCE only; passwords and mandatory passkey/TOTP challenges are handled on IdM pages.
core-service provides separate consistency-critical endpoints: POST /core/accounts creates an internal account and POST /core/payments atomically debits one internal account, credits another, records both ledger entries, and accepts the payment. Its transactional outbox asynchronously publishes banking.payment.accepted, which the transaction projector consumes.
Payment requests require an idempotencyKey. Account reservations are idempotent by payment ID, and the payments outbox uses database row claiming with FOR UPDATE SKIP LOCKED, allowing several payment replicas to publish safely. Transaction and SEPA consumers use shared durable pull consumers; their database uniqueness constraints make JetStream's at-least-once delivery safe.
Each database service applies ordered migrations/V<version>__<name>.sql files before accepting traffic. Applied versions and checksums are tracked in schema_migrations; concurrent startup is serialized with a PostgreSQL advisory lock.
Public REST contracts live in api/openapi; internal protobuf contracts live in go-services/libs/rpc.
The customer console is served at /; the operations console is served at /backoffice and supports account listing and manual funding through the core API.
Kubernetes
Apply deploy/kubernetes/base with Kustomize after provisioning
postgres-credentials, internal-service-auth, banking-database-urls, and
the banking-tls TLS Secret.
The base intentionally contains no credentials. For local k3d development,
apply deploy/kubernetes/overlays/local, which supplies development-only
credentials and disables secure cookies.
Create the persistent RSA signing-key Secret before deployment:
./tools/provision-auth-key.sh
./tools/provision-auth-mfa-key.sh
Production deployments also require auth-smtp, created with
tools/provision-auth-smtp.sh from the SMTP environment variables documented
by that script.
The /core, /transactions, and /sepa operational APIs require an admin
JWT role. After registering the operations user, grant it with:
./tools/grant-admin.sh operator@example.com
For the local k3d deployment, use http://banking.127.0.0.1.nip.io:8088/. The nip.io hostname resolves to 127.0.0.1, so no hosts-file entry or VPN is needed.
For internet exposure, do not use the local overlay. Terminate TLS at a trusted
Nginx/Caddy instance, force HTTPS and HSTS, configure the auth service's public
issuer and redirect URI, enforce per-IP limits on registration/login/token
routes, and keep service ports 8080/9090 private. See
go-services/services/auth-service/README.md for remaining identity-provider
operational requirements.
Signing-key rotation, OpenID Foundation conformance, and OWASP ZAP procedures
are documented in security/README.md.