# Bansun architecture & security

## Principles

1. **User data stays on the user's device.** The vault, journal, watched wallets, watchlist, predictions and credits live in the browser (optionally inside the encrypted vault). The server keeps only its signing key and the list of spent nullifiers.
2. **Watch, never connect.** Bansun never asks to connect a wallet or hold keys. Revokes are built as plain transactions that the user signs in their own wallet.
3. **Providers see the server, not the user.** Ethereum RPC and price requests are made by the Bansun server, which logs no addresses. A self-hosted node removes even that third party.
4. **Honest AI.** Every answer carries a confidence score, a reason and an "ask a professional" flag. Several models can be compared and scored against reality.
5. **Outside data is data, not instructions.** Documents, token metadata, tool results and source data are wrapped as *untrusted* and checked for prompt-injection patterns.
6. **No silent third parties.** Self-hosted fonts, no analytics, no cookies, a strict CSP. The one exception is the local AI model download, which the user starts (the engine itself is served by the Bansun server once vendored).
7. **Zero dependencies.** Server and frontend use only Node.js and standard Web APIs, so the code is easy to audit and self-host.

## Diagram

```
 Browser (PWA, offline-capable)                          Server (Node.js, no deps)
 ┌─────────────────────────────────────────┐           ┌───────────────────────────────────────┐
 │ Landing (WebGL particles)               │           │ Static files + strict security headers │
 │ App tools                               │  HTTPS    │ /api/agent  plan → tools → model loop  │──► OpenAI-compatible LLM
 │  · Before you sign ← shared/evm.js      │ ────────► │ /api/chat /compare /simplify /scam     │    (Ollama / llama.cpp /
 │  · Journal & risk  ← shared/trading.js  │           │ /api/chain/* status gas market token   │     vLLM / TEE)
 │  · Scam check      ← shared/scam.js     │           │   explain tx portfolio approvals ens   │──► Ethereum JSON-RPC
 │  · Vault/Recovery  ← AES-GCM / Shamir   │           │   (server/chain.js, batching, failover)│    (your node or public)
 │  · Credits         ← shared/blindrsa.js │           │ /api/credits issue / redeem            │──► DefiLlama prices
 │  · Local AI        ← WebLLM (vendored)  │           │ Rate limit: HMAC(daily salt, IP)       │    (they see the server,
 │ localStorage / vault sections:          │           │ data/: keys.json, spent.json           │     never the user)
 │   journal, wallets, watchlist, ledger   │           └───────────────────────────────────────┘
 └─────────────────────────────────────────┘
```

The `shared/` modules run **in both the browser and the server** (ES modules + Web Crypto + BigInt), so keccak, the ABI codec, the EVM analysers, trading maths, the scam rules and the cryptography are tested once for both. The static preview even runs `server/chain.js` and `server/agent.js` in the browser against a sample chain.

## Ethereum layer

- **Keccak-256** (`shared/keccak.js`): BigInt sponge, verified against reference vectors and the SHA3 variant; EIP-55 checksums; ENS namehash.
- **ABI codec** (`shared/abi.js`): static, dynamic and array types; `string` / `bytes32` metadata; unit formatting.
- **Analysers** (`shared/evm.js`):
  - `analyseTransaction`: approve / increaseAllowance / Permit2 approve / setApprovalForAll / transfer / transferFrom / permit / swaps / WETH / multicall (recursive) / Universal Router / fake `claim()`-style functions.
  - `analyseTypedData`: Permit, Permit2 (single, batch, transfer), Seaport `OrderComponents`, wrong chain, other owner.
  - `scanBytecode`: opcode walk collecting `PUSH4` dispatcher selectors (push data skipped, CBOR metadata stops the walk), EIP-1167 clones, SELFDESTRUCT.
  - `rateToken`: risk score from capabilities, proxy, active owner, liquidity and decimals; well-known tokens capped.
- **Data layer** (`server/chain.js`): JSON-RPC batching with fail-over, proxy slots (EIP-1967 implementation / beacon / admin, ZeppelinOS), Uniswap V2 `getPair` + V3 `getPool` (0.05 / 0.3 / 1 %) liquidity, `eth_feeHistory` gas tiers, ERC-20 balances, allowance and `Approval` / `ApprovalForAll` log scans in chunks, ENS resolution, DefiLlama prices / 24h change / hourly chart.
- **Agent** (`server/agent.js`): deterministic pre-planning from the message (hashes, calldata, addresses, ENS, "gas", symbols, scam wording), then a JSON step protocol (`{"tool": …}` or `{"final": …}`) with a step cap, duplicate-call reuse and every tool result wrapped as untrusted data.

## Folder layout

