Reference

Locked decisions

A running list of decisions that have been made and should not be revisited without a written proposal in proposals/. This is the "do not bikeshed" list.

Disagreeing with a locked decision? Open a proposal, do not just edit the code. Decisions are locked for a reason — usually because reversing them later is expensive, not because the original choice was obviously correct.

Why this list exists

Every project accumulates a set of "we tried that, it did not work" decisions. Without a written record, the same argument happens every time a new contributor joins. This page is that record. If a decision is not on this list, it is open to discussion.

Architecture

# Decision Why locked
A1 Fork cosmos/evm v0.7.0 instead of building on geth or besu Native IBC, single binary, single identity
A2 Single binary evmd for consensus + EVM Simpler ops than separate processes
A3 Postgres for the indexer, not ClickHouse Simpler ops; volume is local-dev scale
A4 OpenResty for the RPC proxy, not Envoy or HAProxy Lua scripting is the path of least surprise for rate-limit + batch-cap
A5 No cross-chain bridge in v1 Bridge audits are 6+ months and not on the local-dev critical path
A6 Single validator (PoA) in local dev Multi-validator local is not representative of a public testnet anyway
A7 Sweep architecture (per-invoice deposit address ? settlement address) Reversing this requires re-onboarding every merchant

Product

# Decision Why locked
P1 Fiat-priced invoices (fiat_amount + fiat_currency) Merchant mental model is fiat, not token
P2 Native 2BABY for payment, not a stablecoin No stablecoin issuer in v1; would re-architect the sweep
P3 QR code is EIP-681 URI Any EVM wallet works; no custom protocol
P4 Webhook delivery is at-least-once with idempotency keys At-most-once is impossible; exactly-once is the merchant''s job
P5 Sweep is server-initiated, not customer-initiated The deposit key never leaves the server
P6 confirmations_required is per-merchant, not global Coffee shop and luxury goods vendor have different risk profiles

Security

# Decision Why locked
S1 Argon2id for api_key hashing Memory-hard; resistant to GPU cracking
S2 AES-256-GCM with envelope encryption for webhook_secret Standard, well-audited, FIPS-compliant
S3 Reject all debug_* calls at the proxy Leaks internal state, no legitimate use from the public internet
S4 Reject eth_sendRawTransaction inside batched calls Batch amp protection
S5 HMAC-SHA256 with timestamp for webhook signatures Industry standard; replay protection via timestamp window
S6 Reject any webhook_signature whose timestamp is more than 5 minutes off Replay protection
S7 No public faucet in dev Faucet key reuse is a footgun
S8 api_key returned exactly once, at creation Industry standard; if you lose it, rotate

Operations

# Decision Why locked
O1 Local dev runs on WSL2 + Docker Desktop macOS and native Windows paths were tried; WSL2 is the only one that matched production behavior closely enough
O2 Every component is a separate container Mirrors the deployed shape; no "all-in-one" image
O3 Postgres is a single instance, not a cluster Volume is local-dev scale; cluster adds ops cost without proportional safety
O4 Prometheus + Grafana for monitoring Standard, well-understood, free
O5 No Kubernetes in local dev docker compose is enough; K8s adds 10x the moving parts for no local benefit

Things explicitly out of scope

  • A public testnet. We are still on the local dev stack. The gap analysis to testnet is in Roadmap & gaps.
  • A mainnet. Not on the roadmap yet.
  • A cross-chain bridge. Not in v1.
  • A stablecoin. Not in v1.
  • Mobile wallet native (non-Expo) builds. BabyWallet is Expo only in v1.
  • Multi-validator local. Single-validator PoA only.
  • Slashing. Not applicable to PoA.
  • A custom mempool. CometBFT in-process only.