summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js
Commit message (Collapse)AuthorAgeFilesLines
* feat(android): no text messages backup, and one build againChristophe Besson24 hours1-5/+0
| | | | | | | 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>
* fix(auth): the sign-up notice links the privacy statement, with a spaceChristophe Besson24 hours1-0/+1
| | | | | | | | | | | | | | | 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>
* feat(auth): the recovery key never reaches the hubChristophe Besson25 hours1-3/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* feat(hub): one account, several linked nodesChristophe Besson29 hours1-12/+15
| | | | | | | | | | | | | | | | | | | | | | | | | 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>
* docs: a browser is not linked as a deviceChristophe Besson39 hours1-5/+5
| | | | | | | | | | 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>
* feat(hub): replace reCAPTCHA with a self-hosted proof of workChristophe Besson2 days1-2/+1
| | | | | | | | | | | | | | | | | 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>
* feat(node): skip a file the disk stops answering for, then pause its rootChristophe Besson2 days1-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* feat: keep the sidebar for groups; search in the nav, the rest in the user menuChristophe Besson5 days1-3/+0
| | | | | | | | | | | | | | | | | | | | | | | 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>
* feat: let the operator pause and resume a root's indexing (MNP 6.2)Christophe Besson5 days1-0/+4
| | | | | | | | | | | | | | | 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>
* feat(hub): tell the person at sign-up what the hub keeps and whyChristophe Besson5 days1-0/+1
| | | | | | | | | | | | | | | | 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>
* feat(node): carry connections on several coresChristophe Besson5 days1-0/+2
| | | | | | | | 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>
* fix(android): what the first backup on a phone showedChristophe Besson6 days1-0/+4
| | | | | | | | | 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>
* feat(android): back up WhatsApp's own chat backups, and its media if askedChristophe Besson6 days1-0/+11
| | | | | | | | 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>
* feat(android): back up the files of folders the person choosesChristophe Besson6 days1-0/+12
| | | | | | | | 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>
* feat(photos): show a phone's clips in their albumsChristophe Besson6 days1-0/+5
| | | | | | | | Videos in a photo folder are thumbnailed by the node, counted and marked in the album, and played in the group's video player from the lightbox; the slideshow passes them by. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): back the videos of the chosen albums up beside the photosChristophe Besson6 days1-0/+5
| | | | | | | | A 'Videos too' option, off by default, sends them into the same YYYY/YYYY-MM folders. Files are read from the phone a ranged chunk at a time, so a large video is never whole in the page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): back the calendars up as an iCalendar fileChristophe Besson6 days1-0/+3
| | | | | | | A Calendar section sends every calendar the person can edit, as a dated .ics, into <folder>/<account>-calendar once a day when it changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): back text messages up, in a build Play does not getChristophe Besson6 days1-0/+3
| | | | | | | | A Messages section sends the SMS added since the last copy, as restorable <smses> XML, into <folder>/<account>-messages/YYYY. A play flavor has neither READ_SMS nor the code that reads messages; full is the default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): one backup destination, a group the account owns aloneChristophe Besson6 days1-10/+16
| | | | | | | | Chosen once at the top of Android Sync for every kind; photos and contacts go into <folder>/<account>-photos and -contacts. Owner and sole member are checked at set-up and before every run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(android): back the phone's contacts up to a group of one's ownChristophe Besson6 days1-0/+21
| | | | | | | | A Contacts backup section on the Android Sync page sends a dated .vcf into <folder>/<account>-contacts once a day when the address book changed, only to a group the account is alone in, checked again at every run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(hub): photo backup moves to its own Android Sync pageChristophe Besson6 days1-0/+2
| | | | | | | A Phone section of the side menu leads to it, on the Android application only; Settings no longer holds it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): say when the account's node is elsewhere, and let go of itChristophe Besson6 days1-0/+9
| | | | | | | | | | | | | | | | | | | | | | Signing in on a desktop links this machine's node to the account, but never over a key already linked (that would cut off the user's other machine) nor a node set up for another account. On a real install both left the node reading "Running" while the hub refused it in a loop, and nothing said why. And the only way to unlink was the linked machine's own Node page, of no use once that machine is gone. - The Node page works out, from the node and the hub each time it looks, whether this node can serve the signed-in account (nodeLinkProblem), and says why not: "Link this node instead" (asked first) puts this node's key on the account; "Use this node for my account" switches a node set up for another account through node:start, which takeOver now lets past a node that answers "running". The first version went through node:start for both, and clicking it on a real install did nothing: a node signed in before the account was linked elsewhere answers "running". - The Profile page unlinks the account's node (DELETE /v1/users/me/node_key), from any machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(packaging): the Store package declares what the NSIS scripts doChristophe Besson6 days1-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A test-signed install of the MSIX build, in the WindowsApps folder a Store install uses, showed that every script-made piece of the NSIS model breaks there, because each names the install folder and every update deletes it: the firewall rules went stale, the PATH entries piled up pointing at deleted folders, and the Startup-folder .vbs was refused ("Permission denied") right after sign-in. The network capabilities the manifest declared covered nothing: they make rules for sandboxed apps only, and a listener in the package still got the Windows firewall prompt. The package's own startup task was on by default, started the node whatever mode the Node page said, and ran the console executable, whose window stopped the node when closed. The package now declares what Windows then creates at install, carries across updates and removes with the app, all without an administrator prompt (each measured on the real install, through an update and a reboot): - firewall rules for the node, in a custom manifest template, since only a package-level element can hold them; - the startup task, off by default, running meshbay-nodew.exe, a new build of the daemon without a console; - an execution alias for meshbay-node.exe, so the app adds no PATH entry. The node's CLI switches the startup task (platform.startup_task, ctypes over the WinRT ABI): Windows gives the package's identity to the executables in it, not to a powershell.exe the app starts, which got "Element not found". `meshbay-node autostart install | remove | status` therefore works in the Store package from the app and a terminal alike; the app caches the answer, since the Node page polls. Starting at boot stays the .exe installer's: the Store package offers no service mode, and the CLI refuses `service install` there. Process listings count both image names. The Node page's status poll cleared the message of a refused action within five seconds; the two errors are kept apart now (all Windows builds). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: back up the phone's photos to a group, once a day on Wi-FiChristophe Besson7 days1-0/+45
| | | | | | | | | | | | | | | | | | | | | | | | | The Android application sends the photos taken on the phone to one folder of one group chosen by the member (docs/MESHBAY_DESIGN.md §9.12). The phone lists MediaStore, keeps a ledger of what was sent and hands each photo's bytes to the page by an opaque token on the packaged origin; the page decides when a run is due and uploads through the existing path, one photo at a time under a slot. - Once a day from the last finished run, on an unmetered network only; "Back up now" asks first on mobile data. Leaving Wi-Fi stops after the file in flight. - Photos already on the phone are sent by default, newest first, under <folder>/YYYY/MM; edits are sent beside the original as -edited-<date>. - Additive by construction: nothing is ever deleted, renamed or replaced on the node, and a photo deleted on the node is not sent again. - A confirmation names the group, owner, members, folder and size when the destination or starting point changes; a lasting refusal (disk full, folder read-only or gone, no longer a member) is said once and retried a day later. - No ACCESS_MEDIA_LOCATION, so the platform redacts photo locations. - A dataSync foreground service keeps a run going with the screen off. HEIC/HEIF photos are sent but not shown in Photos yet (§15.2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(node): refuse an upload on a full disk with a stated reasonChristophe Besson7 days1-0/+1
| | | | | | | | | | | | Nothing on the upload path knew about ENOSPC: a write that found no room raised out of the handler, the catch-all answered "Request failed", and the .part stayed behind holding the space that had run out. The node now refuses with `disk_full` at chunk 0 when the announced size would leave less than 1 GiB free, and at any write that fails with ENOSPC/EDQUOT, dropping the partial. The client carries the code on the error and the transfers panel says "The node's disk is full" in every catalogue. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: let the operator purge a group's chat (MNP 6.1)Christophe Besson7 days1-0/+2
| | | | | | | | Signed chat_purge from the Chat settings deletes every stored message; epoch keys and attachments stay. The ack is broadcast so open chat panels empty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: notifications on Android while closed, with nothing to installChristophe Besson7 days1-0/+9
| | | | | | | | | | | | | | | | | | | | The phone fetches what is new every fifteen minutes with a poll secret (POST /v1/push/poll) that reads notification lines and nothing else. When a UnifiedPush distributor is already installed, the hub also pushes at once, encrypted to the phone (RFC 8291); losing the distributor falls back to fetching. The hub now honours "disable all notifications" itself: create_notification creates nothing for that account, as it already did for a muted group, so neither switch lets anything reach a phone. The interface used to be the only reader of the account-wide switch. Push endpoints are member-supplied URLs: a send refuses non-public addresses, connects to the address it checked, and follows no redirect. Android build untested here (no SDK on this machine). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: set the Windows node up at sign-in, and stop it for realChristophe Besson9 days1-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Found by the first Windows beta tester, then reproduced on a clean install. After a service-mode install nothing set the node up for the account that signed in: the boot task started a node that quit ("hub.username not set"), and the sidebar showed Node / Create group only once the hub held a node key. The only way to the wizard that provisions was the home page's welcome card, which an account already in a group never sees. The way out was `meshbay-node init` and the key pasted on the profile page -- which is also what PACKAGING-GUIDE.md told people to do. - main.js `node:ensure`, called by app.js at sign-in: provisions, starts and links the node this build ships (Windows, bundled node only). A node set up for another account, or an account linked to another node, is left alone. node:start waits for it, so the two never race. - The sidebar shows the Node section when a node exists on this machine. - The Node page's status is the node's: its control API and the process list, not the service task's state (a node started from a terminal ran while the page said Stopped). Stop says Stopped only once no meshbay-node.exe is left, and stays offered for a process that answers nothing. - CLI stop kills the pid that answered when a graceful stop does not finish, and fails with the reason when a node process is still there. - The daemon ends its process 3s after _shutdown(): Python's exit waited for a busy indexer thread, with the control API already closed. Armed by main() only, never by a daemon run inside a test. - node.toml is read as utf-8-sig (PowerShell 5.1 writes a BOM), and a config that cannot be read is logged instead of dying silently in service mode. - "Pair this browser" queues the code for the next group of this node to open instead of saying "Paired successfully"; no banner before a group. - test_e2e_windows_app.py (opt-in, MESHBAY_WIN_E2E=1) drives the installed app against a throwaway hub: fresh account to linked node, Stop, Start, Restart, checked against the real processes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(hub): play video on iPhone through ManagedMediaSourceChristophe Besson10 days1-0/+1
| | | | | | | An iPhone has no MediaSource; every film was refused as an unsupported codec. A browser with neither now says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: copy a file's or folder's #/name@owner link from Files, Music, Photos ↵Christophe Besson11 days1-0/+3
| | | | | | | | | | | | | | | | | | | | | | | and Search "Copy link" puts the address group-link.js resolves on the clipboard, on the hub's origin rather than the page's, so a link copied in the desktop application is not app://meshbay. Files offers it for one row, from the right-click menu or the toolbar with one row ticked (a phone's way in); Music on one track's menu, whose dots a phone has; Photos on a right-clicked tile and in the lightbox's bar. The video player and the file preview carry a link button next to Download. Applications get a `linkFor(entry | folderPath)` prop (MESHBAY_DESIGN.md §9.2) and offer the action only when it names a link. The group page builds it from the hub's row; Search from each result's own group and its path before the merged views prefixed it, and names no link for a folder of the merged tree, which a group name alone does not identify. harness/copy_link_probe.py mounts the three applications in Chrome and reads what reached the clipboard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: open a group, a folder or a file from a #/name@owner linkChristophe Besson11 days1-0/+2
| | | | | | | | | | | | | | | | | | | A group can now be reached by the handle shown under its name, and a path after it points inside the group: #/name@owner/root/dir/file downloads the file and opens Files on its folder; a folder opens Files there. The handle is resolved in the client against the account's own /v1/groups/mine, so no hub route answers for a name and nobody can probe for one. While a group is open the address shows the handle (replace, no history entry); a linked path is taken out of the address once acted on, so a reload does not download twice. Signing in no longer sends everyone home: the form stood in for the page the address named, and that is where a link opened signed out was going. group-link.js holds the parsing and lookups, executed whole by test_group_link.py; harness/group_link_probe.py drives the router in Chrome. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: list as members only the accounts the node has admittedChristophe Besson11 days1-0/+1
| | | | | | | | | | | | | | | | The Members list showed the hub's membership, which an account gains when it accepts the invitation or redeems a link, before it has presented its code to the node. The node's roster is the authority (MESHBAY_DESIGN.md §3.4), so the list now crosses the hub's members with the sealed group roster the node already sends every connected member. An account the node has not admitted yet is shown to the owner alone, as waiting for its code, with the Remove button; other members do not see it. When the roster cannot be read, the hub's list is shown as before. groupRoster() takes { fresh: true } so the page sees who joined since the connection opened. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: move the desktop client's Hub section from Settings to ProfileChristophe Besson11 days1-1/+1
| | | | | | | | | | | 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 days1-0/+1
| | | | | | | | | | | | | | | | | | | 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 Besson11 days1-1/+0
| | | | | | | | 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>
* feat(cast): photos on the TV, and a television chosen once for the sessionChristophe Besson12 days1-0/+2
| | | | | | | | | | | | | | 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>
* Player: redesigned cast remoteChristophe Besson13 days1-1/+2
| | | | | | | 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 Besson13 days1-0/+6
| | | | | | | 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>
* fix(client): no confirmation dialog for adding a folder or its flagsChristophe Besson2026-10-021-2/+0
| | | | | | | 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 Besson2026-10-021-2/+2
| | | | | | | | | | 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>
* fix(client): rotating a group key asks nothingChristophe Besson2026-10-011-1/+0
| | | | | | | 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 Besson2026-10-011-1/+0
| | | | | | | 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>
* feat: browser access, decided in the desktop applicationChristophe Besson2026-09-301-0/+8
| | | | | | | | | Off for an account made there: its identities stay on the device and nothing is left on nodes. Turned on from the Profile page behind a native confirmation; each node is settled when its group next opens. The hub keeps a mirror a browser reads to say why a group will not open; it grants nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(client): the desktop application keeps M and every node identity in its ↵Christophe Besson2026-09-301-0/+1
| | | | | | | | | | | | main process keyring.js derives, opens, mints, seals, signs and agrees there; the page gets public keys and a handle. Argon2 comes from the page's own WebAssembly build (Electron's crypto has none). Without OS key storage the page keeps its keys as a browser does. A node's bundle is settled after connecting, re-sealed when the key changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: bundles sealed per node under the passphrase and the hub's pepperChristophe Besson2026-09-301-0/+2
| | | | | | | | | The session key is M = HKDF(Argon2(passphrase) || pepper, account id); each node's bundle key and the playlist key derive from it. Bundles are MBK3, bound to account and node; MBK1/MBK2 are refused by name, never replaced silently. Playlists move to key v2 and are re-sealed over unreadable node copies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(client): the page names node operations, and the app confirms what ↵Christophe Besson2026-09-301-0/+6
| | | | | | | | | | | widens the node node:call is replaced by named operations with checked arguments; hosting a group, sharing an unpicked folder, key rotation, denylist clearing and a change of node account are confirmed by a native dialog. Every channel checks its sender, secrets:get/set/clear are gone, node:start writes the app's own hub. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: only the owner decides who hosts a group, and nobody is made a member ↵Christophe Besson2026-09-301-0/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | unasked - hub: a node may host a group only if its account owns it or the owner approved that node (new `group_hosts`). Membership was the ceiling, and every member holds the group key, so any member's node could register as a host and be the one clients kept. A node claiming a group it may not host is recorded as a request; the owner is notified once and approves or refuses it (GET/POST/DELETE /v1/groups/{id}/hosts[/{node_id}]), which takes effect on a connected node at once. - hub: an owner adding a username creates an invitation (new `group_invitations`), accepted or declined by the invitee (/v1/groups/invitations, /{id}/invitation/accept|decline). Until then the group is not listed, not dialled, not searched and not in any token. Invitation links, open joins and group creation still make members directly: they are the account's own act. - hub: the MNP token names only the group it is minted for (group_id is now required), so a node operator no longer learns a member's other groups. - SPA: invitations on the home page; invited people and host requests in the group's settings; the transport sends group_id. Ten catalogues. - Browser probes for both screens, run in Chrome and Firefox. - Design §5.2, §7.2, §7.3, AV32, AV33; protocol §6.3; user guide. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(client): save files under a name every platform can writeChristophe Besson2026-09-281-0/+4
| | | | | | | | | A node serves the name its disk gave a file; the client now makes it portable at save time (single file, zip entries, zip name) and says so on the transfer row. Same rule as paths.sanitize_for_download, held by a parity test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(hub): reports from public-group members, decided by an administratorChristophe Besson2026-09-281-0/+24
| | | | | | | | | | A report needs a person's account at least a day old, membership of the public group, and fits a daily allowance per account. Past the threshold a hash is queued and administrators are notified; blocking without review is an instance setting, off by default. Report menu item in public groups, Reports tab and settings in the admin panel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(hub): new login tagline, dimmer gradient topChristophe Besson2026-09-281-1/+1
| | | | Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>