Internal plugins are the administrator's to switch: hide them on Settings → Plugins by default, behind a check mark, and take the person's switch away #200
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Postulo/postulo#200
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The change
Plugins of provenance internal — the ones shipped inside Postulo — are the
administrator's to switch on and off, not the person's. A regular user cannot enable or
disable them. On Settings → Plugins they are hidden by default, behind a check mark
that shows them; with the mark off, the page lists the plugins that were installed on
the instance — official and custom — and nothing else.
What happens today
policy.decide(plugins/policy.py:109-149) treats every governed plugin the same way:instance switch, then the administrator's row for this person, then the administrator's
row for everybody, then the person's own
Profile.plugins_off. A plugin with noadministrator row is theirs —
Decision(theirs=True)— whatever its provenance, andset_choice(:165) writes the person's choice intoplugins_off. So Severaltelephone numbers, Several websites, the email notifier, the local store: every
built-in feature and service is a checkbox a person can untick on their own settings
page today.
policy.overview(:184) lists every plugin of a governed kind that is offered, withits provenance read once from
installing.status()(internal,official,custom,uploaded—plugins/provenance.py:37-47), andsettings/plugins.htmldraws one rowper plugin with a checkbox, disabled where the row is not theirs. Nothing on the page
filters by provenance, and nothing in the policy knows provenance at all.
The administrator's side already exists: Server settings → People → Plugins
(
PersonPluginsView,server_views.py:1000) writesPluginPolicyrows — available,forced on, forced off, unavailable — per person or for everybody. That is the mechanism
the change leans on; the person's own choice is what it takes away for internal plugins.
What a fix has to settle
decideneeds the plugin's provenance —provenance.of_builtinfor a built-in,of_recordfor an installed one — and, for aninternal plugin, must never reach
_their_choices:theirs=False,ondecided bythe administrator's rows or the default,
decided_bysaying which.set_choicethenrefuses by itself, which is what stops a hand-written POST.
plugins_offentries that already name an internal plugin. Anybody who hasunticked Several telephone numbers has
"phone-numbers"inplugins_offtoday. Oncethe person's choice no longer counts for internal plugins, that entry is inert; either a
data migration drops those names, or the reader ignores them and they linger. Inert
data that looks like a choice is worse than none.
internalare left out unless the mark is on. Themark is a decision of its own: a query parameter (
?internal=1, bookmarkable, notremembered) or a stored preference (remembered, one more field). Internal rows, when
shown, carry no checkbox — the reason beside them says whose decision it is, in the
existing why slot.
uploadedis neither official nor custom. A wheel somebody uploaded that matchesnothing a repository signed (
provenance.py:44-47) is still a plugin installed on theinstance and still a person's to switch. The change says official and custom; the
page should list uploaded ones too, or the distinction is by evidence the person cannot
see. Say which.
plugins_off—test_phone_numbers.py,test_phones.py,test_web_links.py,test_profile_sections.py,test_mail_transport.py,test_plugin_policy.py,test_settings_plugins.py— and every one of them does it to an internal plugin. Theymove to the administrator's route, a
PluginPolicyrow inFORCED_OFF, whichtest_recovery_number.py:190already does.test_plugin_policy.pyandtest_settings_plugins.pyalso assert the person can choose, and change to assertthe new rule.
:455) says afeature can be switched off "for yourself under Settings → Plugins, or for the whole
instance by an administrator"; Writing a plugin says a feature is "switched on and off
through the same page, the same policy and the same explanation as everything else"
(
:995) and that off "is offered … the person is told how many are kept back" (:1036);the plugin descriptions themselves ("Switched off, Postulo shows and uses the primary
number only") are written to the person. The pages and the descriptions say the new
truth: an administrator's switch, not yours.
Several websites is switched off" is still true when an administrator did the
switching; the who is already in the decision, and the page can say it.
Classification
Breaking change: a person who switched a built-in feature off for themselves loses that
switch, and the state they chose either migrates to nothing or lingers. Say so in the
changelog.