aboutsummaryrefslogtreecommitdiffstats
path: root/docs/MESHBAY_DESIGN.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-14 13:34:47 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-14 13:34:47 +0200
commit51705056a578d2649a989bf14a056fbcfae58a6b (patch)
treedfd078aba518427387fca29b9d43c3723b030008 /docs/MESHBAY_DESIGN.md
parentdaec4bc6a2a9f9e038e5269586b06018ff327a27 (diff)
downloadmeshbay-51705056a578d2649a989bf14a056fbcfae58a6b.tar.gz
feat(hub): replace reCAPTCHA with a self-hosted proof of work
Sign-up and passphrase reset sent every visitor's address and browser details to Google, which needed a consent the sign-up form could not ask for freely. The hub now issues its own challenge (ALTCHA's scheme, signed with a key derived from the hub's private key, single-use, 30 minutes) and the page solves it with SubtleCrypto while the form is filled in. - GET /v1/users/captcha issues a challenge; 404 captcha_disabled when off. - [captcha] enabled / max_number replace site_key / secret_key, which are now ignored with a warning; MESHBAY_CAPTCHA_ENABLED replaces the old variables. - No Google origin left in the CSP of the hub, the desktop shell or the Android shell; captcha_site_key leaves /v1/hub/info. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/MESHBAY_DESIGN.md')
-rw-r--r--docs/MESHBAY_DESIGN.md20
1 files changed, 18 insertions, 2 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md
index f9ceaa2..2174879 100644
--- a/docs/MESHBAY_DESIGN.md
+++ b/docs/MESHBAY_DESIGN.md
@@ -2533,9 +2533,25 @@ Two things survive on purpose:
the nodes refuse the account and close the groups' sessions now. A node that is
offline misses it.
-Registration is gated by a CAPTCHA whenever one is configured — **unconditionally**,
+**Registration and the passphrase-reset request are gated by a proof of work**
+(`captcha.py`), on unless `[captcha] enabled = false`, and **unconditionally** —
not only when some other field is absent, or the real client's ordinary request
-skips it. The desktop client renders the widget too.
+skips it. The hub signs a challenge (the SHA-256 of a nonce, an expiry and a
+number below `max_number`) with a key derived from its own private key; the page
+finds the number while the form is being filled in and sends it with the form.
+An answer is checked against the hub's signature, its expiry, and the answers
+already spent, so one solve is one form. **No third party is involved**: no
+script, cookie or visitor address leaves for anyone else, which is what keeps the
+sign-up form free of a consent it could not ask for freely. What it buys is cost
+per attempt, not a verdict on who is human; the bound that holds against a
+caller with machines to spare is the mail budget (§7.4), since these two routes
+are what make the hub send mail.
+
+**The sign-up form states what the hub keeps**, as a notice and never a checkbox:
+the account rests on the terms of use and the connection log on a legal
+obligation, so there is no consent to collect, and one that blocks sign-up would
+be neither free nor withdrawable. The notice links to the legal pages of the hub
+in use (`/legal/`), which are its operator's to write.
**Sessions end three ways, all admin settings in hours** (`session.*`, §7.4):