music's library browser depends on another plugin's permission, not just its own
MusicBrowser lists folders with GET /file-browser/ls rather than through the music sidecar. /file-browser belongs to `files`, which is `confined` — so a member granted `music` and not `files` gets a working player, working favourites and an empty library, and `files` is not a grant that can simply be handed over, since authorize.ts drops a confined grant for an account with no Linux user. First cross-plugin PERMISSION dependency in the system, and a different animal from offscale's. That one is ConsoleView → TerminalView: code, resolved at build time, worst case a plugin that will not compile. This resolves at request time, per account, and fails as a screen that renders perfectly and shows nothing. Three shapes written down, none chosen. Moving the listing into the sidecar is probably right — it is the same rule offscale follows, that the sidecar absorbs everything — but it is tomorrow's call. Recorded now rather than trusted to memory: it was found by reading, after the extraction was already verified and pushed, so nothing was going to surface it again on its own.
This commit is contained in:
@@ -205,6 +205,37 @@ exist before.
|
|||||||
|
|
||||||
## Still open
|
## Still open
|
||||||
|
|
||||||
|
### The library browser reads the filesystem, not this plugin — and that is a PERMISSION dependency
|
||||||
|
|
||||||
|
Found 2026-08-15, after the extraction landed, by reading the code rather than by anything failing.
|
||||||
|
|
||||||
|
`MusicBrowser.tsx` lists folders with `GET /file-browser/ls`, not through the music sidecar
|
||||||
|
(`MusicBrowser.tsx:63,81`). `/file-browser` belongs to the **`files`** capability, and `files` is
|
||||||
|
**`confined`** — so:
|
||||||
|
|
||||||
|
- a member granted `music` but not `files` gets a working player, working favourites, and an **empty
|
||||||
|
library**, because every listing 403s;
|
||||||
|
- and `files` is not a grant that can simply be handed over. `authorize.ts` drops a confined grant for an
|
||||||
|
account with no `osUser`, so it means nothing without a per-user Linux account.
|
||||||
|
|
||||||
|
This is the first **cross-plugin permission dependency** in the system, and it is a different animal from
|
||||||
|
the one offscale has. Offscale's `ConsoleView` → `TerminalView` is a CODE dependency: it resolves at build
|
||||||
|
time, and the worst case is a plugin that will not compile. This one resolves at request time, per
|
||||||
|
account, and its failure mode is a screen that renders perfectly and shows nothing.
|
||||||
|
|
||||||
|
Three possible shapes, none chosen:
|
||||||
|
|
||||||
|
1. **The sidecar lists.** Music already walks the library for its index — `GET /music/ls` would put the
|
||||||
|
listing behind the `music` permission where it belongs, and the plugin stops needing `files` at all.
|
||||||
|
Most self-contained, and the most work.
|
||||||
|
2. **The manifest declares a permission dependency**, and the platform refuses the grant or warns. Honest,
|
||||||
|
but it makes one plugin's grant conditional on another capability, which is new machinery.
|
||||||
|
3. **Leave it and document it** — a member needs `files` too. Cheapest, and it quietly ties a music grant
|
||||||
|
to a Linux account, which is a much bigger commitment than the owner is agreeing to on that page.
|
||||||
|
|
||||||
|
(1) is probably right, and it is the same shape as offscale's rule that the sidecar absorbs everything.
|
||||||
|
Not tonight's call.
|
||||||
|
|
||||||
- **`hasPersonalWrites` reads `c.personal` only**, so the permissions API reports `false` for a plugin
|
- **`hasPersonalWrites` reads `c.personal` only**, so the permissions API reports `false` for a plugin
|
||||||
that declares the same thing through `readOnlyWrites`. Nothing renders the field, so it is dead on the
|
that declares the same thing through `readOnlyWrites`. Nothing renders the field, so it is dead on the
|
||||||
wire — noted rather than fixed.
|
wire — noted rather than fixed.
|
||||||
|
|||||||
Reference in New Issue
Block a user