# 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.

{% hint style="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.
{% endhint %}

## 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:**

```json
{
  "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:**

```json
{
  "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:**

```json
{
  "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:**

```json
{
  "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

| Variable                      | Default                                       | Description                                                                    |
| ----------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------ |
| `CHAIN_RPC_URL`               | `http://localhost:8545`                       | Erigon node RPC URL. In Docker Compose: `http://erigon:8545`                   |
| `USER_DB_URL`                 | `http://localhost:8548`                       | User DB service URL. In Docker Compose: `http://user_db:8548`                  |
| `PROXY_PORT`                  | `8546`                                        | Port the backend proxy listens on                                              |
| `AUDIT_DB_PATH`               | `./data/audit.db`                             | SQLite audit log path. Use a volume-mounted path in production                 |
| `AUTH_MODE`                   | `advisory`                                    | `advisory`: log auth failures; `strict`: reject unauthenticated calls with 401 |
| `LOCAL_CHAIN_ID`              | `33`                                          | Chain ID used for IBAN account number generation                               |
| `ALLOWED_ORIGINS`             | `http://localhost:3000,http://localhost:3001` | Comma-separated CORS allowed origins                                           |
| `SESSION_CACHE_TTL`           | `5s`                                          | Duration to cache validated session tokens                                     |
| `PERMISSION_REGISTRY_ADDRESS` | *(from deployments.json)*                     | `PermissionRegistry` contract address. If blank, permission checks are skipped |
| `DEPLOYMENTS_PATH`            | `/app/deployments.json`                       | Path to the contract address manifest                                          |
| `INTEROP_ENABLED`             | `false`                                       | Enable 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               |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cocoon.erigon.tech/operators/backend-configuration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
