<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-hub/tests, 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-15T13:09:58Z</updated>
<entry>
<title>feat(android): no text messages backup, and one build again</title>
<updated>2026-10-15T13:09:58Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-15T13:09:58Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=39cac2878de059992cb09a1ccf09b6bcece99fae'/>
<id>urn:sha1:39cac2878de059992cb09a1ccf09b6bcece99fae</id>
<content type='text'>
READ_SMS sits behind restricted settings outside a store and Play
keeps it for the default SMS application: not worth a second build.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix(auth): the sign-up notice links the privacy statement, with a space</title>
<updated>2026-10-15T12:33:03Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-15T12:33:03Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=37b38e0eb15a79bbda3cd0a1b502669b32e773dc'/>
<id>urn:sha1:37b38e0eb15a79bbda3cd0a1b502669b32e773dc</id>
<content type='text'>
The link under the Register button was glued to the sentence before it: htm
drops whitespace that holds a line break, so "deleted.Legal information".
It also pointed at the hub's /legal/ index. Where an account is created is
where GDPR art. 13 owes the person the information about their data, so it
now links the privacy statement itself — /legal/confidentialite.fr.txt in
French, /legal/privacy-statement.en.txt in every other language — on the
hub that served the page, like every legal link. The sidebar's "Legal
information" is unchanged.

Checked in Chrome and Firefox (headless), in English and French.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(auth): the recovery key never reaches the hub</title>
<updated>2026-10-15T12:25:00Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-15T12:25:00Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=28c77b7648b2a44a18be64ec44344d91cccfd742'/>
<id>urn:sha1:28c77b7648b2a44a18be64ec44344d91cccfd742</id>
<content type='text'>
Ticking "also e-mail it to me" at registration sent the recovery key R in
the register body, and the hub appended it to the verification e-mail: the
hub saw R in clear on its way out, and the resend door — no captcha — let
anyone who knew a pending username and address have the hub mail a
"recovery key" of their choosing.

The box is gone. The recovery screen offers "E-mail it to myself", a mailto:
link that opens the person's own mail application with the key filled in;
the desktop shell hands mailto: to the system (http, https and mailto only)
and the Android shell to a mail application (ACTION_SENDTO). The CLI drops
--email-recovery-key and prints the key, as before. The hub mails the code
alone, and refuses a register that still carries a recovery_key rather than
dropping it, so an older client offering the option cannot tell someone
their key was sent when it was not.

A mailbox holding R remains, with the reset code that reaches the same
mailbox, enough to recover the account's identities; the link says so, and
it is the person's choice.

Checked in Chrome and Firefox (headless, the real page against a stubbed
hub) and by the CLI's end-to-end registration against a local hub. The
Android change was not built here, and the desktop link was not clicked in
the application.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix(hub): a phone's poll secret ends with the account's sessions</title>
<updated>2026-10-15T12:24:35Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-15T12:24:35Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=2dbff20818d171242a15e3567e14292c0d63aea2'/>
<id>urn:sha1:2dbff20818d171242a15e3567e14292c0d63aea2</id>
<content type='text'>
The secret a phone polls /v1/push/poll with is a credential of its own,
outside any session, and it outlived the ones that should have ended it:
"sign out everywhere" — what someone who lost a phone presses — a
passphrase change and an admin revocation left every push row in place, so
the lost phone went on reading "X posted in &lt;group&gt;" lines. Each now deletes
the account's rows, as a reset and an erasure already did, and the poll
refuses a revoked or deleted account whatever deleted the row or not. A
suspended one still reads: the line telling it so is one of them.

