Skip to main content

Backend Service Configuration

The backend proxy is the gateway between the internet-facing interfaces (dashboard, investor portal) and the private Erigon node. This page details how the backend is configured and what it enforces on every request.

What the Backend Proxy Does

Every JSON-RPC call from the dashboard or investor portal is routed through the backend proxy (port 8546) rather than directly to Erigon (port 8545). The proxy:

  1. Validates the session token by querying the user DB (with a 5-second cache) to identify the caller's role and KYC status.
  2. Checks argument-level permissions against the PermissionRegistry contract — if the call is blocked by a permission rule, it is rejected with error code -32001 before reaching the chain.
  3. Logs the call to the audit database regardless of outcome.
  4. Enforces CORS — rejects calls from origins not in ALLOWED_ORIGINS.
  5. Forwards the call to Erigon and returns the response.
warning

Do not expose port 8545 (Erigon RPC) externally. All external traffic must pass through port 8546 so that session validation, permission checks, and audit logging are enforced on every call.

IBAN Registry

The backend proxy maintains a SQLite registry mapping Ethereum addresses to Swiss-style IBANs. Each registered user account has a unique IBAN derived from the chain ID and an account number.

IBAN Format

CH + 2 check digits + 00033 (chain ID) + 12-digit account number = 21 characters total.

Examples:

  • Admin: CH7900033000000000001
  • Alice: CH5200033000000000002
  • Bob: CH2500033000000000003

IBANs allow FIAT-style payments within the Cocoon ecosystem: the investor frontend's payments screen accepts IBANs as payment targets rather than raw Ethereum addresses, making the user experience familiar for institutional users.

IBAN API Endpoints

These endpoints are served by the backend proxy alongside the JSON-RPC interface:

GET /api/ibans

Return all registered IBAN accounts.

Response:

{
"ibans": [
{ "iban": "CH7900033000000000001", "address": "0xf39Fd6e51aad...", "name": "Admin" },
{ "iban": "CH5200033000000000002", "address": "0x70997970C518...", "name": "Alice" }
]
}

GET /api/iban/:code

Resolve an IBAN to its registered Ethereum address and name.

Response:

{
"iban": "CH5200033000000000002",
"address": "0x70997970C518...",
"name": "Alice"
}

Returns 404 if the IBAN is not registered.

GET /api/address/:addr/iban

Reverse lookup: resolve an Ethereum address to its IBAN.

Response:

{
"address": "0x70997970C518...",
"iban": "CH5200033000000000002",
"name": "Alice"
}

Returns 404 if the address has no registered IBAN.

Health Endpoint

GET /health

Returns the backend's operational status.

Response:

{
"status": "ok",
"chainReachable": true
}

If the Erigon node is unreachable, chainReachable is false but the endpoint still returns HTTP 200 — the backend can serve IBAN and audit queries even when the chain is down.

Authentication Flow

The backend validates sessions by calling the user DB's GET /auth/me endpoint with the caller's bearer token. To avoid a round-trip on every request, results are cached:

Incoming request with Authorization: Bearer <token>

├─ Cache hit (< SESSION_CACHE_TTL, default 5s) → use cached role
└─ Cache miss → GET user_db:8548/auth/me → cache result

The cache key is SHA-256(token) — the raw token is never stored in the cache.

In AUTH_MODE=advisory (default): requests without a valid session token are forwarded but the caller is logged as unauthenticated.

In AUTH_MODE=strict: requests without a valid session token are rejected with HTTP 401.

Environment Variables Reference

VariableDefaultDescription
CHAIN_RPC_URLhttp://localhost:8545Erigon node RPC URL. In Docker Compose: http://erigon:8545
USER_DB_URLhttp://localhost:8548User DB service URL. In Docker Compose: http://user_db:8548
PROXY_PORT8546Port the backend proxy listens on
AUDIT_DB_PATH./data/audit.dbSQLite audit log path. Use a volume-mounted path in production
AUTH_MODEadvisoryadvisory: log auth failures; strict: reject unauthenticated calls with 401
LOCAL_CHAIN_ID33Chain ID used for IBAN account number generation
ALLOWED_ORIGINShttp://localhost:3000,http://localhost:3001Comma-separated CORS allowed origins
SESSION_CACHE_TTL5sDuration to cache validated session tokens
PERMISSION_REGISTRY_ADDRESS(from deployments.json)PermissionRegistry contract address. If blank, permission checks are skipped
DEPLOYMENTS_PATH/app/deployments.jsonPath to the contract address manifest
INTEROP_ENABLEDfalseEnable cross-chain interop listener
INTEROP_ADMIN(empty)Ethereum address for signing cross-chain transactions
INTEROP_ADMIN_KEY(empty)Hex-encoded private key for the interop admin
PEER_CHAINS(empty)Comma-separated chainId=rpcUrl=deploymentsPath for peer chains