Files
Julius Joska 10ca35e352 feat(relay): optional proof-of-work for registration
GET /v1/register/challenge issues a stateless challenge (version, difficulty,
expiry and a random nonce, HMAC-signed with a per-process key). The client
finds a counter so that SHA-256(domain || challenge || identity_key ||
counter) has the requested number of leading zero bits and sends it in the
X-Sepot-Pow header of POST /v1/register. Verification is one HMAC and one
SHA-256; used challenges are kept in memory until they expire.

SEPOT_REGISTER_POW=off|optional|required (default optional): in optional
mode registrations with a valid solution get a separate, more generous
per-IP bucket (SEPOT_RL_REGISTER_POW_*), registrations without one keep the
existing limit; both share the global cap. required answers 428 without a
valid solution. Difficulty: SEPOT_REGISTER_POW_BITS (18), raised by one bit
per doubling of the registration rate over SEPOT_REGISTER_POW_ADAPT_PER_MIN
up to SEPOT_REGISTER_POW_MAX_BITS (22). server-info advertises the mode.

The paused-registration 503 now carries Retry-After.
2026-10-23 11:44:47 +02:00
..