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.
