diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-06 18:16:57 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-06 18:16:57 +0200 |
| commit | 85a2ec47b7ad334208a3dbb091fadccc7631785c (patch) | |
| tree | a75ff6c12b8229d2dc8082bb36ebc5b3de73b706 /packages/meshbay-common/src | |
| parent | 4e6d6573003b06dd58268602d50a98988d4ce3d0 (diff) | |
| download | meshbay-85a2ec47b7ad334208a3dbb091fadccc7631785c.tar.gz | |
feat(node): Phase 2 server side — one directory setting for every app
`video_root` (a string), `audio_root` (a string) and `photo_roots` (a list)
said the same thing three ways: three roster accessors, three ops, three MNP
messages, three admin-op subjects. They become `set_app_directories(app_key,
paths)` and its single-directory wrapper, stored under `<app>_directories` and
keyed by the app's registry name — so an application can be added without
touching this layer, which is the whole claim of the plugin architecture.
The three old names still work. Their MNP messages are handled, and the roster
falls back to the old key when the new one is unset, so a node upgraded into
this keeps working with no migration step — the plan called for a script, and
a script nobody runs on the machine where it matters is worse than a fallback.
Two things are new rather than moved:
The paths are validated. The setters this replaces accepted anything, so a
typo — or a path left behind when a root was removed — was stored happily and
then matched no entry, leaving an app showing an empty tab with nothing to
distinguish "misconfigured" from "no files yet". Deliberately not
`RootSet.resolve()`: that also refuses a currently-unavailable root, and an
operator must be able to point an app at a library on a drive they ejected.
The legacy scalar is derived, never stored. `video_root` still rides on the
handshake ack for MNP 1.0 clients; kept as a second stored value it would
drift from the list within one run, which reads as "it works after a restart".
Also here: chat's own two settings (a directory, which must be on a read-write
root because it is a destination rather than a view, and a link-preview switch
gating the unfurl path — checked before the cache, or turning it off would
still serve every preview already fetched), the `app_directories`,
`chat_directory` and `chat_link_preview` MNP messages, the plural
`<app>_directories` on the handshake ack, and `music` as the app's one
identifier where storage said `audio` and the registry said `music`.
The Music enricher now resolves a boundary per configured directory rather
than one for the group: with several, a single boundary is wrong for all but
one of them, and for Music that is the difference between reading a folder as
an artist and reading it as a release.
Suite: 11 failures, all pre-existing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pvMdvLBG92jyhvD5pD6us
Diffstat (limited to 'packages/meshbay-common/src')
| -rw-r--r-- | packages/meshbay-common/src/meshbay_common/adminop.py | 6 | ||||
| -rw-r--r-- | packages/meshbay-common/src/meshbay_common/protocol.py | 12 |
2 files changed, 18 insertions, 0 deletions
diff --git a/packages/meshbay-common/src/meshbay_common/adminop.py b/packages/meshbay-common/src/meshbay_common/adminop.py index 1d2e2b2..9a56934 100644 --- a/packages/meshbay-common/src/meshbay_common/adminop.py +++ b/packages/meshbay-common/src/meshbay_common/adminop.py @@ -106,6 +106,12 @@ OP_AUDIO_ROOT = "audio_root" OP_PHOTO_ROOTS = "photo_roots" OP_ROOT_ADD = "root_add" OP_ROOT_REMOVE = "root_remove" +# One op for every application's directories. The subject is +# "<app>:<comma-joined sorted paths>" so what the operator is shown before +# signing names both the app and the outcome — "video_root" alone said neither. +OP_APP_DIRECTORIES = "app_directories" +OP_CHAT_DIRECTORY = "chat_directory" +OP_CHAT_LINK_PREVIEW = "chat_link_preview" OP_ROOT_UPDATE = "root_update" OP_ROOT_EJECT = "root_eject" OP_ROOT_PLUG = "root_plug" diff --git a/packages/meshbay-common/src/meshbay_common/protocol.py b/packages/meshbay-common/src/meshbay_common/protocol.py index 7ee5df1..689adbf 100644 --- a/packages/meshbay-common/src/meshbay_common/protocol.py +++ b/packages/meshbay-common/src/meshbay_common/protocol.py @@ -164,6 +164,18 @@ class MNP: ROOT_ADD_ACK = "root_add_ack" # node → operator: confirmed ROOT_REMOVE = "root_remove" # operator → node: remove a root from a group ROOT_REMOVE_ACK = "root_remove_ack" # node → operator: confirmed + # One message for every application's directories, keyed by the app's own + # name — adding an app adds no message type. VIDEO_ROOT / AUDIO_ROOT / + # PHOTO_ROOTS above are the same instruction under three earlier names and + # are still handled, for clients that predate this. + APP_DIRECTORIES = "app_directories" # operator → node: an app's folder(s) + APP_DIRECTORIES_ACK = "app_directories_ack" + # Chat's own two: where attachments are written (a destination, so it must + # be a read-write root), and whether the node unfurls links members post. + CHAT_DIRECTORY = "chat_directory" + CHAT_DIRECTORY_ACK = "chat_directory_ack" + CHAT_LINK_PREVIEW = "chat_link_preview" + CHAT_LINK_PREVIEW_ACK = "chat_link_preview_ack" ROOT_UPDATE = "root_update" # operator → node: change writable/removable on a root ROOT_UPDATE_ACK = "root_update_ack" ROOT_EJECT = "root_eject" # operator → node: mark removable root as ejected |