Lana Bank Functional Architecture
Table of Contents
- General Description
- Application Architecture
- Communication Flows
- Integrations with External Systems
- Authentication and Security Flows
- Network Segmentation by Environment
- Security Zones
- Audit
- Bitcoin-Backed Loan Flow
- Portability and Vendor Lock-in
- Servers / Instances
- Operating Systems
- Databases
- Middleware / Integration
- External Services
1. General Description
This document describes the logical architecture of Lana Bank, including the internal architecture of the application, integrations with external systems, authentication and security flows, network segmentation by environment, and security zones.
1.1 General Overview
Lana Bank is a banking core application specialized in Bitcoin-backed lending. The architecture follows the principles of Domain-Driven Design (DDD) and Hexagonal Architecture, clearly separating the domain, application, and infrastructure layers.
The backend is developed in Rust, using PostgreSQL as the main database and Cala Ledger as the double-entry accounting engine with strong consistency guarantees. The web frontends are built with Next.js and TypeScript, consuming GraphQL APIs exposed by the backend. For reporting and analytics, there is a data pipeline based on Meltano that extracts information to BigQuery, where data is transformed with dbt.
2. Application Architecture
2.1 Banking Core Modules
The core modules implement the bank's business logic, following Event Sourcing principles where each entity maintains its state as a sequence of immutable events.
2.1.1 Credit
The credit module is the heart of the system, managing the complete lifecycle of Bitcoin-backed loans. A credit facility goes through a well-defined lifecycle that begins when an operator creates a CreditFacilityProposal for a customer. This proposal automatically enters an approval process managed by the governance module; members of the assigned committee must vote to approve it.
Once approved, the proposal transforms into a PendingCreditFacility. At this stage, the customer must deposit the required Bitcoin collateral. If the facility has an assigned custodian, custodian webhooks automatically keep the collateral balance synchronized. If there is no custodian (manual mode), an operator can update the collateral directly. The system continuously monitors the collateralization ratio (CVL - Collateral Value to Loan) comparing it with the current Bitcoin price.
The facility is automatically activated when the CVL reaches the initial threshold configured in the terms. TermValues define all loan parameters: the annual interest rate, duration (classified as short or long term depending on whether it exceeds 12 months), interest accrual intervals (daily or monthly), the initial commission (one-time fee), and three critical CVL thresholds that must maintain a strict hierarchy: the initial CVL must be greater than the margin call CVL, which in turn must be greater than the liquidation CVL. The disbursement policy is also configured, which can be single or multiple.
With the CreditFacility active, the customer can request Disbursals. Each disbursement goes through its own approval process. When executed, the funds are credited to the customer's deposit account and an Obligation is created representing the debt. Obligations have a state cycle: they begin as "not yet due", move to "due" on the due date, can become "overdue" if not paid on time, enter "liquidation" if the delinquency persists, and finally be marked as "defaulted".
The system executes periodic jobs for interest accrual. InterestAccrualCycles calculate interest according to configured intervals and generate new obligations for accrued interest. When the customer makes a Payment, the system automatically allocates funds to pending obligations in priority order through PaymentAllocation, typically prioritizing the oldest obligations and interest over principal.
If the CVL falls below the margin call threshold, the facility enters an alert state. If it falls below the liquidation threshold, a LiquidationProcess is initiated where the bank can execute the collateral to recover the debt. The system implements a hysteresis buffer to avoid frequent oscillations between states when the CVL is near the thresholds.
2.1.2 Deposit
The deposits module manages the accounts where customers maintain their funds in USD. When a DepositAccount is created for a customer, the system automatically generates the corresponding accounting accounts in the ledger. The accounting categorization depends on the customer type: accounts for individuals, government entities, private companies, banks, financial institutions, and non-domiciled companies are grouped under different nodes of the chart of accounts.
Deposits represent fund inflows to the account and are recorded immediately. Withdrawals follow a more controlled flow: when initiated, funds are reserved in accounting and an approval process is created. The assigned committee must approve the withdrawal before it executes. If approved, funds leave the account; if rejected or cancelled, the reserve is reversed. There is also the possibility of reversing already recorded deposits when necessary.
Accounts can be in different states that affect permitted operations. An active account allows all normal operations. A frozen account prevents new operations but keeps the balance visible; this is useful for compliance situations where funds need to be temporarily blocked. A closed account is permanent and is only permitted if the balance is zero. The module also supports bulk updating of the state of all accounts for a customer, for example when their KYC verification changes.
The account history can be consulted through the ledger, showing all transactions that have affected the balance. The module calculates available balance considering pending approval withdrawals.
2.1.3 Customer
This module manages information about the bank's customers and is fundamental for regulatory compliance. Each customer is created with a specific type that determines their accounting and regulatory treatment: Individual for natural persons, GovernmentEntity for government entities, PrivateCompany for private companies, Bank for banks, FinancialInstitution for other financial institutions, ForeignAgencyOrSubsidiary for foreign agencies, and NonDomiciledCompany for non-domiciled companies.
The KYC verification process integrates with SumSub. A customer begins in PendingVerification state. When SumSub notifies via webhook that verification was successful, the customer moves to Verified with a KYC level (Basic or Advanced). If verification fails, they remain in Rejected state. The system can be configured to require verification before allowing the creation of deposit accounts or credit facilities.
The module manages documents associated with the customer, storing them in the cloud and allowing generation of temporary download links. Documents can be archived or deleted as needed.
For compliance with inactive account regulations, the system tracks the last activity of each customer. A periodic job automatically classifies customers according to their activity: Active if they have had recent activity (less than one year), Inactive if they have been between one and ten years without activity, and Suspended if they exceed ten years. This classification can affect the state of their deposit accounts.
2.1.4 Custody
The custody module provides an abstraction over multiple Bitcoin custody providers, allowing the bank to work with different custodians according to their operational and regulatory needs. The system is designed with a plugin pattern where each Custodian implements a common interface. Currently BitGo and Komainu are implemented, but the architecture allows adding new custodians without modifying the rest of the system.
In each deployment, multiple custodians can be configured and activated simultaneously. When a credit facility is created, you can specify which custodian will manage that particular facility's collateral. This allows, for example, using different custodians for different customer segments or jurisdictions.
Each custodian manages Wallets that are assigned to credit facilities to receive Bitcoin collateral. Custodians notify the system about changes in wallet balances through webhooks. When a notification arrives, the system updates the Collateral associated with the corresponding facility and recalculates the CVL. This automatic synchronization is critical for maintaining an accurate view of risk in real time.
Custodian webhooks are received at provider-specific endpoints and are cryptographically validated before processing. The configuration for each custodian includes the necessary API credentials and keys to verify webhook authenticity. Sensitive keys are stored encrypted.
2.1.5 Accounting
The accounting module implements a complete double-entry accounting system, fundamental for any regulated financial institution. It uses Cala Ledger as the underlying engine, a specialized Rust crate that provides predefined transaction templates and ACID consistency guarantees for all accounting operations.
The ChartOfAccounts defines the bank's hierarchical account structure. It can be imported from CSV files and supports a tree structure with multiple levels. Each tree node can be an individual account or a group that aggregates its children's accounts. The chart of accounts integrates with other modules: customer deposit accounts, credit facilities, and collateral accounts are automatically created as children of appropriate nodes according to customer and product type.
Each LedgerAccount has a normal balance type (debit or credit) and can maintain balances in multiple currencies (USD and BTC). LedgerTransactions represent accounting movements that always maintain balance: total debits equal total credits. The system automatically records transactions for each business operation: deposits, withdrawals, disbursements, loan payments, interest accrual, and collateral updates.
For financial reports, the module generates the TrialBalance which lists all accounts with their debit and credit balances, useful for verifying that the books balance. The BalanceSheet presents the bank's financial position organizing assets, liabilities, and equity. The ProfitAndLoss shows income (mainly loan interest) minus expenses to calculate the period's result.
The system supports multiple FiscalYears and allows querying balances and reports for specific date ranges. It also allows ManualTransactions for accounting adjustments that do not originate from automated system operations.
2.1.6 Governance
The governance system provides a flexible framework for implementing multi-signature approval flows on sensitive operations. It is designed to adapt to different organizational structures and regulatory requirements.
Committees represent groups of people authorized to make decisions about certain types of operations. A committee can have any number of members, typically system users with specific roles. The same user can belong to multiple committees.
Policies define the approval rules for each type of process. A policy specifies which committee is responsible for approving that type of operation and what the required threshold is: the minimum number of affirmative votes needed to approve. For example, a policy for disbursement approval could require 2 of 3 members of the credit committee.
When an operation requiring approval is initiated, the system automatically creates an ApprovalProcess linked to the corresponding policy. The process begins in pending state and records committee member votes. A member can vote to approve or to deny (with a mandatory reason). When the approval threshold is reached, the process is marked as approved and an ApprovalProcessConcluded event is emitted. If any member denies, the process immediately terminates as rejected.
Approval process conclusion events are consumed by jobs that execute the approved operation or handle the rejection. This design decouples the approval flow from execution, allowing approvals to be processed asynchronously.
2.1.7 Access
The access module implements role-based access control (RBAC) for all system operators. Users represent the people who operate the bank through the Admin Panel. Each user has a unique identifier that links with the external authentication system.
Roles group permission sets and are assigned to users. A user can have multiple roles, and their effective permissions are the union of permissions from all their roles. PermissionSets are named collections of specific permissions that facilitate configuration of common roles.
The permission system is granular: each operation in each module has an associated permission. For example, there are separate permissions for reading customers, creating customers, approving KYC, viewing credit facilities, initiating disbursements, etc. Before executing any operation, the system verifies that the user has the corresponding permission and records the action in the audit log.
The authorization system uses Casbin, a flexible access control engine, with policies stored in PostgreSQL for persistence and synchronization between instances. The RBAC model follows a three-level structure: User → Role → PermissionSet → Permissions (Object + Action).
Each module defines its own permission sets that group related actions. Typical permission sets follow a viewer/writer pattern. The system includes predefined roles like Admin (full access), Bank Manager (similar to admin but without access to access management or custody), and Accountant (focused on accounting and viewing functions).
Permissions are managed dynamically through the API and changes persist immediately to the database, reloading on each permission verification, ensuring updates are effective without restarting the system.
2.1.8 Price
This module obtains and manages Bitcoin prices, a critical function for a bank offering BTC-collateralized loans. The system integrates with Bitfinex to obtain real-time prices through its API.
When a new price is obtained, the module publishes a CorePriceEvent that other modules consume. The credit module is the main consumer: it uses the price to calculate the CVL of all active facilities and determine if any have fallen below margin call or liquidation thresholds. Price changes can trigger state updates in facilities and potentially initiate liquidation processes.
2.1.9 Report
The reports module coordinates the generation of regulatory and operational reports. It defines Report types that specify what data to include and in what format. Each report execution is registered as a ReportRun with its state (pending, executing, completed, failed) and generated files.
Report generation integrates with the data pipeline: transformed data in BigQuery feeds the final reports. The system can integrate with external reporting systems according to the regulatory needs of each jurisdiction where the bank operates.