diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-02 10:20:09 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-02 10:20:09 +0200 |
| commit | e4f61771131be635b9e81a19203a00707b4b19df (patch) | |
| tree | d80e4edafbeade3c27137e6753140e6585a26b9b /packages/meshbay-client/src | |
| parent | e941cc4c39c38a12220153ea572bd4c7bb92fde0 (diff) | |
| download | meshbay-e4f61771131be635b9e81a19203a00707b4b19df.tar.gz | |
feat(mnp): sharing a folder is decided on the node's machine only (MNP 6.0)
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>
Diffstat (limited to 'packages/meshbay-client/src')
| -rw-r--r-- | packages/meshbay-client/src/main.js | 11 | ||||
| -rw-r--r-- | packages/meshbay-client/src/transcripts.js | 17 |
2 files changed, 26 insertions, 2 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js index cbaabc4..0020084 100644 --- a/packages/meshbay-client/src/main.js +++ b/packages/meshbay-client/src/main.js @@ -2218,7 +2218,16 @@ function registerBridge() { await confirmFolder(body.path); return ['POST', target, body]; }, - updateRoot: (a) => ['PATCH', root(a), anObject(a.updates)], + // Opening a folder to writes from every member is asked like sharing it; + // closing it, or the removable flag, only narrows. + updateRoot: async (a) => { + const updates = anObject(a.updates); + if (updates.writable === true) { + await confirmOrRefuse('native.root_writable_confirm', + { name: aText(a.rootName, 'the folder name') }); + } + return ['PATCH', root(a), updates]; + }, ejectRoot: (a) => ['PUT', `${root(a)}/eject`], plugRoot: (a) => ['PUT', `${root(a)}/plug`], removeRoot: (a) => ['DELETE', root(a)], diff --git a/packages/meshbay-client/src/transcripts.js b/packages/meshbay-client/src/transcripts.js index 0b6d0c0..63f87b2 100644 --- a/packages/meshbay-client/src/transcripts.js +++ b/packages/meshbay-client/src/transcripts.js @@ -30,6 +30,21 @@ function lenPrefixed(prefix, parts) { return Buffer.concat(chunks); } +// The signed operations this application asks a node to perform +// (meshbay_common/adminop.py). A list, not a pattern: what widens a node's +// sharing — `root_add`, `root_update`, `group_attach`, gone from MNP 6.0 — is +// never signed here, so a node older than that cannot be driven into it by a +// script in the page either. +const ADMIN_OPS = new Set([ + 'file_delete', 'dir_delete', 'invite_create', 'invite_link_create', + 'invite_cancel', 'member_revoke', 'member_unpin', 'gek_rotate', + 'apps_enabled', 'set_scan_settings', 'transfer_limits', 'tmdb_config', + 'tmdb_enabled', 'tmdb_override', 'tmdb_rematch', 'musicbrainz_enabled', + 'root_remove', 'root_eject', 'root_plug', 'app_directories', + 'chat_directory', 'chat_link_preview', 'search_listed', 'chat_epoch', + 'group_detach', +]); + // ── Field checks ────────────────────────────────────────────────────────── // // Shapes, not trust: what is checked here is that a field is what its name @@ -143,7 +158,7 @@ function transcriptFor(kind, f, ctx) { } case 'admin': { const op = String(fields.op ?? ''); - if (!/^[a-z_]{1,32}$/.test(op)) refuse('not an operation'); + if (!ADMIN_OPS.has(op)) refuse('not an operation'); return lenPrefixed(PREFIX.admin, [ enc(op), enc(sameNode()), enc(groupId(fields.groupId)), enc(text(fields.subject, 'the subject', 16384)), |