<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/second-review.md, branch 0.7</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.7</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.7'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-08-18T00:14:39Z</updated>
<entry>
<title>docs: settle the desktop client, and draft v6</title>
<updated>2026-08-18T00:14:39Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-18T00:14:39Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=50ebb4f2e620dad8e1fbca8307b97c5e10e7e6c0'/>
<id>urn:sha1:50ebb4f2e620dad8e1fbca8307b97c5e10e7e6c0</id>
<content type='text'>
A design discussion on 2026-08-17 settled Phase 13 and, in doing so, changed
four things the spec states. v6 restates only those; v5 stays authoritative for
everything it does not touch, per the convention v5 itself used with v4.

What changed:

  * The native shell is **Electron**, not pywebview — structural decision 18
    reversed. The SPA depends on Chromium-class APIs (WebRTC, WebCrypto
    X25519/Ed25519, MSE, Service Workers), so keeping Chromium keeps
    transport.js, crypto.js, keyderive.js, downloads.js and sw.js *as the
    client*. A system webview meant reimplementing ~2500-3000 lines. The old
    "69 % reused" figure was measured against an app.js of ~2600 lines; it is
    4586.

  * A group's content is **several named roots**, not one directory, because
    the planned video and audio libraries will not live in one folder on one
    disk.

  * **Device linking**: one person may hold several devices on a node,
    admitted by a key the node already pinned and bound by a one-time code the
    new device generates. Without it a native client is refused where a browser
    is not, and an account created natively could never be opened in a browser.

  * **Authorship is authenticated, not asserted** — chat senders sign, uploads
    have a provable owner, and delete authorization moves from the uploading
    key to the account.

And one rule v5 assumed without writing down: **group-related server state
lives on the node.** Verified for multi-root — SwarmSource carries hashes and
endpoints, no paths.

Also here: the Caddy configuration, which was a snippet in the roadmap that
would have broken the SPA (it predates /a/&lt;hash&gt;/ asset versioning and would
have 404ed /sw.js, silently killing streamed downloads on Firefox and Safari);
and downloads.html, which becomes a security page once a release key exists.

Phase 15 was re-read against device linking and is wrong as written: a sender
key must be per **device**, never per person, or two devices sharing a chain
produce key and nonce reuse — C1 again, one level down. senderkeys.py already
fails this silently.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>docs: Argon2id, the multi-browser property, and what a browser found</title>
<updated>2026-08-14T12:43:48Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-14T12:43:48Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=9fa2117de1caf4d713cc0b7a310b9549467738c3'/>
<id>urn:sha1:9fa2117de1caf4d713cc0b7a310b9549467738c3</id>
<content type='text'>
draft-v5 §7 rewritten around the keypair bundle, because that is where the last
open finding actually lives. New §7.1 states the adversary (an operator holding
their own node's disk), what cracking a bundle yields (identity keys, hence
content on *other* nodes and the ability to sign as that user — not the content
they host in the clear by design), and the measured numbers rather than
adjectives: PBKDF2 241 ms vs Argon2id 88 ms natively, a GPU ceiling moving from
~8k to ~2k guesses/s, six days for a 10⁹ dictionary run, four random words
outlasting the sun. The honest summary is in there too — a factor of four on one
card, not a thousand; what it buys is the cost of scale.

§2 gains the row the table never had: **your identity keys stay yours**, ⚠️
against a malicious node operator. An operator hosts your content by design, and
that was documented; that they can also try to become *you* was not. That is the
difference between reading what they host and reading what other operators host.

§4 records that the challenge now carries `node_pk`, why (a first-time member
signs a transcript naming the node and has no GEK to complete a handshake with),
and that it is checked against the ack rather than trusted. Also that refusals
carry a code, and what `not_a_member` usually means.

§8.1 states the multi-browser property plainly — one identity across browsers,
recovered with the passphrase, no second code — together with its cost, since it
is the same mechanism as C4.

