Status: done # 11 — C6: Wallet binding ownership proof + binding overwrite safety ## What to build `POST /v1/wallet/register` binds a client Solana wallet to an API key for deposit attribution. Today any Bearer key can bind any wallet string without proving ownership. Prevent hijack and accidental overwrite. **Code refs:** - `packages/tracker/meshnet_tracker/server.py` — `_handle_wallet_register` (~2625–2648) - `packages/tracker/meshnet_tracker/billing.py` — `bind_wallet` (~153+), `_wallet_bindings` / direct overwrite on apply (~351) Require signed message from wallet pubkey (ed25519 via `cryptography` / solders). Reject rebinding without admin or signed release. Use explicit overwrite policy — today `~351` overwrites binding directly; gossip apply must reject conflicting binds instead of silently clobbering. ## Test-first 1. Red: bind wallet A with only API key, no signature — must fail after fix. 2. Red: wallet already bound to key1; key2 cannot steal without proof. 3. Green: valid signature binds; deposit watcher credits correct API key. ## Acceptance criteria - [x] Wallet binding requires cryptographic proof of pubkey ownership - [x] One wallet → one API key (or documented admin override) - [x] Gossip `bind` events cannot overwrite existing binding via direct overwrite at `~351` - [x] Tests with deterministic keypairs (local adapter) ## ADR links - [ADR-0017](../../docs/adr/0017-tracker-authentication-and-authorization.md) §5 - [ADR-0015](../../docs/adr/0015-usdt-custodial-settlement.md) ## Blocked by - `02-a2-unified-auth-boundary_completed.md` - `03-c5-starting-credit-zero_completed.md`