A plugin's kind and where it came from wear the same grey pill, and one of them is missing entirely #184

Closed
opened 2026-09-12 09:21:09 +00:00 by tiagoagueda · 1 comment
Owner

Observation

Two different facts about a plugin are drawn identically, and on the page where people
actually manage their plugins one of them is not drawn at all.

server/plugins.html shows both, in the same pill:

{# the kind #}
<span class="ms-2 rounded-full bg-ink-100 px-2 py-0.5 text-xs text-ink-600 ...">

{# where it came from #}
<span class="ms-2 rounded-full bg-ink-100 px-2 py-0.5 text-xs text-ink-600 ..."
      data-provenance="{{ plugin.provenance }}"
      title="{{ plugin.provenance_explanation }}">{{ plugin.provenance_label }}</span>

Same shape, same grey, side by side. Nothing tells a reader that importer and official
are answers to different questions.

settings/plugins.html:47 shows the kind, in that same grey pill, and no provenance at
all
— so the page a person uses to turn their own plugins on and off never says where any
of them came from.

What it should be

  • The kind is coloured. It is a category with a small fixed vocabulary, and colour is what
    makes eight categories scannable in a list. The kinds are in plugins/policy.py:
    source, notifier, store, sync, importer, feature (governed) and transport,
    identifier (ungoverned). Eight.
  • Where it came from stays grey, and gets added to the settings page.

Grey is not a default here — it is the existing argument, and it is right

server/plugins.html already explains why provenance is not styled to reassure:

Where it came from, derived rather than declared: an upload is named as a repository's only
when its checksum matches what that repository signed. Deliberately not styled as a
reassurance — installing a plugin runs somebody else's code whatever this says
(#94).

A green Official badge reads as a safety rating, and it is not one. Keeping provenance grey
while the kind takes colour is the same argument made visually: the colourful tag is a
category, the grey one is a fact about origin that nobody should read as an endorsement.

There are four origins, not three

plugins/provenance.py already has the whole vocabulary, labels and explanations included —
nothing needs inventing:

Label What it means
internal Internal Ships inside Postulo. It cannot be removed.
official Official Its file matches what the official repository signed.
custom Custom Its file matches what a repository on this instance signed.
uploaded Uploaded Nothing here signed this file, so nothing vouches for it.

uploaded is the one to be careful about. #94's own opening says why it exists:

The difficulty is entirely in the second kind, and it is one sentence: a zip is a zip. A
file somebody uploads carries no evidence of who published it. Calling it official because
it is named after an official plugin would be worse than not labelling it.

So a design that offers three origins has to decide what an uploaded plugin shows, and the
answer cannot be "official". It has a label already; it should keep it.

Worth getting right

  • Colour must not be the only carrier. Each tag has its own text, so this holds as long as
    nobody replaces the word with a dot. Both themes need real contrast — app.css already has
    the 100/500/700 ramps for amber, emerald and the rest — and eight distinguishable hues is
    more than a palette usually gives, so some kinds may share and lean on the word.
  • One class per kind, defined once. app.css already has .chip and friends; these want
    the same treatment rather than eight inline class strings repeated across two templates.
  • data-provenance is load-bearing. server/plugins.html carries it on the pill and the
    e2e tests read it; whatever this becomes keeps that attribute and its title.
  • The two pages should end up drawing a tag the same way. They do today only by coincidence.
## Observation Two different facts about a plugin are drawn identically, and on the page where people actually manage their plugins one of them is not drawn at all. **`server/plugins.html`** shows both, in the same pill: {# the kind #} <span class="ms-2 rounded-full bg-ink-100 px-2 py-0.5 text-xs text-ink-600 ..."> {# where it came from #} <span class="ms-2 rounded-full bg-ink-100 px-2 py-0.5 text-xs text-ink-600 ..." data-provenance="{{ plugin.provenance }}" title="{{ plugin.provenance_explanation }}">{{ plugin.provenance_label }}</span> Same shape, same grey, side by side. Nothing tells a reader that *importer* and *official* are answers to different questions. **`settings/plugins.html:47`** shows the kind, in that same grey pill, and **no provenance at all** — so the page a person uses to turn their own plugins on and off never says where any of them came from. ## What it should be - **The kind is coloured.** It is a category with a small fixed vocabulary, and colour is what makes eight categories scannable in a list. The kinds are in `plugins/policy.py`: `source`, `notifier`, `store`, `sync`, `importer`, `feature` (governed) and `transport`, `identifier` (ungoverned). Eight. - **Where it came from stays grey**, and gets added to the settings page. ## Grey is not a default here — it is the existing argument, and it is right `server/plugins.html` already explains why provenance is not styled to reassure: > Where it came from, derived rather than declared: an upload is named as a repository's only > when its checksum matches what that repository signed. **Deliberately not styled as a > reassurance — installing a plugin runs somebody else's code whatever this says** (#94). A green *Official* badge reads as a safety rating, and it is not one. Keeping provenance grey while the kind takes colour is the same argument made visually: the colourful tag is a category, the grey one is a fact about origin that nobody should read as an endorsement. ## There are four origins, not three `plugins/provenance.py` already has the whole vocabulary, labels and explanations included — nothing needs inventing: | | Label | What it means | | --- | --- | --- | | `internal` | Internal | Ships inside Postulo. It cannot be removed. | | `official` | Official | Its file matches what the official repository signed. | | `custom` | Custom | Its file matches what a repository on this instance signed. | | `uploaded` | **Uploaded** | Nothing here signed this file, so nothing vouches for it. | **`uploaded` is the one to be careful about.** #94's own opening says why it exists: > The difficulty is entirely in the second kind, and it is one sentence: **a zip is a zip.** A > file somebody uploads carries no evidence of who published it. Calling it official because > it is named after an official plugin would be worse than not labelling it. So a design that offers three origins has to decide what an uploaded plugin shows, and the answer cannot be "official". It has a label already; it should keep it. ## Worth getting right - **Colour must not be the only carrier.** Each tag has its own text, so this holds as long as nobody replaces the word with a dot. Both themes need real contrast — `app.css` already has the 100/500/700 ramps for amber, emerald and the rest — and eight distinguishable hues is more than a palette usually gives, so some kinds may share and lean on the word. - **One class per kind, defined once.** `app.css` already has `.chip` and friends; these want the same treatment rather than eight inline class strings repeated across two templates. - **`data-provenance` is load-bearing.** `server/plugins.html` carries it on the pill and the e2e tests read it; whatever this becomes keeps that attribute and its `title`. - The two pages should end up drawing a tag the same way. They do today only by coincidence.
Author
Owner

Landed on 0.3.0 as 934ea6301.

Kind coloured, origin grey and now shown on the settings page too, both drawn through one partial so they cannot drift apart again. policy.overview gained the provenance that page never had. Four new strings, in French and both Portuguese catalogues.

Landed on `0.3.0` as `934ea6301`. Kind coloured, origin grey and now shown on the settings page too, both drawn through one partial so they cannot drift apart again. `policy.overview` gained the provenance that page never had. Four new strings, in French and both Portuguese catalogues.
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#184
No description provided.