No description
  • Shell 63.9%
  • HTML 27.2%
  • Dockerfile 8.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
pavel 62fc770151
Some checks failed
Build Gotlin services / verify (push) Has been cancelled
Pin ambient persistence compiler
2026-08-29 13:07:41 +02:00
.gitea/workflows Pin ambient persistence compiler 2026-08-29 13:07:41 +02:00
api/openapi Replace banking platform with Gotlin services 2026-08-29 11:19:23 +02:00
deploy Replace banking platform with Gotlin services 2026-08-29 11:19:23 +02:00
go-services Adopt ambient persistence patterns 2026-08-29 13:06:42 +02:00
security Replace banking platform with Gotlin services 2026-08-29 11:19:23 +02:00
tools Replace banking platform with Gotlin services 2026-08-29 11:19:23 +02:00
.dockerignore Replace banking platform with Gotlin services 2026-08-29 11:19:23 +02:00
.gitignore Replace banking platform with Gotlin services 2026-08-29 11:19:23 +02:00
docker-compose.yml Replace banking platform with Gotlin services 2026-08-29 11:19:23 +02:00
Dockerfile.webapp Prepare application source extraction 2026-08-22 15:30:17 +02:00
gradle.properties Prepare application source extraction 2026-08-22 15:30:17 +02:00
README.md Replace banking platform with Gotlin services 2026-08-29 11:19:23 +02:00

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.