| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
| |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
| |
Windows
packages/meshbay-client/build/_pip-audit (and its siblings) is made by the
Windows build and was untracked noise. test_packaging_default_env checked a
POSIX file mode that Git's bash on Windows cannot set.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A `meshbay-cli chat --follow` left open holds node-runtime's DLLs, so the
previous version's uninstaller failed ("Failed to uninstall old application
files"), a silent update included, and left the node it had stopped not
running. stop-node.ps1 now ends a meshbay-cli.exe run from this install
(-InstallDir, setup's $INSTDIR), and no other copy.
Found through CIM, not Get-Process: setup runs the 32-bit PowerShell, which
reads no path for a 64-bit process, and the first version of the stop matched
nothing. The test runs the script in that PowerShell. Checked live: an update
over a running follower now ends it, replaces every file and restarts the node.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Its suite had only run on Linux. On Windows, against a real hub and node and
from the installed meshbay-cli.exe:
- secrets.enc was written in text mode (os.open without O_BINARY): every 0x0A
of the ciphertext became CR LF and the saved session "does not open with
its key" on the next run.
- isatty() is true for NUL, so a script run with `< NUL` or by the Task
Scheduler was asked questions instead of told to pass --yes;
output.terminal() checks for a real console.
- Ctrl+C waited for the selector loop's next timer, up to half a minute in
`chat --follow`; the loop now points the signal wakeup at its self-pipe,
as the proactor does.
- Right-click copy and paste raised: asyncio cannot start a process on the
selector loop; the clipboard tool runs in a thread.
- Tab completion of remote paths ran on the default (proactor) loop, which
never opens a node, and wrote in the locale encoding; the PowerShell script
now reads it as UTF-8.
- `get -R` into a folder past MAX_PATH died with a traceback; get, put, the
resume file and the interactive mode use the extended form at each disk
call, as the node does.
- `groups` showed a SQLite hub's naive UTC time as local time.
The opt-in end-to-end suite now runs on Windows (16 tests: Chrome found under
Program Files and started with the real environment, VLC as the player, Ctrl+C
through a console of its own, PowerShell 5.1 completion of an accented name).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
| |
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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
No lock file pins the dependencies, so each build installs the newest
releases and what ships is only known once it has. packaging/audit_deps.py
runs pip-audit then: build-common.sh on the venv before stripping it,
build-node-runtime.ps1 on the environment before PyInstaller freezes it.
A known vulnerability stops the build, unless its id is listed in
packaging/pip-audit-ignore.txt with why it does not apply. No network only
skips the audit with a warning, as does a pip-audit that cannot be installed
or writes no report. pip-audit runs from a venv of its own, never from the
one that ships. Our packages are not audited (not on PyPI), nor pip,
setuptools and wheel, which do not ship.
Checked with the real build-common.sh (79 packages, none known), with
PyJWT 2.14 (the build stops on its two advisories, and goes on once they are
listed) and offline (a warning, the build goes on). The PowerShell step was
not run here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
test_a_scan_asks_the_disk_nothing_from_the_event_loop patched Path.stat,
and since the indexer learned Windows' long paths it calls
os.stat(long_path(p)) and os.scandir instead: the guard saw no call at all,
and asserting that the calls ran on the indexer's thread failed on an empty
set. It watches os.stat and os.scandir now (Path.stat goes through os.stat
too), counting what the root holds and not the root, whose availability
check runs on the roots' I/O thread. Nothing runs on the loop; a stat added
there makes it fail again.
The node CLI's parser names itself: under `python -m pytest`, Python 3.14
named the program after the module, so test_cli_golden saw "python -m
pytest" in the help. The installed meshbay-node was not affected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
| |
pip-audit reports two advisories against 2.14.0, both fixed in 2.15.0.
PYSEC-2026-4141 reaches the hub: federation.py decodes a peer's token
without verifying it first, and a deeply nested payload raises a
RecursionError there, an unauthenticated 500. PYSEC-2026-4183 does not:
no key is imported from a JWK. The builds resolve the newest release
anyway; the floor keeps an older environment from satisfying them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The Node page and the CLI remove access through the loopback API, and
revoke and unpin there wrote nothing to audit.db; only the signed MNP door
did. A removed person's next connection then showed an auth_failed with
nothing before it to explain it. Both routes now record member_revoke and
member_unpin once the operation has succeeded, with the node's own account
as the actor and 127.0.0.1 as the address, which tells the two doors apart.
A refusal changes nothing and records nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 <group>" 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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
build-node.sh and build-node-runtime.ps1 copied QE/default.env whole into
every deb, rpm and Windows build after checking only its first 30 bytes. The
file is unversioned and sits beside other QE notes, so any line added to it
later would have gone out publicly. Only its first line ships now, and only
once it is exactly MESHBAY_TMDB_DEFAULT_TOKEN=<JWT>; a missing file, a BOM,
a token not on the first line or an empty one still stop the build.
The Linux step is run by a test against a scratch repo; the PowerShell one
has the same rule and was not run here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
account shows the account and does what the sign-up form and the Profile
page do: register (the passphrase floor and the hub's proof of work checked
here, the recovery key printed once), verify, change the passphrase, reset a
forgotten one, change the e-mail address, sign out everywhere, delete. A new
passphrase carries the copy of the account's keys each node keeps for
browsers first — opened under the old M, the same keys sealed under the new
one — and only then tells the hub; a refusal sets the copies back. A reset
restores them from the recovery copy. The connections that do it never make
keys nor ask for a device approval. This machine keeps the M it changed away
from, so a node out of reach is carried at its next connection; a copy under
an M it does not know is no longer rewritten, which locked the browsers out
after a passphrase changed elsewhere.
rm -r removes a folder and all it holds, from the node's operator key: the
files, then the folders deepest first, one confirmation that counts them.
mkdir makes folders, --parents the missing ones (not -p, the passphrase).
completion bash|powershell prints the script that makes Tab complete actions,
verbs, options and the paths of the groups this machine is signed in to,
cached two minutes; the deb and rpm packages install the bash one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A member pinned on the node who then redeems the operator pairing code was
written down as the operator but the node kept its "nobody can authorize"
flag until it restarted: every admin operation — removing a folder, inviting,
the apps' settings — was refused meanwhile. Only a key paired fresh set it.
The join result now names `operator` for an account holding the node-wide
operator row, whatever its row in the group says. The page and the CLI read
that role to know what to offer, and refused before asking deletions the node
would have accepted. Nothing is granted by it: every admin operation is still
checked against the operators' keys.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`meshbay-cli stream PATH` serves one video or sound file over HTTP on
127.0.0.1 for VLC, mpv or any player that reads HTTP; `--player PROGRAM`
starts the player, and closing it stops the stream, as Ctrl+C does.
The file goes as the node stores it: no remux, no transcode, no stream
slot on the node. Byte ranges are answered from leaseless file_req chunks
decrypted in memory, eight ahead and the last 24 kept. Loopback only, a
random token in the address, a foreign Host refused (DNS rebinding), an
audio or video type with nosniff. The connection is pinged and reopened
when it dies; a refusal by the node stops the stream (exit 5).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
/put FILE sends one local file, relative to the current directory or
absolute, into the chat's folder, then posts the application's attachment
message naming it ({"text": "", "attachment": {filename, size, type}}), so
the page shows it as its paperclip's. /get NAME saves a file of that folder,
named from it, into the current directory, never over a file already there.
The chat's folder is the page's rule: the operator's choice while its root
is writable and present, else the first such root; a chat_directory_ack
moves it. A line above the one written in shows the transfer's progress.
Attachment messages, from the page or from /put, read as [file: name, size]
in the room and in `chat`, and as an `attachment` field with --json.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
help prints what --help prints; help ACTION, what ACTION --help prints.
In the interactive chat a right-click on the conversation copies the text
selected with the mouse, else the line under the pointer: to the terminal
(OSC 52) and to the platform's clipboard tool. A right-click on the line
written in pastes the system clipboard's text at the cursor, its lines side
by side, read with wl-paste, xclip or xsel, pbpaste or PowerShell, else what
was copied here last. The conversation is selectable with the mouse, which
RichLog alone is not. The deb and rpm packages recommend wl-clipboard or
xclip for the paste.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 -> 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 -> Link Node point at Profile -> Linked nodes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
chat GROUP --follow prints the last messages, then each one the node pushes,
until Ctrl+C (exit 130). The connection is pinged every half minute; one
that closes, fails or stops answering is opened again, and what was said
meanwhile is read from the history. Each message is printed once, by its
(device, nonce) pair, which the node stores once. With --json, one object
per line. The man page lists it, with an example, and its FILES now names
the device keys kept for the Tier 2 check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
chat GROUP prints the last ten messages, oldest first (-N, as head -N, or
-n N for another count, paging back past the node's 200), and -m posts one
(- reads it from stdin). The application's construction: every epoch key
from chat_keys_req, a post sealed under the current epoch through the
device subkey and signed with this machine's key on the node, the sender's
name inside the envelope; nothing sent past the node's ciphertext bound.
A stored message is read signature first, then key, then content, and one
that fails is shown as unreadable, never dropped. Not done here: the Tier 2
roster check on the signing device.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
search dials every group through the pool and matches each index here, on
the Search page's fields (name, folder, title, artist, album), every word
required. A group left out of Search by its operator (search_listed in the
sealed ack) is skipped before its index is asked for. A file several groups
hold is one result, keyed by its content hash, printed from the reader's own
node first, as a path get takes. A group that cannot be searched is named
and the others go on; one waiting for this machine's approval names its code
instead of holding everything up.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
rm deletes files, resolved as get resolves paths and patterns, with the
node's rule (design §5.4): the uploading account's devices, or the node's
operator account. The whole run is checked against the index first (the
entry's uploader_id, the role the join result gives this key): a file
outside the rule, or a folder, refuses it before anything is asked or sent.
Then one confirmation, or --yes. The node's challenge is checked against
what was asked before it is signed. In the interactive mode, Delete on the
right pane does the same, asked once per batch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
| |
Revoking a device or removing a member opens a chat epoch, announced to
everyone connected to the group, the asker included. Sent inside the
handler, the asker's copy was stamped with its request's id and arrived as
the answer to device_revoke, before the real one. It now leaves outside the
reply context.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
| |
A browser keeps no identity between connections, so a key approved for it
is gone by the next one: the guide, the design and the interface no longer
offer it. With browser access off, the application and the command-line
client open the account's groups; the linking form, shown in the
application only, now says "this computer".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
"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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
| |
A new device of a known account holds no identity the node pinned, so it
cannot complete a handshake until a pinned device approves it: it now files
device_add_request in the pre-proof window, as the desktop app's case
already required. The request stays inert until countersigned; at most 10
are pending per account, the oldest dropped. A 6.2 node answers it
"Handshake required", which a client reads as "cannot link here".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
With the system's default setting (LongPathsEnabled off) every call given
a plain path of 260 characters or more refuses it, so a deep library was
partly invisible: the walk could not list such a directory and its files
never reached the members.
The node now hands each call that touches a group's disk the extended
form (paths.long_path), and keeps the plain path in the index, the hash
cache and the log. A directory is listed under its long form and its
entries named from the plain one (indexer.walk_files, wire._walk_dirs).
Covered: the walk, stats and hashing, reconcile and the watcher, the
folder list members see, serving over WebRTC and QUIC, deletion, uploads
and their recovery, folder creation and removal, audio tags and the
cover beside a track, photos, and a show's episode numbering. ffmpeg
extends a long path itself and keeps the plain one.
long_path now normalises before prefixing (the extended form skips the
system's normalisation) and starts at 248 characters, where creating a
directory is already refused.
test_long_paths.py runs with the setting off: 15 of its 17 tests fail
without the change. Checked by hand in the installed app with files at
312 to 380 characters.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A Windows tester's scan stuck for good on one directory of a large disk:
one read that never returned held the indexer's only thread, and with it
every root behind that one.
- A disk call is timed by its silence, not its length: each directory
entry listed and each megabyte read counts as an answer. After 60 s of
silence the call is abandoned on its daemon thread, the file is noted
unread and the scan goes on.
- Three silent files in a row pause the root (not persisted). Resume
skips the files already known to give no answer; a restart, a replug
or a change to the file retries them.
- The walk is per directory with os.scandir: a subdirectory that cannot
be listed costs itself, and a listing that stops answering pauses the
root at once. A scan no longer stats anything from the event loop.
- The log names the file after 10 s of silence, the indexing band shows
it, and Group settings shows the paused root, where it stuck and the
unread files with their reason, on the node's machine only.
- generate_http_api.py writes LF on Windows too.
Verified with real kernel-blocked opens (an unacknowledged oplock) in the
installed frozen app.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
| |
The probe followed the browser's language, so its assertions on
English labels failed on a machine set to French.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Connection processes and the larger UDP receive buffer were written and
measured on Linux; nothing had run on Windows, and `meshbay-node.exe
webrtc-worker` had never run from a frozen build on any system.
- test_connection_processes.py failed on Windows (8 tests): the selector
loop the suite uses there cannot start a process. A test marked
`daemon_loop` now runs on the daemon's own loop, chosen through
pytest-asyncio's loop factories.
- The build starts both frozen executables as connection processes and
carries a connection through each (smoke-connection-process.py). The
daemon's own smoke test never signs in to a hub, which is when the
processes start.
- The warning for a receive buffer below what was asked named
net.core.rmem_max on every system; it names it on Linux only. Windows
grants the 4 MB.
Measured on an installed build in service mode, docs/WINDOWS-PORT.md §5.12:
two processes at startup and on a live change, a browser's handshake, chat,
a 200 MB download over 8 connections across both processes, an upload, a
video stream, and stop, restart and start leaving no process behind.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
| |
Node and Create group left the sidebar for the user menu. A source-reading
test still looked for the old `showNode=` expression and failed everywhere;
the installed application's end-to-end test waited for "Create group" in the
sidebar and would have timed out. Both now check the menu, and the packaging
guide says where the two entries are.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
| |
The bar was 457 px wide and pushed the close button to 397..437 px, off a
360 px phone. Delete leaves the lightbox (it stays on the tile's menu:
right-click, or press and hold), and below 768 px the bar drops the file
name, the zoom label and 100%.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Search is an icon in the nav, left of the tray button and the bell, and marks
itself current on its page. Administration, Node, Create group and Android
Sync moved to the user menu, between Settings and the theme, each under the
condition it had in the sidebar. The sidebar keeps Public groups and the
groups.
On a phone, a tablet or the Android application the menu trigger is the
avatar alone (max-width 768px or a coarse pointer); the name is the dropdown's
first line, one line with an ellipsis. Measured: a 20-character handle put the
trigger 159 px off a 320 px screen with search and transfers in the nav, and a
64-character one pushed the dropdown 122 px off the left.
Creating a group is a desktop-application feature by design: a hand-typed
#/create-group no longer opens the form in a browser, and QUICKSTART step 6
now says to use the desktop application instead of the browser.
test_layout_responsive read only the first 768px media block; it reads them
all now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A line under the Register button: creating an account accepts the hub's
terms of use, and the law requires the hub to keep the connection log (IP
address, date, action) for one year, even after the account is deleted. It
links to the legal pages of the hub in use, so a self-hosted hub shows its
own operator's documents.
A notice, not a checkbox: the account rests on the contract and the log on a
legal obligation, so there is no consent to ask for, and one that blocks
sign-up would be neither free nor withdrawable.
legalUrl() moves to platform.js, shared by the sidebar and the form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
| |
The page reads its settings from list_groups, which lacked cpu_count,
so the field showed "of 1" and stayed at 1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
| |
Uploads ran at 6.5 MB/s because the kernel dropped datagrams at the
node's 256 KB socket. Asking for 4 MB gave 19.5 MB/s, no drop.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
| |
connection_processes (default 1) starts that many processes for the
WebRTC stack; sessions and keys stay in the node. Set from node.toml
or the Node page, applied to new connections.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
| |
One WebRTC connection carries 5 to 6 MB/s whatever the line can do.
A leased download of 64 MB or more now opens seven more to its node,
and a lease serves the other connections of its device in its group.
Measured through the whole stack: 5 MB/s before, 24 after.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
| |
One INFO line per lease: bytes, duration, rate, and the SCTP
association's window, round trip, losses and T3 expirations.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
| |
Slices are asked for in the address, not a Range header the WebView drops;
a settings change runs at once; the notification is updated once a second;
the SMS section says how to lift Android's restricted setting; the photo
section says whether videos are included.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
| |
A WhatsApp section takes WhatsApp's folder through the picker, sends its
encrypted Databases and Backups (not the dated copies of earlier weeks) into
<folder>/<account>-whatsapp, and names the restore set in the manifest.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
| |
Photos, videos and files record, per file, their path on the node, their path
and album on the phone, dates, size and SHA-256, uploaded as
meshbay-manifest/manifest-<date>.jsonl once the run is done.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
| |
A Files section takes folders through the system picker (no storage
permission), refuses DCIM, Pictures and Movies, skips what the photo backup
sends, and runs on the photo backup's own runner into <folder>/<account>-drive.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|