invite-pairing-v1 is no longer "a proposal": it shipped. §9bis gains the four
browser-found failures and their common thread — e2e.py is a second
implementation of the client, written in the right order by construction, so it
proves the protocol and nothing about app.js.

CLAUDE.md gets the two things a future session must not rediscover the hard way:
the KDF parameters live in three places held identical by a parity test, and an
unbounded await on the hub socket makes a node silently unreachable (three found).

second-review: C4 marked reduced, not closed. devel-phases-next: 12.2's CSP must
keep `wasm-unsafe-eval`, or the strict policy locks every user out of their keys.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>docs: record the invite redesign — H3 and M3 closed</title>
<updated>2026-08-13T23:28:12Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-13T23:28:12Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=d7120761fe8cf406f374ef769db6e1f9bf1fe287'/>
<id>urn:sha1:d7120761fe8cf406f374ef769db6e1f9bf1fe287</id>
<content type='text'>
draft-v5 §2: against an active hub, reading content moves from "❌ H3" to
"❌ T3 (browser) · ✅ native". The defensible sentence becomes "the hub cannot
read your content unless it ships you malicious client code" — T3 is now the only
path, it is an artifact rather than a silent directory lie, and it does not exist
for a native client. New §5.5 describes admission and key delivery, with the four
properties that carry it and the one exception (open-join groups, where the hub
can walk in the front door — a property of open joining, and the setting is read
from node.toml).

Corrected while writing it: §5.1 said the C5b fix stopped a group admin who does
not run the node from inviting, and that the redesign reverses this. It does not,
because delegation was deferred. What changed is the timing — the operator issues
a code and is then out of the loop.

devel-phases-next: 12.1 is done and NOT as written. The plan was key transparency
plus safety numbers; what shipped removes the directory read instead. Safety
numbers make substitution detectable by a human who checks, at first contact,
when there is nothing to check against. 12.2 (served-SPA integrity) is now the
highest-value item in that phase. Phase 14 marked for what landed.

second-review: H3 and M3 annotated closed at the finding, with what actually
closed them. The §7 verdict table is left intact — it is the record of an audit
on a date, and falsifying it would be worse than leaving it — with a note
pointing at draft-v5 §2 for current state.

CLAUDE.md matters most here, being loaded every session: NS4 read "admin_pk_ed25519
auto-pinned from keystore ✅ DONE", which is M3 described as a feature. Rewritten,
with the two fixes that must never be attempted (auto-pin, hub lookup).

QE/deploy/README.md: set-admin-pk retired from the walkthrough; the regression
checklist now exercises pairing, joining by code, recognition without a code, and
revocation.

USERGUIDE.md is beyond the invite work but was actively wrong: it told users to
POST GEK bundles to a hub endpoint deleted in Phase 12, and to re-wrap for every
remaining member on revocation. Both replaced with what the code does.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>docs: second security review + roadmap rewrite</title>
<updated>2026-08-13T01:56:30Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-13T01:56:30Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=ee6573c57f721db8550e34e1c1c79c5922c62a4b'/>
<id>urn:sha1:ee6573c57f721db8550e34e1c1c79c5922c62a4b</id>
<content type='text'>
Second architecture and security review (second-review.md): 6 critical and
7 high findings against the Phase 12 implementation, plus an assessment of
whether the system meets its end-to-end confidentiality claim.

Roadmap rewritten against those findings (devel-phases-next.md): new blocking
Phase 11.5 (security remediation), Phase 12 (hub minimization), Phase 13
(native desktop client). Old phases 12-17 renumbered to 14-19.

tmp-decisions.md records two open decisions: whether the hub keeps serving
the web UI, and browser extension vs native desktop client vs both.

CLAUDE.md and devel-phases-next.md also carry pre-existing Phase 12 edits from
the working tree that could not be cleanly separated from the review changes.

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