aboutsummaryrefslogtreecommitdiffstats
path: root/packages
Commit message (Collapse)AuthorAgeFilesLines
* feat: move the desktop client's Hub section from Settings to ProfileChristophe Besson11 hours12-35/+35
| | | | | | | | | | | The hub address is where the person's account lives, so it sits with the account: on the Profile page, after Sessions and before deleting the account. Settings keeps "Keys on this device", which describes the machine. The hint now says what the setting is: the hub this application connects to, and that changing it signs you out while the account stays on that hub. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: generate an HTTP API listing for the hub and the node control APIChristophe Besson11 hours23-4/+138
| | | | | | | | | | | | | | | | | | | 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 <noreply@anthropic.com>
* feat: prefill https://meshbay.org on the desktop client's hub screenChristophe Besson12 hours12-15/+4
| | | | | | | | The first-run "Which hub?" field now starts filled with meshbay.org; it is still asked, so the client can be pointed at another hub. The note under the form, which explained there was no default, is removed with its catalogue key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(node): print "running" once in meshbay-node statusChristophe Besson12 hours1-1/+2
| | | | | | | | The daemon line repeated the state the daemon reports ("running — running"). The state is now appended only when it says something more than "running", such as waiting_for_hub. The QUICKSTART example is updated to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: read the node token per call and detect before polling the index dockChristophe Besson12 hours2-11/+24
| | | | | | | | | | | | | node:op only knew the daemon's token once a page had called detect(), and kept it after the daemon replaced it on restart: the index dock stayed empty on a node machine until the Node page was opened, every operation answered 401 after a node restart, and on a machine without a node each 30 s poll was a rejected IPC call Electron printed to the terminal ("Node not detected"). node:op now reads the config and token from disk on every call, and the dock asks detect() before its first operation and after any failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore: license MeshBay — LGPL protocol layer, AGPL for the restChristophe Besson12 hours37-3/+4354
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | The protocol layer is LGPL-3.0-or-later in every language it exists in, so any client may use it whatever its own licence: meshbay-common, and the files marked with an SPDX line — keyderive.js, crypto.js, playlist-crypto.js, transport*.js; keyring.js, transcripts.js and argon2-wasm.js on the desktop; Kdf.kt, Keyring.kt and Transcripts.kt on Android. Everything else is AGPL-3.0-or-later, which the RPM specs and package.json already declared without a licence file to back them. Two AGPL section 7 permissions: - group applications may be under any licence when they use the interface only through a named surface (static/licenses/APPLICATION-EXCEPTION.txt); the reference application is 0BSD so that copying it brings no AGPL code; - the Android application may be conveyed linked with Google Play services. Third-party code is accounted for: THIRD-PARTY-NOTICES.txt is generated from what a build ships (packaging/third_party_notices.py) for the deb/rpm venv and the frozen Windows node — PyAV's wheel grafts in libx264 and libx265, which its BSD licence does not mention — and the vendored browser libraries get their licence texts and htm-preact.js its provenance. Wheels carry SPDX metadata, RPMs %license, debs a DEP-5 copyright file, every Windows target LICENSE.txt. test_licensing.py holds the line: the LGPL layer imports nothing under the AGPL, the reference application nothing outside the application interface, and every SPDX line is one of the known ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): launch icon stays up for at least half a secondChristophe Besson19 hours1-0/+23
| | | | Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(cast): music on the TV, the music bar as its remoteChristophe Besson19 hours21-408/+1274
| | | | | | | | | | | | | | | | | A cast button in Music's toolbar and in the music bar. With a television chosen, each decrypted track goes to the relay with its cover — found as the album card finds it — and plays there as music with its title, artist and album; the bar's play, pause, seek, previous and next drive the receiver, its clock is the receiver's, and the end of a track there moves the queue on. A film or a photo taking the television pauses the bar; stopping the cast carries the track on locally. Photos and tracks now share one path: a whole file sent to the relay in pieces (binary frames on Android, written to disk there), served at /file with byte ranges and its cover at /cover, and loaded as what the relay says it is. cast:image is gone; cast:chromecast:seek is new. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(cast): photos on the TV, and a television chosen once for the sessionChristophe Besson20 hours28-45/+1137
| | | | | | | | | | | | | | A cast button in Videos' toolbar, at the top of Photos, in an album's bar and in the lightbox, in a group and in Search alike. A television chosen there is kept for the session: a film opened plays on it with the player as its remote from the start, and a photo opened in the lightbox is shown on it, scaled to 1920x1080, upright, as JPEG. The lightbox gains a slideshow. The relay serves one photo at /image behind the stream's token, on the desktop and on Android; the shell, not the page, decides that the receiver loads it as a picture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(hub): music keep-alive outlasts a skipped trackChristophe Besson22 hours1-7/+15
| | | | | | | | Held while a track plays or loads and released 5 s late, so skipping a bad file with the screen off no longer drops the Android foreground service, which cannot be taken back from the background. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): music keeps playing with the screen offChristophe Besson22 hours11-20/+81
| | | | | | | | While a track plays, the page asks the shell to stay awake (playback:keep-alive): on Android the cast's foreground service and visible WebView, with a notification; on desktop a power save blocker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(hub): music player retries a track lost to a screen-off disconnectChristophe Besson23 hours1-3/+60
| | | | | | | | A transport failure while the page is hidden, or within 30 s of waking, keeps the track and its spinner and retries once the page or the connection is back, instead of skipping it with an error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(android): music player starts on its own and no longer shows autoplay ↵Christophe Besson23 hours2-2/+7
| | | | | | | | | refusals WebView now allows play() after the track fetch; a NotAllowedError leaves the track waiting for the play button instead of raising an error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore: bump version to 0.18.0Christophe Besson2 days8-8/+8
| | | | Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Player: redesigned cast remoteChristophe Besson2 days14-74/+254
| | | | | | | Skip buttons with circular arrows, filled scrubber, large play/pause, device header; the remote is its own component. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Player: remote control while castingChristophe Besson2 days14-9/+280
| | | | | | | Shows the receiver's position with play/pause, ±30 s and a scrubber; a seek restarts the relay where asked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Cast: receiver position and pause/play on both clientsChristophe Besson2 days7-0/+102
| | | | | | | The player's remote mode reads where the television is instead of the local playhead, which drifts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(android): cast context created at launch, session found if its callback ↵Christophe Besson2 days2-2/+28
| | | | | | | | | is missed As the SDK recommends; and a connected session the listener did not hear of still counts, so a missed callback no longer fails the cast. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(android): the cast header is everything before the first moofChristophe Besson2 days3-3/+74
| | | | | | | | The node's first chunk can be the 28-byte ftyp alone, the moov in the next; served as the header, the receiver had no moov and gave up. A receiver early for the header now waits for all of it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(android): release builds signed with the debug key for nowChristophe Besson2 days1-1/+7
| | | | | | | Not debuggable, no WebView devtools, no console forwarding; installs over a debug build and back. A stand-in until the release key (Stage D12). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(android): the cast relay spools a receiver's lead to diskChristophe Besson2 days4-44/+143
| | | | | | | | Fragments are 5-10 MB at a film's bitrate; dropped past 8 MB in memory, the TV froze for their length. Each receiver now reads from its own spool file, deleted with it; nothing is dropped short of a disk bound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): log what a cast does downstream of the relayChristophe Besson2 days2-3/+57
| | | | | | | | Fragments dropped for a slow receiver, writes that block, a periodic per-client summary, and every receiver state change with its position — the only trace a freeze on the television leaves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): the MeshBay iconChristophe Besson2 days10-0/+46
| | | | | | | The desktop client's icon in the adaptive icon's safe zone, over its own edge colour, so no launcher mask crops the M. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): the local player is silent while castingChristophe Besson2 days2-0/+33
| | | | | | | It keeps playing to pace the relay, so it doubled the television's sound. The viewer's mute setting comes back when the cast ends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(android): cast relay serves a clean header and restarts on its portsChristophe Besson2 days5-12/+159
| | | | | | | | The init is what precedes the first moof; ports are reused like Node's; the SDK is read on the main thread; a cast that fails says why on screen, and success waits until the receiver actually plays. Never a VPN's address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): a seek's first segments are held while it lands, not droppedChristophe Besson2 days3-3/+106
| | | | | | | | They are the new stream, header first. Dropped, a cast relay restarted at the landing got no ftyp/moov and the receiver gave up; they are now replayed in order once reinitAt/resumeAt is done. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): casting through a LAN relay and the platform cast SDKChristophe Besson2 days17-35/+1176
| | | | | | | | A port of cast-relay.js (backlog also bounded in bytes), discovery and control with the default media receiver, relay calls kept in order, and a foreground service plus a WebView kept visible so a cast survives the screen going off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): downloads to disk and uploads through the system pickerChristophe Besson2 days10-11/+624
| | | | | | | | Native save over the Storage Access Framework and MediaStore, chunks sent as binary bridge messages, a chosen folder that has gone asks rather than redirects, unfinished files removed on abort and after a killed process. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): a download written to disk no longer holds the whole fileChristophe Besson2 days2-0/+57
| | | | | | | pipelinedDownload kept every chunk's resolved promise until the end; a 2 GB download held 2 GB in the page. Each is released once read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): device key, bundle key and node identities held nativelyChristophe Besson2 days18-8/+1327
| | | | | | | | Keystore-wrapped store, a Kotlin port of keyring.js and transcripts.js held to the shared vectors, the same keys/device/secrets bridge as the desktop, and a native confirmation before browser access is widened. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): the node setup welcome is for a build that has a nodeChristophe Besson2 days2-1/+15
| | | | | | | Gated on capabilities.nodeAdmin rather than on any bridge, so a phone with no groups sees its invitations and the join link. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): client shell with the interface from the packageChristophe Besson2 days26-0/+1560
| | | | | | | | WebView over the packaged UI (copied from hub/static at build time), the desktop CSP as a header, a bridge answering our top-level document only, hub calls from native to the signed-in hub. Keys stay in the page for now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(hub): shared keyring and transcript vectorsChristophe Besson2 days3-0/+716
| | | | | | | One file every bundle/transcript implementation must reproduce, generated from the desktop keyring; checked against it and against the specification. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Merge branch 'main' of meshbay.org:meshbayChristophe Besson3 days45-6062/+502
|\
| * refactor(mnp): remove ten operator messages no client sent0.17Christophe Besson3 days20-4335/+132
| | | | | | | | | | | | | | | | | | node_status, node_settings_set, roster_read, denylist_read, denylist_clear, node_reload and the signed gek_rotate, member_unpin, transfer_limits, group_detach leave MNP 6.0; the Node page and the CLI do this work over loopback. Their ops keep their tests, moved to the ops level. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| * fix(client): no confirmation dialog for adding a folder or its flagsChristophe Besson3 days16-64/+13
| | | | | | | | | | | | | | Removes confirmFolder (addRoot, attachGroup) and the writable confirmation added in e4f6177, with their two catalogue keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| * feat(mnp): sharing a folder is decided on the node's machine only (MNP 6.0)Christophe Besson3 days36-1714/+408
| | | | | | | | | | | | | | | | | | | | root_add, root_update and group_attach leave MNP: adding a directory and switching writable/removable go through the loopback API (native dialog in the desktop app) or the CLI. The operator's Settings tab still lists the roots from any browser, read-only. The desktop app refuses to sign those ops; a loopback flag change now reaches open pages (publish_roots). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* | test(node): node.toml fixtures use POSIX paths, and a Windows-impossible ↵Christophe Besson4 days2-8/+13
|/ | | | | | | | | | | folder is skipped The root fixtures wrote `path = C:\Users\...`, which is not valid TOML: node_toml now reads values with tomllib, so the four tests failed on Windows. The node and the app always write paths with `/`, as the other fixtures do. A folder named with a quote and a newline cannot exist on Windows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(client): list cast receivers as they answerChristophe Besson4 days6-46/+205
| | | | | | | | The scan still runs six seconds, but the picker polls what it has found and shows each receiver immediately. A rescan no longer has its timer cut short by the scan it replaced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(hub): wrap a docstring ruff flaggedChristophe Besson4 days1-3/+3
| | | | Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): rotating a group key asks nothingChristophe Besson4 days13-25/+3
| | | | | | | Rotation narrows rather than widens: members still connected receive the new key, and nothing already shared changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): hosting a group asks nothing when its folder came from the pickerChristophe Besson4 days11-12/+1
| | | | | | | The folder chosen in the native picker is the consent; the dialog that followed on every group creation asked the same thing twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(hub): a username is unique whatever its caseChristophe Besson4 days2-4/+34
| | | | | | | | Registration refuses a name that differs from an existing one only by case; accounts that already do keep their names, and a pending retry needs the exact name (F-26). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(hub): what an offer or a node message costs the hub is boundedChristophe Besson4 days3-25/+113
| | | | | | | | | An offer's IP-log row (kept a year) was written before any check, for any string named as a node; it is written once the offer goes to a node. The ICE list is capped (64 candidates, 32 KiB). A node's update_groups, a database read each, is budgeted like chat_notify and claims at most 1000 groups (F-22). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): the audit export never hands a spreadsheet a formulaChristophe Besson4 days3-5/+48
| | | | | | | A cell starting with = + - @ (or a tab or carriage return) gets a leading apostrophe; the export carries text members chose (F-29). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore: remove a spike page served in production and an unused derivationChristophe Besson4 days4-453/+1
| | | | | | | | static/webrtc-test.html posted a raw password to /login from the hub's own origin; meshbay_common/keyderive.py derived keys from a password and nothing called it (F-32). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(node): the clear fields beside a chat message are boundedChristophe Besson4 days2-2/+48
| | | | | | | | sender_name and thread_id travel in clear beside the sealed envelope and were stored and relayed whatever their type and size. A name longer than a username or a thread id that is not a short id is now dropped (F-27). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(node): a member is told a media tool failed, not what ffmpeg saidChristophe Besson4 days4-3/+30
| | | | | | | | Stream, transcode and subtitle failures sent the exception's text — operator paths, versions — to the member. Fixed messages now, the cause in the log (F-24). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(node): the reaper deletes only the .part files the node wroteChristophe Besson4 days2-11/+34
| | | | | | | | Any *.part older than a day in a writable root was deleted — a browser's download in progress in a shared folder included. Only names carrying the node's tag (name.<8 hex>.part) are reaped now (F-28). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(node): a revoked account is disconnected, not only refused next timeChristophe Besson4 days2-13/+84
| | | | | | | | A user revocation closed nothing: the denylist stopped the next connection and left the live ones streaming and chatting. Revocations now go through one method that closes the account's or the group's sessions (F-21). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>