diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-07 10:35:09 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-07 10:35:09 +0200 |
| commit | 2c0903c648e24b4e2adf20492398e8b67d033b49 (patch) | |
| tree | 0435f298010f0f946362f28baebbe88337ca8768 /docs/meshbay-draft-v6.md | |
| parent | 0ed078c92cabab1dab0f70f321562032ea549ce6 (diff) | |
| parent | eeda274d751c537f4ecef3087994a16a9517478f (diff) | |
| download | meshbay-2c0903c648e24b4e2adf20492398e8b67d033b49.tar.gz | |
Merge branch 'refactor/groups-phase1'
Groups refactor, phases 1-3.
The root model replaces the old `upload` flag and group-wide `member_upload`
with per-root `writable`/`removable`/`ejected`, carried by a `RootSet` that
both front doors — the loopback API and signed MNP — reach through the same
`ops` functions. MNP goes to 1.1, additively: the roots table now rides on
`index_delta`, so a root added, removed, ejected or plugged reaches every
connected client instead of only whoever reloaded.
The group UI becomes a plugin architecture: an application is a registry
entry in `apps.js` plus its own files, with directories stored generically
by `ops.set_app_directories` under whatever the app is called. A reference
application, hidden behind `?dev=1`, is what makes that claim testable —
adding it is what found the two places still naming apps by hand.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pvMdvLBG92jyhvD5pD6us
Diffstat (limited to 'docs/meshbay-draft-v6.md')
| -rw-r--r-- | docs/meshbay-draft-v6.md | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/docs/meshbay-draft-v6.md b/docs/meshbay-draft-v6.md index 180050c..28aea0c 100644 --- a/docs/meshbay-draft-v6.md +++ b/docs/meshbay-draft-v6.md @@ -57,7 +57,7 @@ | 6 | Portability | exFAT/NTFS and Windows are the **common** case. Case folding and Unicode normalization become correctness requirements, not compatibility notes | E8 / decision 12 | | 7 | Accounts | Native registration is **hybrid**: passphrase-derived `auth_key` (the recovery path) plus a device Ed25519 key for day-to-day authentication | E3 / decision 4 | | 8 | Authorship | Chat senders are **cryptographically authenticated to each other**; an upload has a **provable owner** who may delete it, as the operator may. v5's node-asserted attribution is replaced | operator decision, §2.4b | -| 9 | Node authority | The operator may **close uploading to everyone but themselves**, per group. Signed MNP op, stored on the node, enforced by the node — the hidden button is a courtesy, the refusal is the control | §2.1b | +| 9 | Node authority | The operator decides **which directories accept uploads**, per root. Signed MNP op, stored on the node, enforced by the node — the hidden button is a courtesy, the refusal is the control. **Superseded 2026-09-06** by `docs/refactor-groups.md` §1.1: the group-wide `member_upload` switch this section described is replaced by RO/RW per root, and the "everyone but the operator" carve-out is gone | §2.1b | | 10 | Client | A group's UI is a **set of pluggable applications** (Chat, Files today), not one monolithic page. Which are shown is a per-group, operator-signed setting on the same pattern as change 9 | §2.7 | | 11 | Hub role | The hub gains a **runtime instance-policy store** (`hub_settings`). First policy: an admin switches **public groups off** hub-wide, enforced server-side on every hub-mediated path. `suspend` vs `revoke` on a group are now written down as the distinct things they are | §2.8 | | 12 | Group registry | A group name is **unique per owner account**, not globally; the group's identity is still its UUID. Listed everywhere as `name@owner` | §2.9 | @@ -74,10 +74,22 @@ v5 confines uploads to `shared_root/uploads/` with a filename allowlist, no overwrite, chunk ordering and a size cap. All four protections stand. Two amendments: -- There is no single `shared_root`. **The operator designates one root as the upload - destination**; the quarantine lives inside it. If that root is unavailable the upload - fails with a stated reason and never falls back to another; if none is designated, - uploads are refused rather than guessed. +- There is no single `shared_root`. **Each root is read-only or read-write**, and an + upload goes to the folder the sender is looking at, inside a writable root. If that + root is unavailable the upload fails with a stated reason and never falls back to + another; if the group has no writable root, uploads are refused rather than guessed. + (Amended 2026-09-06 — the original text designated *one* root as the upload + destination, and the client named none. See `docs/refactor-groups.md` §1.1.) +- **There is no `uploads/` quarantine directory any more** (2026-09-06). It was the + last of v5's, the per-user layer having gone on 2026-08-14, and it went for the same + reason: a folder appearing beside the operator's library because somebody sent a + file is the node deciding how their disk is arranged. **What made the quarantine + worth having was never the subdirectory** — it is the filename allowlist, the size + cap, the chunk ordering and the no-overwrite rule, and all four are unchanged. + The client now names the destination folder, which is safe for one reason and only + one: it is resolved through `RootSet.resolve()`, which refuses `..`, absolute + segments and anything escaping its root, symlinks included. A member answers "which + of this group's folders", never "which path on the operator's disk". - **The no-overwrite rule is unchanged and still holds on exFAT/NTFS.** An earlier draft claimed a string comparison let `README.TXT` land on `readme.txt` there. It does not: the check is `Path.exists()`, and `stat()` is itself case-insensitive on those @@ -91,6 +103,31 @@ device that asked, so the node keeps no thumbnail store. ### 2.1b §5.2 Uploads — the operator may close them +> **Superseded 2026-09-06.** `member_upload` is gone; the mechanism is `writable` on +> each root. What the three load-bearing properties below say is *unchanged* — read +> "the root's `writable` flag" for "`member_upload`" and every word of them still +> holds, which is why they are kept rather than deleted. What did change: +> +> - **It is per root, not per group.** A group can publish one library read-only and +> accept uploads into another, which the single switch could not express. +> - **There is no carve-out for the operator.** Read-only means read-only for +> everyone, because a published library that quietly accepts writes from whoever +> holds admin authority is not one. The paragraph below justifying the setting by +> "the only way to get a curated library was to designate no upload root at all, +> which refuses the operator too" is therefore the reasoning that was reversed: that +> *is* the model now, and refusing the operator is the point rather than the defect. +> - **The client names the destination root.** With several writable roots the node +> cannot choose without guessing, and a guess sends a member's file to a disk the +> operator did not intend. It names a root, never a path; everything below the root +> is still decided by the node. +> - The signed op is `OP_ROOT_UPDATE` (plus `OP_ROOT_EJECT` / `OP_ROOT_PLUG`) rather +> than `OP_MEMBER_UPLOAD`, and the flags live in `node.toml` — they are +> configuration — while the *ejected* runtime state lives in `roster.db`. +> `member_upload` survives on the handshake ack alone, computed as "any root is +> writable", for MNP 1.0 clients that read no other field. +> +> See `docs/refactor-groups.md` §1.1 and §1.5b. + New. A group where every member may add files is the default and stays the default; some groups want a library the operator curates, and until now the only way to get one was to designate no upload root at all, which refuses the operator too. |