diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-05 11:53:57 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-05 11:53:57 +0200 |
| commit | 8f25294b0f6bc3f292442edd69a2e149f0717b52 (patch) | |
| tree | 58cfe661b15fce395ab5116f19341bdb6a5b07fe /docs | |
| parent | 28752696f376eb11feb686580a435b166750a723 (diff) | |
| download | meshbay-8f25294b0f6bc3f292442edd69a2e149f0717b52.tar.gz | |
feat: open a group, a folder or a file from a #/name@owner link
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>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/MESHBAY_DESIGN.md | 29 | ||||
| -rw-r--r-- | docs/USERGUIDE.md | 7 |
2 files changed, 35 insertions, 1 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md index 78a9cb5..7c5dce9 100644 --- a/docs/MESHBAY_DESIGN.md +++ b/docs/MESHBAY_DESIGN.md @@ -2088,10 +2088,17 @@ A group's **identity is its UUID**, everywhere: the route, the node's configurat membership. A group **name is unique per owner account**, case-insensitively and trimmed, enforced by a functional unique index; two different owners may each have a `photos`. Names are displayed as `name@owner`, which is a label plus a create-time -check and **not an addressing scheme**. The handle is hub-local: the same +check and **not an identity**. The handle is hub-local: the same `name@owner` on two federated hubs are different groups, and a federated row shows its source hub rather than an account. +The client also accepts the handle in the address, as an alias for the UUID +(§8.4): `#/name@owner`, optionally followed by a path inside the group. It is +resolved **in the client, against the account's own `/v1/groups/mine`**, and no +hub route answers "which group is called this" — so a handle tells nobody +anything they could not already see, and cannot be used to probe for a group. +A rename breaks the handle links to a group and none of its `#/group/<id>` ones. + `visibility` and `join_policy` are the two independent axes described in §3.5. `join_policy` is read from the node's own configuration, never from the hub. @@ -2545,6 +2552,26 @@ that decides where the hub is or fetches the API relative to the page origin. That is a testable invariant, and it is what any feature adding third-party egress must preserve — which is one of the reasons enrichment is node-side (§6.5). +**Inside the application, every route is a fragment** (`#/…`). What follows `#` +is never sent to a server, so it is in no hub or proxy log and no `Referer`; +that is what lets an invitation carry its code (§3.4), and it is why the same +router runs unchanged on `app://meshbay` and in the Android WebView, where no +server could answer a path. Two forms name a group: + +| Route | Meaning | +|---|---| +| `#/group/<uuid>` | the group — every link the application draws | +| `#/name@owner` | the same group by its handle (§7.3); the address shows this form while a group is open, written with `replace` so it is not a history entry | +| `#/name@owner/<root>/<dir>/<file>` | a file: Files opens on its folder and the file is downloaded. A folder instead of a file opens Files there. The path is taken out of the address once acted on, so a reload does not download twice | + +The owner is after the **last** `@` (a username cannot contain one); each path +segment is percent-decoded on its own. Opened signed out, the sign-in form +stands in for the page and the address is left alone, so signing in lands on +it. A download started this way has no user gesture behind it, so where a browser +offers a Save As dialog it takes the fallback a dialog refused for want of a +gesture already takes (`file-utils.js` `_openDownloadTarget`): streamed to the +download folder. `static/group-link.js`. + ### 8.5 Downloads and streaming **Downloads go to disk, never through RAM, on every platform.** There are three diff --git a/docs/USERGUIDE.md b/docs/USERGUIDE.md index 97ea679..d7f0624 100644 --- a/docs/USERGUIDE.md +++ b/docs/USERGUIDE.md @@ -297,6 +297,13 @@ file browser — sort, select, download, preview. - **Right-click a file or folder** for the same actions as the toolbar, listing only the ones that apply to it. On a ticked row the menu acts on everything ticked, like the toolbar does. +- **A link to a group, a folder or a file.** While a group is open the address + bar shows `https://<hub>/#/name@owner` — the name under the group's title. + Add a path after it to point inside the group: + `#/name@owner/root/folder/photo.jpg` downloads that file, and a folder opens + Files there. Only members get anywhere with such a link — anyone else is told + the group is unknown — and someone not signed in is asked to sign in first, + then taken where the link pointed. Renaming the group breaks these links. ### Chat |