<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/docs/MESHBAY_HTTP_API.md, branch 0.20</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.20</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.20'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-10-15T07:33:28Z</updated>
<entry>
<title>feat(hub): one account, several linked nodes</title>
<updated>2026-10-15T07:33:28Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-15T07:33:28Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=1e8eae1f3de765fcd8163716de6e5fe5aab5a034'/>
<id>urn:sha1:1e8eae1f3de765fcd8163716de6e5fe5aab5a034</id>
<content type='text'>
An account links up to MAX_NODES_PER_ACCOUNT node keys (node_keys table)
instead of the one users.pk_node_ed25519; the migration carries each
account's key over and the downgrade keeps the last one linked.
/v1/nodes/auth accepts any linked key, and its token names the key that
won it (nk). PUT /me/node_key adds a key, idempotently, 409 past the
limit; DELETE /me/node_key names the key: a browser session any of its
own, a node only its own. Unlinking a key closes that node's socket and
refuses its tokens at once, on REST and on the socket; the account's other
nodes are untouched. /pubkeys no longer gives a node key to other accounts,
and gives the caller its last linked one, which installed desktop apps read.

The node reports waiting_for_node_key while its key is unlinked and signs
in again as soon as the hub says so, so a key linked again is back within
seconds; unlinking itself signs in first to hold a token naming its key.

Profile -&gt; Linked nodes lists each node (connected, last seen, IP, linked
since, This machine in the desktop app) with Copy and Unlink, and adds a
key by hand. The Node page banner, Create group and the desktop app add
this machine's key instead of replacing another's. Messages that pointed
at Settings -&gt; Link Node point at Profile -&gt; Linked nodes.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(hub): replace reCAPTCHA with a self-hosted proof of work</title>
<updated>2026-10-14T11:34:47Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-14T11:34:47Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=51705056a578d2649a989bf14a056fbcfae58a6b'/>
<id>urn:sha1:51705056a578d2649a989bf14a056fbcfae58a6b</id>
<content type='text'>
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 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: let the operator pause and resume a root's indexing (MNP 6.2)</title>
<updated>2026-10-11T22:17:32Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-11T22:17:32Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=14911aae21ec4975f7a805b91e3c4867cb41974b'/>
<id>urn:sha1:14911aae21ec4975f7a805b91e3c4867cb41974b</id>
<content type='text'>
A whole-root walk now checks its root before every file: removed or
ejected, it stops instead of reading the drive to the end; paused, it
finishes from the hash cache alone. A paused root is not watched, not
swept by reconcile and survives a restart (roster), its indexed files
stay served. Resume runs the reconcile sweep over the root, so entries
and their enrichment are kept.

Signed root_pause / root_resume over MNP, loopback routes, CLI
`root pause|resume`, a pause button on the indexing dock and
pause/resume in the roots table of Group settings.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: notifications on Android while closed, with nothing to install</title>
<updated>2026-10-09T10:08:31Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-09T10:08:31Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=6832df6177ad973ad0e1b4f0a49d7a6da06c6e04'/>
<id>urn:sha1:6832df6177ad973ad0e1b4f0a49d7a6da06c6e04</id>
<content type='text'>
The phone fetches what is new every fifteen minutes with a poll secret
(POST /v1/push/poll) that reads notification lines and nothing else. When a
UnifiedPush distributor is already installed, the hub also pushes at once,
encrypted to the phone (RFC 8291); losing the distributor falls back to
fetching.

The hub now honours "disable all notifications" itself: create_notification
creates nothing for that account, as it already did for a muted group, so
neither switch lets anything reach a phone. The interface used to be the only
reader of the account-wide switch.

Push endpoints are member-supplied URLs: a send refuses non-public
addresses, connects to the address it checked, and follows no redirect.

Android build untested here (no SDK on this machine).

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>docs: generate an HTTP API listing for the hub and the node control API</title>
<updated>2026-10-05T08:36:18Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-05T08:36:18Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=b8671635cd891068afee81fde05bed880124ec85'/>
<id>urn:sha1:b8671635cd891068afee81fde05bed880124ec85</id>
<content type='text'>
docs/MESHBAY_HTTP_API.md lists every route of the hub (by domain, with the
authentication each requires) and of the node's loopback control API. It is
written by docs/generate_http_api.py from the routes and their docstrings;
test_http_api_doc.py fails when the file drifts from the code or when a
route has no docstring, so a new route must say what it does.

79 routes had no docstring and get a one-line description; a few whose first
line did not describe the route get a summary line.

The login page's developer docs gain an API link next to Design and
Protocol, in every language. README, MESHBAY_DESIGN.md (§0.1, §6.7, §7) and
CLAUDE.md point to the listing; README also points to examples/.

The examples scripts with a shebang become executable.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
