Resilient Inclusive Banking Fabric · Team Rexosphere · Duothan 6.0 Phase 2 (REBUILD)
A zero-trust, offline-capable banking platform rebuilt from the ground up: no single point of failure, a cryptographically verifiable ledger, and banking that still works without an internet connection.
This repository implements the architecture submitted in Phase 1 RECON blueprint.
FINIX is a hackathon demo banking platform — a serious rebuild of banking for a scenario where a cyberattack has taken traditional systems offline. It is not a single monolith app; it is a mesh of smaller services (identity, accounts, ledger, payments, risk, and more) that keep working under failure, offline conditions, and strict security.
What it shows:
- Banking that still works offline, on low-data pages, and over USSD (
*334#) - Strong security: zero-trust, short-lived tokens, master-key recovery only inside an enclave
- A tamper-evident ledger you can verify was not altered
- Multiple channels: web PWA, lite page, admin console, USSD simulator
What “running it” means: Docker starts the gateway, databases, Kafka, Keycloak, and the banking services. You then open the web/admin UIs and walk through the demo.
Two ways to start: use our published images (Docker only — fastest for new users), or build everything yourself from this repo if you prefer. Same demo either way — see How to run, then docs/DEMO.md.
A Super Malware Agent has taken the world's banking systems offline. Customer data survived in backups, but the Master Key that unlocks the banking network is sealed behind security layers. Rebuilding the old monolith would only recreate the same failure: one shared database, one network zone, one compromise away from total collapse.
FINIX is designed as a banking mesh, not a banking app:
| Failure in the old system | How FINIX answers it |
|---|---|
| Monolith — one compromise takes everything | Independent services, database per service, blast-radius containment |
| Implicit trust inside the network | Zero trust: mTLS everywhere, continuous verification, 5-minute tokens |
| Master Key held by a single custodian | Shamir 3-of-5 split across institutions, reconstructed only inside an enclave |
| Mutable logs — tampering is undetectable | Append-only hash-chained ledger, Merkle-anchored and signed every 60s |
| 100% internet-dependent — excludes rural users | Offline-first vouchers, USSD *334#, low-data mode under 50 KB |
| Classical crypto against a 2065 threat model | Post-quantum ML-KEM-768 and ML-DSA-65 |
flowchart TB
subgraph L1["Layer 1 · Edge Channels"]
WEB["Web PWA<br/>Next.js"]
LITE["Low-data<br/><50KB"]
USSD["USSD<br/>*334#"]
POS["ATM / POS"]
end
subgraph L2["Layer 2 · Security Edge"]
GW["Kong API Gateway"]
IAM["Keycloak IAM<br/>OIDC · MFA · WebAuthn"]
end
subgraph L4["Layer 4 · Business Services"]
IDN["Identity"]
ACC["Account"]
ORC["Orchestrator<br/>Saga"]
LED["Ledger<br/>append-only"]
VLT["Vault<br/>Shamir 3-of-5"]
PAY["Payment Hub<br/>Go"]
RSK["Risk AI<br/>Python"]
LOA["Loan"]
CMP["Compliance"]
NTF["Notification<br/>Node"]
end
subgraph L5["Layer 5 · Data & Events"]
KFK["Kafka"]
PG[("PostgreSQL<br/>per service")]
RDS[("Redis")]
end
subgraph L6["Layer 6 · Trust Anchor"]
ENC["Enclave Runtime<br/>reconstruct-only"]
ANC["Merkle Anchor<br/>ML-DSA signed"]
end
L1 --> GW --> IAM
GW --> L4
ORC --> ACC & LED & PAY & RSK
L4 --> KFK
L4 --> PG
IDN --> RDS
VLT --> ENC
LED --> ANC
Six layers, ten services, four languages. The polyglot split is deliberate — see ADR-0001.
This is an in-progress Phase 2 build. The table is the honest state of the repository, not the target architecture.
| Milestone | Scope | Status |
|---|---|---|
| M0 | Build system, convention plugins, shared kernel, compose skeleton, CI, ADRs | ✅ Complete |
| M1 | Identity + auth: Keycloak realm-as-code, PKCE BFF, DPoP, OPA, Vault PKI profile | ✅ Complete |
| M2 | Money core: account-service, append-only double-entry ledger + hash chain | ✅ Complete |
| M3 | Saga orchestrator, transactional outbox → Redpanda, AsyncAPI, chaos script | ✅ Complete |
| M4 | Vault: Shamir + Feldman VSS, custodians, enclave, ceremony UI | ✅ Complete |
| M5 | Merkle anchor, proof API, in-browser verification, tamper demo | ✅ Complete |
| M6 | PWA, offline vouchers, USSD gateway, /lite under 50 KB |
✅ Complete |
| M7 | Risk AI, adaptive step-up auth, service quarantine | ✅ Complete |
| M8 | Payment Hub, loans, compliance, notifications, admin console | ✅ Complete |
| M9 | Full QA suite, load/chaos/DR evidence, user guide | ✅ Complete |
M0–M9 are in tree. JVM modules pass ./gradlew verify; polyglot edges have their own tests:
- shared-kernel — Money, JCS, Merkle, PQC, outbox, DPoP, OAuth2 resource-server defaults
- identity-service — profiles, devices, login-risk scoring, PKCE authorize/token BFF cookies
- account-service — open/list accounts, reserve/commit/release holds, seed personas, offline voucher register/reconcile + double-spend quarantine
- ledger-service — balanced double-entry journals, SHA-256 hash chain, append-only DB triggers,
/verify, ML-DSA Merkle anchors + proof + tamper demo - transaction-orchestrator — internal-transfer saga with risk gating (
allow/AWAITING_STEP_UP/BLOCKED) + compensation + outbox events - vault-service — Shamir 3-of-5 + Feldman VSS, hybrid-sealed custodian shards, ceremony workflow
- enclave-runtime — attestation, reconstruct-only path with key zeroing
- ussd-gateway — Africa's Talking
POST /ussdfor*334#(balance, send, mini-statement, language) with Redis sessions - risk-ai-service — IsolationForest + rules (
/v1/score), login enrichment, AI Shield quarantine, FedAvg demo; model card indocs/model-card-risk-ai.md - loan-service — SME micro-loans with deterministic credit decision + repayment schedule
- compliance-service — AML/sanctions/SAR cases + party screening + risk-case ingest
- payment-hub (Go) — LankaPay/Visa/CBDC connectors + ISO 20022 pacs.008
- notification-service (Node) — SMS/email/push/voice templates in si/ta/en
- Keycloak SPI —
infra/keycloak/spiadaptive authenticator calls identity/login-risk - apps/web — offline PWA, USSD simulator, zero-JS
/lite.html(<50 KB CI budget), ledger verify - apps/admin — ops console: ceremony, risk/shield, compliance, loans, payments, notifications
- docs — USER-GUIDE, FIDELITY-MATRIX, DEMO, QA + runbooks
- infra — compose core profile wires the full demo stack
Pick one path — both end in the same running demo.
| Path | Who it’s for | Needs | Command |
|---|---|---|---|
| Use published images | New users, judges, quick try | Docker only | make demo-pull |
| Build yourself | Contributors, offline/air-gapped, prefer source | Docker + JDK 21 | make demo |
git clone https://github.com/Rexosphere/finix.git
cd finixNo local Gradle build. Images are published to GHCR on every push to master / main
(ghcr.io/rexosphere/finix/<service>:latest):
make demo-pullThat pulls the images, starts the stack, waits until healthy, seeds personas, and prints URLs. Then open the links below and follow docs/DEMO.md.
| URL | What |
|---|---|
| http://localhost:3000 | Web PWA / lite / USSD simulator |
| http://localhost:3001 | Admin / vault ceremony |
| http://localhost:8081 | Keycloak (admin / admin) |
Demo logins (password Finix!2026 for all): farmer@finix.lk, sme@finix.lk,
elder@finix.lk, regulator@finix.lk.
Pin a specific commit build:
FINIX_IMAGE_TAG=sha-<shortsha> make demo-pullIf docker pull fails with unauthorized, make the GHCR packages public (org settings), or
docker login ghcr.io with a PAT that can read packages.
Prefer not to pull prebuilt images? Build and run from this repository instead — same stack, same seed data, same URLs:
make demoNeeds Docker and JDK 21.
| Command | What it does |
|---|---|
make demo-pull |
Pull GHCR images, start, wait healthy, seed, print URLs |
make demo |
Build locally, start, wait healthy, seed, print URLs |
make up-pull |
Pull + start only (no wait/seed) |
make up |
Start with local image build (no wait/seed) |
make seed |
Seed personas into a running stack |
make logs |
Tail compose logs |
make down |
Stop the stack and remove volumes |
Requires JDK 21. The Gradle wrapper is pinned to a verified SHA-256 — nothing else to install for compile/unit tests.
./gradlew verify # full local gate (compile + tests + coverage + detekt)
./gradlew :shared-kernel:test # tests only
./gradlew detekt # static analysis only
./gradlew integrationTest # Testcontainers suites (requires Docker)verify runs the full local gate across every module: compile, unit and property tests,
static analysis, and the coverage threshold.
Integration tests start real PostgreSQL, Kafka and Keycloak containers, so they need a running Docker daemon. They are a separate source set and are deliberately excluded from
check, so the main gate stays runnable without Docker.
finix/
├── services/
│ ├── build-logic/ Gradle convention plugins — one build contract for every service
│ └── shared-kernel/ Money, canonical JSON, Merkle, post-quantum crypto
├── config/detekt/ Static analysis ruleset
├── docs/adr/ Architecture decision records
└── gradle/ Version catalog + pinned wrapper
Services are auto-discovered: any directory under services/ with a build.gradle.kts is included
in the build, so a new service can never be silently left out of ./gradlew verify.
Every gate below runs as part of ./gradlew verify and blocks a failing build.
| Gate | Threshold |
|---|---|
| Kotlin compiler | Warnings are errors |
| detekt | Zero issues against config/detekt/detekt.yml |
| Line coverage | ≥ 80%, scoped to domain / application / crypto |
| Branch coverage | ≥ 70%, same scope |
Coverage is scoped to the hexagon interior on purpose. Adapters are covered by integration tests instead, so a single repository-wide percentage would flatter the number without meaning much.
The gates earn their place — while the kernel was being written they caught two real defects: default-locale number formatting, which would have made ledger hashes differ between machines, and an off-by-one in the ECMAScript exponent boundary, cross-checked against Node.
- USER-GUIDE.md — graded operator guide
- FIDELITY-MATRIX.md — every Phase-1 claim → status + evidence
- DEMO.md — 12-minute judge script
- Architecture Decision Records — every decision worth challenging, with its rationale and its trade-offs
- QA strategy · Runbooks
Key decisions so far:
| ADR | Decision |
|---|---|
| 0001 | Faithful Spring Boot 3 + Kotlin core, polyglot at the edges |
| 0002 | Gradle native platform() BOM over io.spring.dependency-management |
| 0003 | Logical database-per-service by default, physical under a profile |
| 0004 | ML-DSA-65 anchor signatures instead of BLS aggregation |
ADR-0004 is worth reading as a statement of intent: the blueprint promised BLS aggregation, but BouncyCastle ships no BLS provider and BLS is not post-quantum secure, so it would have contradicted the blueprint's own security requirements. It is recorded as not implemented rather than quietly claimed. Anything FINIX cannot deliver honestly is documented, not dressed up.
| Layer | Choice |
|---|---|
| Core services | Kotlin 2.3 · Spring Boot 3.5 · JDK 21 (virtual threads) |
| Payment Hub | Go |
| Risk / AI | Python · FastAPI |
| Notifications | Node.js |
| Web | Next.js · TypeScript · Tailwind |
| Data | PostgreSQL per service · Redis · Kafka |
| Identity | Keycloak — OIDC, WebAuthn, TOTP |
| Crypto | BouncyCastle — ML-KEM-768, ML-DSA-65, SHA-256 |
| Build | Gradle 9.6 · convention plugins · version catalog |
| Quality | detekt · JaCoCo · Kotest · Testcontainers · ArchUnit |
| Member | GitHub |
|---|---|
| Sangeeth Kariyapperuma | @NipunSGeeTH |
| Kalana Liyanage | @Kalana-Pankaja |
| Ifaz Ikram | @Ifaz-Ikram |
| Suhas Dissanayake | @SuhasDissa |
Built for Duothan 6.0 · IEEE Student Branch of NSBM