```
server/      config, app (routes, static, headers), llm, chain, agent, credits, ratelimit, store
shared/      keccak, abi, evm, trading, bytes, scam, shamir, blindrsa, guard, ledger, answer   (isomorphic)
public/      index.html (landing), app.html, css/, js/ (particles, app shell, chain-ui, private-store, tools/), fonts/, sw.js
             vendor/web-llm/ (created by `npm run vendor`)
preview/     in-browser API emulator for the static preview
scripts/     build-preview.mjs, vendor-webllm.mjs
test/        unit + integration tests, mock LLM, sample Ethereum chain (chain-fixtures.js), demo server
docs/        GUIDE, API, ARCHITECTURE
Dockerfile, docker-compose.yml, install.sh
```

## Snowmoon → code

| Snowmoon | Bansun feature | Files |
|---|---|---|
| The Bansunpei arrange language to be accessible (ch. 4) | Document simplifier, visual answers (tables, steps) | `server/llm.js`, `tools/simplify.js` |
| The Bansunpei raise privacy standards (ch. 32) | Privacy check, CSP, no trackers | `tools/privacy.js`, `server/app.js` |
| Emerald, the honest local AI (ch. 1) | WebGPU local AI + confidence scores | `local-ai.js`, `shared/answer.js` |
| The concert gate learns "valid and unused, nothing else" (ch. 1) | Anonymous credits (blind signatures + nullifiers) | `shared/blindrsa.js`, `server/credits.js` |
| Reputation loan with a nullifier (ch. 6) | Credit nullifiers prevent double spending | `shared/blindrsa.js` |
| Wallet recovery by 4 of 6 people (ch. 6, 16) | Shamir k-of-n for the vault key | `shared/shamir.js`, `tools/recovery.js` |
| Febric checks a transaction before co-signing (ch. 16) | Before you sign, approval audit, scam and link check | `shared/evm.js`, `tools/txcheck.js`, `tools/approvals.js`, `shared/scam.js` |
| "Language models will always be attackable" (ch. 32) | Prompt-injection guard | `shared/guard.js` |
| "AI should be a player, not the game" (ch. 32) | Agent that shows every tool step and source, many models, Compare, prediction ledger | `server/agent.js`, `/api/compare`, `tools/ledger.js` |
| The privacy robe (ch. 1) | No accounts, minimal logs, daily-rotating hash | `server/ratelimit.js` |

## Threat model (summary)

| Threat | Mitigation | Remaining risk |
|---|---|---|
| The server reads the vault | Encrypted on device (PBKDF2-SHA256 600k → AES-256-GCM with AAD) | A weak passphrase can be guessed from a leaked backup |
| The server links credits to users | Blind signatures; the server never sees tokens | A malicious server could use a different key per user → mitigated by the TOFU key-fingerprint warning; in production, a key transparency log |
| Double spending | Nullifier `SHA-256(domain‖token)` stored | Single-instance JSON storage |
| RSA key leak through a CRT fault | Signature verified before release | – |
| Prompt injection from documents or sources | Untrusted wrapper + system rule + pattern detection + UI warning | Heuristic; small models can still be fooled |
| RPC / price providers link addresses to a user | Requests leave from the server; no logs of addresses; watched wallets stored on device or in the vault | A public RPC still sees which addresses the server asks about; run your own node or Helios for full privacy |
| Malicious token metadata (name/symbol with instructions) | Tool results wrapped as untrusted; injection patterns flagged | Small models can still be fooled; numbers in answers come from tools, not the model |
| A drainer tricks the user into signing | Offline decoder + typed-data analyser + live spender check + approval audit | New drainer contracts and function names; unknown selectors are always flagged as unknown |
| Fake "$BANSUN" contracts before launch | In-app checker: no contract is official until announced in the app and repo | Users who never open the app |
| XSS through AI answers | Escape-first Markdown renderer, http(s)-only links with `noopener`, strict CSP | – |
| Abuse / spam | Token-bucket rate limit per HMAC(daily salt, IP), daily credit quota | Rotating IPs can get more free credits |
| Path traversal | Normalisation + directory prefix check (tested) | – |
| Server crash on a failed write | Atomic writes, folder re-created, errors never stop the process | – |

## Roadmap

1. **Transaction simulation** (`eth_call` with state overrides / `debug_traceCall` on your own node) to show exact balance changes before signing, and honeypot sell tests.
2. **Holder concentration and contract age** through an optional indexer, kept self-hostable.
3. **Paid anonymous credits**: ETH / stablecoins first, then $BANSUN, with RFC 9474 (RSABSSA) blind signatures, per-epoch keys and a key transparency log.
4. **Anonymous relay (Oblivious HTTP)** run by a separate party, so even the Bansun server does not see user IPs; a Helios light client by default.
5. **Verified inference (TEE)** for large models, with attestation shown in the app; staked operator network (see $BANSUN).
6. **Alerts** (price, gas, new approvals on watched wallets) delivered as encrypted push or to a local client.
7. **MCP server** so Bansun's chain tools can be used from other AI apps.
8. **L2 support** (Base, Arbitrum, Optimism) once mainnet is solid.
9. Postgres / Redis storage for multiple server instances.
