Add alpha-hardening ADRs and issue plan from pre-release audit.

Lock alpha scope, tracker auth, TOPLOC fraud verification, and deferred multi-tracker money-path work; supersede legacy fraud issues with ADR-0018.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
D.Popov
2026-07-04 23:12:09 +03:00
parent 7caf12980a
commit 68e057209c
35 changed files with 1550 additions and 4 deletions

View File

@@ -0,0 +1,66 @@
# ADR-0019: Money-path consistency (multi-tracker)
## Status: Accepted (design); implementation deferred post-alpha
## Context
ADR-0015 assumes a **single settlement tracker** with Raft-replicated ledger events. The hive already gossips billing, accounts, and stats between trackers. When multiple trackers participate, several money-path races appear:
- Settlement retries may double-pay if idempotency keys diverge from on-chain reality.
- Any tracker follower can apply `forfeit` / `charge` events — fine under one trusted operator, dangerous with adversarial peers.
- Raft term/vote state is in-memory — restart can duplicate leadership epochs.
- `forfeit` events are not commutative with `charge`/`payout` ordering under concurrent replication.
Alpha ships with **one settlement-capable tracker** (ADR-0016). This ADR records the accepted multi-tracker design so Bucket 2 issues do not block alpha while preventing silent architectural drift.
## Decisions
### 1. Settlement idempotency (C2)
- Every on-chain payout batch carries a **stable `settlement_id`** already debiting pending before broadcast (`server.py` ~33533356, `_send_settlement` ~3358).
- **Required hardening:** `solana_adapter.send_payouts` (~186213) and the settlement loop must treat the Solana transaction signature as the idempotency anchor — retries reuse the same `settlement_id`; confirmed signatures must never spawn a second debit.
- Deposit watcher already uses `deposit-<sig>` event ids — extend the same pattern to payouts.
### 2. Consensus-gated money mutations (C3/C4)
Money-affecting events (`charge`, `payout`, `forfeit`, `credit`, `settlement`, `bind`) must commit through **Raft** (or successor consensus), not best-effort gossip alone:
- Only the Raft leader appends money commands to the replicated log.
- Followers apply committed entries in order; gossip becomes a transport, not the source of truth.
- Settlement signing remains **leader-only** and **treasury-key-bearing** (ADR-0015).
Shard-assignment commands already use Raft (`raft.py`); extend the log command set.
### 3. Durable Raft metadata (A3)
Persist `currentTerm`, `votedFor`, and log index to disk (`raft.py` ~26 — today term lives only in memory). Without this, restart can elect split leaders and duplicate settlement epochs.
### 4. Commutative forfeit semantics (H1)
Define explicit ordering rules when replicating `forfeit` vs `charge`/`payout`:
- Forfeit amount is snapshotted at event creation time (`billing.py` ~287).
- Apply forfeit **after** pending balance reflects all prior committed charges in the same epoch, or use signed pending snapshots in the event payload.
- `setdefault` on `_pending_since` (~324) and wallet bindings (~351) must not resurrect stale state on out-of-order apply — use last-writer-wins with `(term, index)` tie-break.
### 5. Alpha posture
| Item | Alpha | Post-alpha |
|---|---|---|
| Single treasury holder | Required | Optional multi-sig |
| Gossip-authenticated billing | Required (ADR-0017) | Superseded by Raft commit for money |
| On-chain idempotency | Best-effort resend | Hard guarantee (C2) |
| Consensus-gated settlement | Leader check only (~3331) | Full Raft gate (C3/C4) |
## Consequences
- Bucket 2 issues in `.scratch/alpha-hardening/` are **tracked but not alpha-blocking**.
- Implementing C3/C4 before alpha would delay release without security benefit while only one operator runs settlement.
- When enabling third-party settlement trackers, **all four** hardening items must ship together — partial deployment is worse than single-tracker alpha.
## Related
- ADR-0015 (settlement loop, pending collateral)
- ADR-0016 (single settlement tracker for alpha)
- ADR-0017 (gossip auth prerequisite)
- Issues: `12-c2-on-chain-idempotency.md` through `15-h1-commutative-forfeit.md`