From 6f68bb6c1970e26de1f66c073ea5d7fecd21840d Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Thu, 15 Oct 2026 00:56:04 +0200 Subject: feat(cli): invitations, join, decline, leave, devices, browser access 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 --- packages/meshbay-cli/src/meshbay_cli/manpage.py | 74 ++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 9 deletions(-) (limited to 'packages/meshbay-cli/src/meshbay_cli/manpage.py') diff --git a/packages/meshbay-cli/src/meshbay_cli/manpage.py b/packages/meshbay-cli/src/meshbay_cli/manpage.py index 0633904..7ee3d33 100644 --- a/packages/meshbay-cli/src/meshbay_cli/manpage.py +++ b/packages/meshbay-cli/src/meshbay_cli/manpage.py @@ -15,29 +15,36 @@ from .__main__ import ACTIONS, build_parser EXIT_CODES = { 0: "Success.", - errors.USAGE: "Usage error: an unknown option, a missing argument.", + errors.USAGE: "Usage error: an unknown option, a missing argument. Also: an action " + "that asks for confirmation, run with no terminal and without " + "\\fB\\-\\-yes\\fR, or not confirmed.", errors.AUTH: "Sign-in refused, no stored session and no passphrase to sign in " "with, or the account is locked out.", - errors.NOT_FOUND: "A group, a path, or a pattern that matches nothing.", + errors.NOT_FOUND: "A group, an invitation, a path, a device or a pattern that " + "matches nothing; an invitation link no longer valid; a linking " + "code no device is waiting with, or several are.", errors.PARTIAL: "Some items failed; the others were done. Each failure is " "named on stderr.", errors.NODE: "No node serving the group could be reached, or the node refused " "the connection. Also: this machine is waiting for device " - "approval (the code is on stderr).", + "approval (the code is on stderr), or the node asks for an " + "invitation's code.", errors.NODE_KEY: "A node presented another key than the one pinned at first " "contact. Nothing was sent. See \\fBtrust\\fR.", errors.VERSION: "This client, or the protocol it speaks, is too old or too new " "for the hub or the node.", errors.REFUSED: "Refused before anything was sent: a name already taken or not " - "accepted by the node, a folder read-only or unavailable.", + "accepted by the node, a folder read-only or unavailable, leaving a " + "group you own, revoking this machine.", errors.INTERRUPTED: "Interrupted (Ctrl+C). A download resumes where it stopped " "on the next run.", } DESCRIPTION = r""" .B meshbay-cli -is a member's view of their MeshBay groups from a terminal: sign in, list the -groups and their folders, download and upload files. +is a member's view of their MeshBay groups from a terminal: sign in, join and +leave groups, list them and their folders, download and upload files, and +approve this account's other devices. It talks to the hub only to sign in and to find a group's nodes; files go directly between this machine and the node, end-to-end encrypted, never through the hub. @@ -159,7 +166,10 @@ The first time this machine opens a group whose node holds no copy of your keys (the application's "Browser access" turned off), it asks to be linked as a new device and prints a code. Approve that code from the application on a device already linked (the -group's Settings); with a terminal, +group's Settings), or with +.B meshbay-cli devices approve +.I GROUP CODE +on a machine already linked; with a terminal, .B meshbay-cli waits and goes on by itself, otherwise it exits with status 5 and the next run goes on once the code is approved. @@ -171,6 +181,46 @@ A node presenting another key is refused, with status 6, until forgets the pin; do that only for a key change the node's operator announced. """ +MEMBERSHIP = r""" +Joining has two halves. +The hub makes the account a member: +.B join +accepts an invitation listed by +.BR invitations , +or redeems an invitation link pasted as it was sent. +Then the group's node admits it: a key pair is made on this machine, the node +wraps the group key for it, and it is kept (see FILES), so +.B join +needs a saved session. +A link carries the code for the node it names, and is sent to that node only. +An invitation's code is given with +.BR \-\-code , +or typed when the node asks for it; a node that cannot be reached gets it at the +next connection. +.PP +.B leave +ends a membership on the hub. +The node keeps what it holds (the key it pinned, its copy of your keys, the +files you uploaded) until its operator removes them, and the group key already +served still opens what it opened until the operator replaces it. +The owner of a group cannot leave it. +.PP +.B devices +lists this account's devices on the node serving a group, approves a new one by +the code it shows, and revokes one. +Exactly one waiting device must match a code: a code that matches several, which +somebody who saw it on your screen could cause, approves none. +.PP +.B browser\-access on +makes this machine leave, on each node it opens a group on, a copy of its keys +sealed under your passphrase, so that a browser can open the group; +.B off +withdraws that copy. +Never set, nothing is written or withdrawn. +It is this machine's setting, as Browser access is the desktop application's: +the hub keeps a copy for browsers to read, and that copy never turns it on here. +""" + FILES = r""" .TP .I $XDG_DATA_HOME/meshbay\-cli/ \fR(default \fI~/.local/share/meshbay\-cli/\fR) @@ -178,9 +228,9 @@ On Windows, .IR %LOCALAPPDATA%\emeshbay\-cli\e . Holds .B state.json -(the hub, the account name, pinned node keys), +(the hub, the account name, pinned node keys, the browser access setting), .B secrets.enc -(the session and keys, encrypted), +(the session, the keys, invitation codes waiting for their node; encrypted), .B store.key only where the system has no key storage, and .B interactive.log @@ -222,6 +272,9 @@ The interactive mode draws without colour. EXAMPLES = r""" .EX meshbay\-cli login \-u alice +meshbay\-cli invitations +meshbay\-cli join Family@bob \-\-code K7P2\-9WQX +meshbay\-cli join 'https://meshbay.org/#/invite?v=1&g=...' meshbay\-cli groups meshbay\-cli ls \-l Family/photos/2024 meshbay\-cli get \-R Family/photos/2024 \-o ~/Pictures/ @@ -229,6 +282,8 @@ meshbay\-cli get 'Family/music/*.flac' meshbay\-cli put \-R ~/scans Family/documents tar c notes | meshbay\-cli put \- Family/documents/notes.tar meshbay\-cli ls \-\-json \-R / | jq '.[] | .path' +meshbay\-cli devices approve Family@bob ZX4P\-7QRT +meshbay\-cli leave \-\-yes Club@carol .EE """ @@ -326,6 +381,7 @@ def render() -> str: out += [".SH REMOTE PATHS", PATHS.strip(), ".SH INTERACTIVE MODE", INTERACTIVE.strip(), ".SH SESSION, DEVICES AND NODE KEYS", SESSION.strip(), + ".SH GROUPS: JOINING, LEAVING, DEVICES", MEMBERSHIP.strip(), ".SH EXIT STATUS"] for code, text in sorted(EXIT_CODES.items()): out += [".TP", f".B {code}", text] -- cgit v1.2.3