Settings → Plugins: an installed plugin never shows where it came from #603

Closed
opened 2026-10-01 10:48:12 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, by comparing the keys policy.overview() looks up with the keys installing.status() writes, and rendering both in a test.

Checked again on 2026-10-01 against main at 0a5cad587: still present. status() moved from plugins/installing.py to plugins/provenance.py (#248), so the code is now at plugins/policy.py:274 (marks = {row["name"]: row for row in provenance.status()}) and :285, and plugins/provenance.py:214-218 (**asdict(entry)) against :198 for built-ins. The packages_by_distribution() and canonicalise named in the fix now live in plugins/record.py:146 and :213; installing still hands out canonicalise but no longer packages_by_distribution.

overview() looks up each plugin's origin by the name the plugin registers (imap, paperless, helloworld), but status() keys installed plugins by their distribution name from the record (postulo-imap, postulo-paperless). The two never match for an installed plugin, so its row on a person's Settings → Plugins has no origin tag. Built-ins match, because their status row is named after the class's name. The page therefore labels exactly the plugins that need no warning (Internal) and leaves out the ones the tag exists for (Uploaded, Custom).

  • Where: plugins/policy.py:283 (marks = {row["name"]: row for row in installing.status()}) and :294 (mark = marks.get(plugin.name, {})); plugins/installing.py:1303-1307 (status(): **asdict(entry), so name is the record's distribution name) against :1287 for built-ins (name=getattr(plugin_class, "name", "")).
  • What happens: an administrator uploads a wheel that no repository signed. On every person's Settings → Plugins its row shows its kind and no Uploaded tag with "Nothing here signed this file". In a test with a record line postulo-imap and a sync plugin named imap, status() returned the row postulo-imap and overview() gave that plugin provenance_label == "".
  • Why it matters: the page a person uses to decide which plugins act for them was meant to say whose code each one is (#184); for every installed plugin it says nothing, which reads the same as a built-in.
  • Fix: map each loaded plugin to its distribution and look the status row up by that: the entry point's dist, as registry._distribution_of already does, kept on the instance when it is loaded, or installing.packages_by_distribution() on the top-level package of type(plugin).__module__; compare with installing.canonicalise. Built-ins keep matching by name.

Related to #184 (closed), which added the origin tag to this page; it works for built-ins only.

Done when

  • A test in tests/test_plugin_provenance.py with a record line whose distribution name differs from the plugin's name (as every official plugin's does) that asserts the person's settings:plugins page shows Uploaded for it.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, by comparing the keys `policy.overview()` looks up with the keys `installing.status()` writes, and rendering both in a test. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. `status()` moved from `plugins/installing.py` to `plugins/provenance.py` (#248), so the code is now at `plugins/policy.py:274` (`marks = {row["name"]: row for row in provenance.status()}`) and `:285`, and `plugins/provenance.py:214-218` (`**asdict(entry)`) against `:198` for built-ins. The `packages_by_distribution()` and `canonicalise` named in the fix now live in `plugins/record.py:146` and `:213`; `installing` still hands out `canonicalise` but no longer `packages_by_distribution`. `overview()` looks up each plugin's origin by the name the plugin registers (`imap`, `paperless`, `helloworld`), but `status()` keys installed plugins by their distribution name from the record (`postulo-imap`, `postulo-paperless`). The two never match for an installed plugin, so its row on a person's *Settings → Plugins* has no origin tag. Built-ins match, because their status row is named after the class's `name`. The page therefore labels exactly the plugins that need no warning (*Internal*) and leaves out the ones the tag exists for (*Uploaded*, *Custom*). - **Where:** `plugins/policy.py:283` (`marks = {row["name"]: row for row in installing.status()}`) and `:294` (`mark = marks.get(plugin.name, {})`); `plugins/installing.py:1303-1307` (`status()`: `**asdict(entry)`, so `name` is the record's distribution name) against `:1287` for built-ins (`name=getattr(plugin_class, "name", "")`). - **What happens:** an administrator uploads a wheel that no repository signed. On every person's *Settings → Plugins* its row shows its kind and no *Uploaded* tag with "Nothing here signed this file". In a test with a record line `postulo-imap` and a sync plugin named `imap`, `status()` returned the row `postulo-imap` and `overview()` gave that plugin `provenance_label == ""`. - **Why it matters:** the page a person uses to decide which plugins act for them was meant to say whose code each one is (#184); for every installed plugin it says nothing, which reads the same as a built-in. - **Fix:** map each loaded plugin to its distribution and look the status row up by that: the entry point's `dist`, as `registry._distribution_of` already does, kept on the instance when it is loaded, or `installing.packages_by_distribution()` on the top-level package of `type(plugin).__module__`; compare with `installing.canonicalise`. Built-ins keep matching by `name`. Related to #184 (closed), which added the origin tag to this page; it works for built-ins only. ## Done when - A test in `tests/test_plugin_provenance.py` with a record line whose distribution name differs from the plugin's `name` (as every official plugin's does) that asserts the person's `settings:plugins` page shows *Uploaded* for it.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:48:12 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#603
No description provided.