A phone still in hand is not affected for long: a refused poll makes it
forget the row, and the page registers it again at its next start.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>refactor(chat): no thread_id — chat has no threads</title>
<updated>2026-10-15T10:57:51Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-15T10:57:51Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=a86bced1640ac1a695b95ac68b95e3fc581e687d'/>
<id>urn:sha1:a86bced1640ac1a695b95ac68b95e3fc581e687d</id>
<content type='text'>
Nothing ever set it (the page and the CLI sent null) and nothing read it
(the node's get_thread had no caller). It is no longer sent by the page or
the CLI, in clear or in the sealed payload, nor relayed or served by the
node; get_thread and its index are gone, and the protocol and design docs
no longer name it.

The node still accepts a chat_msg carrying one, from the desktop apps and
CLIs already installed, and drops it. The column stays, empty, in chat.db:
a node downgraded to an older version names it in every query.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<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(cli): chat — Tier 2 check on the signing device, interactive room</title>
<updated>2026-10-15T00:06:35Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-15T00:06:35Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=419af660eeb8a4403e37a63c54a15586d04d5a8e'/>
<id>urn:sha1:419af660eeb8a4403e37a63c54a15586d04d5a8e</id>
<content type='text'>
Each message's signing device is checked against the group's roster as the
page checks it (a port of transport-roster.js, held to it by the parity
test): chains of countersignatures walked from each account's roots, the
keys accepted per account and node kept in the store, the roster read again
once before a key is called changed. Only "changed" is said, under the
message; --json carries every verdict.

chat with no group opens the interactive chat: the groups, then one group's
conversation IRC-style with pushed messages arriving live and a line to
write in; Esc or /part goes back to the groups, /quit or Ctrl+Q quits. Like
the bare command, it opens on the sign-in screen when nothing is stored.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(cli): invitations, join, decline, leave, devices, browser access</title>
<updated>2026-10-14T22:56:04Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-14T22:56:04Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=6f68bb6c1970e26de1f66c073ea5d7fecd21840d'/>
<id>urn:sha1:6f68bb6c1970e26de1f66c073ea5d7fecd21840d</id>
<content type='text'>
join accepts an invitation or redeems a link pasted as sent, then has the
node admit a key pair made here, with the invitation's code (a link's code
goes only to the node it names; one for a node that is away is kept for the
next connection). decline, leave and devices revoke ask first, and refuse
without --yes where there is no terminal. devices approve countersigns the
one waiting request a code matches, none when several do. browser-access is
the application's setting, kept per machine and never enabled from the hub's
mirror: on leaves a copy sealed under M on each node, off withdraws it,
unset touches nothing. A key pair made for a first contact is now kept.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix(client): link a device from the application; approve one match only</title>
<updated>2026-10-14T21:02:49Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-14T21:02:49Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=3131630d900aa4a72bf880bfa9c5232bff64d6d6'/>
<id>urn:sha1:3131630d900aa4a72bf880bfa9c5232bff64d6d6</id>
<content type='text'>
"Get a linking code" called the connection the page had just closed on the
node's unknown_device refusal, so it never filed anything. It now retries
with the request filed on that connection, before the proof (MNP 6.3), and
the page tries the group again after each refusal until a linked device
approves the code. Offered only in the desktop application: a browser's
minted identity is gone by its next connection.

Approving refuses a code that matches more than one pending request:
filing needs only the account's token, so somebody holding the passphrase
who saw a code could file their own keys under it.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(cli): meshbay-cli, a command-line client for members</title>
<updated>2026-10-14T20:20:15Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-14T20:20:15Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=422647e7898b8df67cd11f8fb060aec23dec84aa'/>
<id>urn:sha1:422647e7898b8df67cd11f8fb060aec23dec84aa</id>
<content type='text'>
Signs in to the hub, lists the account's groups and their folders, and
downloads and uploads files directly with each group's node, end-to-end
encrypted. With no argument it opens a two-pane interactive mode (Textual).
Session and device keys are kept encrypted under the system's key storage,
or a 0600 key file where there is none; node keys are pinned at first
contact; a new machine links as a device.

Packaged on its own on Linux (deb and rpm, on meshbay-common's venv, with a
man page generated from the parser) and frozen next to meshbay-node in the
full Windows installer, not the light one, with a self-test the build runs.
client/keys.py ports keyderive.js and is LGPL like it.

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