An administrator can decide a plugin for a person — and must not be able to decide it quietly #95
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.
Blocks
Reference
Postulo/postulo#95
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?
Observation
Third of four, and the one with something in it worth arguing about before any code is
written.
What exists
Two switches, neither of which is this:
Installed.disabled-- instance-wide, inplugins.jsonon the data volume. On or off foreverybody.
Connection.enabled-- per connection, owned by the person, controlled by the person. Oneaccount's Telegram notifier.
There is nothing in between: no per-person plugin state an administrator can see or set, and
no record anywhere of an administrator having changed something about somebody's account.
core/server_views.pycontains norecord_eventcall at all -- making somebody anadministrator, deactivating them, renaming them, all happen with nothing written down.
What this asks for
A person may turn a plugin on or off for themselves, and an administrator may take that
decision away for a named person or for everybody: let them choose, always on,
always off.
The part that needs deciding first
Forbidding and compelling are not the same act, and this issue should probably not treat
them as one.
Always off is an ordinary operator decision. "This instance does not use that." It removes
a capability, it can lose nobody anything they had not already saved, and the worst case is
somebody's notifier stops firing.
Always on is a different thing, because of what these plugins are. Three of the four kinds
-- notifiers, stores, syncs -- exist to move a person's data somewhere else. A store keeps
documents; a sync pushes and pulls records. Postulo's first stated commitment is that one
person's data never reaches another's. An administrator who can compel a person's account
to run a store plugin is an administrator who can, in principle, arrange for that person's CV
to end up somewhere of the administrator's choosing.
In practice a connected plugin needs a
Connectionholding credentials the person supplies,so compelling one on does not by itself move anything -- it means "you may use this and may
not switch it off". But the shape of the permission is what matters, and this one is worth
being deliberate about rather than discovering later.
Three ways to go, and this needs an answer before implementation:
read pages and hold nothing. Safest, and probably enough for the actual need.
plainly and permanently on their own page which plugins were decided for them and by
whom. Honest, and relies on people reading.
so that choosing it is a choice.
The rest of it, which is not contentious
Precedence. Instance-off beats everything: a plugin switched off for the instance is off,
whatever any per-person policy says, because the code should not be running at all.
Otherwise an administrator's decision beats the person's, and the person's applies where
there is none.
Nothing is deleted. Forcing a plugin off must not remove anybody's
Connectionrows ortheir configuration. It stops them being used. Reversing the decision brings them back
exactly as they were -- a policy that destroys data on the way is not a policy, it is a
delete button with a confusing name.
It has to be written down. An administrator changing what somebody's account may run
belongs in an audit trail, with who, when, and what changed. Since
server_views.pyrecordsnothing at all today, this issue either brings the first such trail with it or waits for one.
That is worth deciding rather than skipping -- the event log being the truth is a rule
elsewhere in this codebase and there is no reason for administration to be the exception.
And the person has to be able to see it, which is the fourth issue.
Scope
Server settings -> People gains the exceptions.
every call site.
tests/security/: instance-off cannot be overridden; a forced-off plugin does not run forthat person; nothing is deleted by any transition; a non-administrator cannot reach any of
it.
Classification
Enhancement, security. Tier 1 because it is a new permission over other people's accounts,
and those are worth getting right before they exist rather than after.
Decided
Option 2 from the issue: symmetric, and visible. An administrator may compel as well as
forbid, and the person always sees what was decided for them -- a control showing the forced
state and locked, rather than a control that has quietly vanished.
That answers the concern raised above rather than overriding it. The worry was never that an
administrator holds this power; it was that it could be held invisibly. A stuck toggle is the
mitigation.
The four states, and the fifth one they imply
Unavailable and forced-off are deliberately different, and both are worth having:
unavailable means not part of your Postulo; forced-off means you can see this exists and
that somebody turned it off for you. The second is more honest and the first is quieter, and
which is right depends on why.
A fifth value is needed that the request does not name: inherit. The four above are set
at instance level as a default, and a person's row needs a way to say "no exception here,
follow the default" -- otherwise every account has to be written to whenever the default
changes.
One precision on "forced on"
For a notifier, store or sync, forcing a plugin on cannot make it run. Those need a
Connectionholding credentials only the person can supply. So forced-on means "this isavailable to you and you may not switch it off", not "this is now sending your documents
somewhere". Worth being exact in the interface too: a forced-on plugin with no connection
should say it is waiting for one, not appear to be working.
Sources are the exception -- they are stateless and need no connection, so forcing one on
genuinely turns it on.
Precedence, unchanged from the issue
Instance-off still beats everything: a plugin switched off for the whole instance is off
whatever any per-person policy says, because the code should not be loaded at all. Below
that, the administrator's decision beats the person's, and the person's applies wherever
there is no administrator decision.
Nothing is deleted by any of these transitions, and every change is written down. Both still
stand.