From 097c24f498ec7645754ebb4bd928a8de7dce975b Mon Sep 17 00:00:00 2001 From: clawbot Date: Tue, 10 Feb 2026 18:10:32 -0800 Subject: [PATCH] Document hashcash proof-of-work plan for session rate limiting --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/README.md b/README.md index 267011c..8387ff2 100644 --- a/README.md +++ b/README.md @@ -648,6 +648,49 @@ Per gohttpserver conventions: 11. **Signable messages** — optional Ed25519 signatures with TOFU key distribution. Servers relay signatures without verification. +### Rate Limiting & Abuse Prevention + +Session creation (`POST /api/v1/session`) will require a +[hashcash](https://en.wikipedia.org/wiki/Hashcash)-style proof-of-work token. +This is the primary defense against resource exhaustion — no CAPTCHAs, no +account registration, no IP-based rate limits that punish shared networks. + +**How it works:** + +1. Client requests a challenge: `GET /api/v1/challenge` +2. Server returns a nonce and a required difficulty (number of leading zero + bits in the SHA-256 hash) +3. Client finds a counter value such that `SHA-256(nonce || counter)` has the + required leading zeros +4. Client submits the proof with the session request: + `POST /api/v1/session` with `{"nick": "...", "proof": {"nonce": "...", "counter": N}}` +5. Server verifies the proof before creating the session + +**Adaptive difficulty:** + +The required difficulty scales with server load. Under normal conditions, the +cost is negligible (a few milliseconds of CPU). As concurrent sessions or +session creation rate increases, difficulty rises — making bulk session creation +exponentially more expensive for attackers while remaining cheap for legitimate +single-user connections. + +| Server Load | Difficulty | Approx. Client CPU | +|--------------------|------------|--------------------| +| Normal (< 100/min) | 16 bits | ~1ms | +| Elevated | 20 bits | ~15ms | +| High | 24 bits | ~250ms | +| Under attack | 28+ bits | ~4s+ | + +**Why hashcash and not rate limits?** + +- No state to track (no IP tables, no token buckets) +- Works through NATs and proxies — doesn't punish shared IPs +- Cost falls on the requester, not the server +- Fits the "no accounts" philosophy — proof-of-work is the cost of entry +- Trivial for legitimate clients, expensive at scale for attackers + +**Status:** Not yet implemented. Tracked for post-MVP. + ## Status **Implementation in progress.** Core API is functional with SQLite storage and