Skip to content

Latest commit

 

History

349 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Note

Part of Flowfin. It works with any Jellyfin server, and with the Flowfin clients.

Account Invitations

A Jellyfin plugin that lets an operator invite somebody with a link, so that person sets up their own account instead of the operator creating it by hand and handing out a password. It is for people who run a server for friends or family and who would rather not be the one who knows everybody's password.

Warning

None of it works yet. What installs today adds one page to the server dashboard and there is nothing on that page to set. No invitation can be minted, no link can be redeemed, and no account is created by this plugin. Everything below describes what is being built and says which part is written down and which part is running code.

The shape of it

An operator mints a link and scopes it in advance: which libraries the account will see, what it may do, how long the link lasts and how many people it is good for. They send the link to somebody. That person follows it, answers a short setup, chooses their own password, and ends up with an account already scoped the way the operator decided. The operator can revoke the link at any point before it is used.

The whole path, state by state and branch by branch, is written down in docs/redemption-flow.md, including the awkward ones: a link that expires between the page being shown and the form being posted, a username somebody else has taken, a password the server refuses. Nothing in that document is implemented.

What it deliberately does not do

  • It is not open registration. Somebody who reaches the setup page without a valid invitation gets an account out of it in no case.
  • It never touches an account that already exists. An invitation presented by somebody already signed in creates nothing and changes nothing, and there is no path by which redeeming one widens an account that is already there.
  • It never mints an administrator, whatever the configuration asks for.
  • It carries no credential in the link. No password, no temporary password, and no token standing in for one.
  • It sends no mail. The operator copies a link and hands it over with whatever they already use to talk to the person, and there is no mail server to configure and no address to collect.

The first four are settled and every issue in the plan is written to keep them true. The issues that turn each into a refusal in the source are named against their rows in docs/threat-model.md, and none of those refusals is code yet.

The mail one is narrower than the others and is worth saying exactly, and this paragraph said the question behind it was open. Item 5 in #11 is answered: this plugin never sends an invitation itself. A sending path arrives with three things that do not exist here, a mail or webhook configuration, a contact address to send to, and an outgoing route off the server, and each of them is a surface of its own. Item 9 in the same place answers the second of the three in the same direction, so the guided setup collects no contact address either.

That makes the bullet a decision rather than a gap, which is why it is written out instead of being left as an absence. An operator who reads nothing about sending concludes it was forgotten and finds out otherwise after installing. If sending is ever wanted it is a milestone of its own rather than a setting, and the answer today is no.

Supported server line

The 10.11 line, on net9.0, and one line rather than two. That is item 1 in #11, answered on #97, and this section read 10.11.0 and later before it was. The number in the manifest is the oldest server of that line the plugin claims to load on, and it is one value read from one file:

$ git grep -nE '^(targetAbi|framework):' -- build.yaml
build.yaml:6:targetAbi: "10.11.0.0"
build.yaml:7:framework: "net9.0"

Directory.Build.props derives the floor build from that same line, so the claim in the manifest is what the plugin is compiled against rather than a second number somebody keeps in step by hand.

targetAbi is a floor and no field beside it names a ceiling, so a server on a later line still installs this plugin and the packaging does not refuse it. The plugin does. It compares the running server against that line when it starts and answers every one of its own addresses with a refusal naming both versions where they disagree, which is #97 and is built. So the heading is what this plugin is built and tested against, and what enforces it is the plugin rather than the manifest.

Installing

There is no published release and no catalogue manifest yet, so there is nothing to paste into a Jellyfin repository list. Saying so is more useful than an install section that describes a URL nobody can fetch. 0.1.0.0 is the version the metadata declares and it has not been tagged; the tag that would publish it is #155 and the sequence a tag runs through is docs/RELEASING.md.

To build it from source:

dotnet restore --locked-mode
dotnet build --configuration Release --no-restore
dotnet test --configuration Release --no-build

That produces Jellyfin.Plugin.Invites/bin/Release/net9.0/Jellyfin.Plugin.Invites.dll, which is the file the packaging metadata names. Dropping it into a plugin directory on a real server is one of the two checks this repository will not automate, and what a person does instead is in docs/manual-checks.md.

Screenshots

None yet. The configuration page has nothing on it to photograph and the setup page does not exist. They arrive with the pages, in #84 and #74.

Security

This plugin creates accounts, so a defect in it hands somebody an account on a server they were never invited to. The posture is that invitation codes are bearer credentials and are treated as such: minted from a cryptographic source, stored only as a keyed hash, indistinguishable in failure, expiring, revocable, and unable to produce an administrator. Every one of those is a decision recorded in an issue today rather than a line of code, and the document that says which is which, including what is not defended at all, is docs/threat-model.md. How to report something is SECURITY.md.

The documents

Each of these is the one place its subject is settled. They are linked rather than summarised here, because a readme that restates a decision is a readme that drifts from it.

Document What it settles
docs/redemption-flow.md Every state and branch from following a link to holding an account
docs/api.md Every route, its parameters and its responses, and what the API deliberately does not offer
docs/threat-model.md What is defended, how, and what is not defended
docs/code-entropy.md How long an invitation code is, and the calculation the length is read off
docs/personal-data.md Every field held about an invited person, why it exists and what deletes it
docs/logging.md What a log line may carry and what it may never carry, at any level
docs/expiry-rules.md The seven decisions behind what looks like one comparison
docs/attempt-outcomes.md The fixed set of outcomes a redemption attempt records
docs/rate-limit.md Where the redemption counter lives, and what a restart does to it
docs/setup-never-asks.md What the guided setup may never put a box on the page for
docs/password-rules.md What the guided setup requires of a password, and why the rules are this plugin's rather than the server's
docs/refusal-response.md The one page every unusable invitation produces, and what identical means
docs/configuration.md One row per setting, its default, its bounds and what breaks
docs/limits.md Behaviour that is correct, surprising, and reported as a bug
docs/what-an-invitation-can-never-do.md Seven sentences an invitation may never break, and what refuses each one
docs/disaster-cases.md Restore from backup, a cloned server, two servers on one store
docs/migration-from-jfa-go.md Whether this replaces jfa-go, answered in both directions
docs/versioning.md Where the version number lives and which part moves when
docs/RELEASING.md What a tag does and what a person does
docs/tests-not-written.md The tests this repository refuses, and what covers each risk instead
docs/manual-checks.md Where a run of the two unautomatable checks is recorded
CONTRIBUTING.md Sign-off, the headless rule, the invariant lint, and what runs on a change

Licence

GPLv3, in LICENSE. A Jellyfin plugin links against the Jellyfin NuGet packages, which are GPLv3, so the compiled binary is GPLv3 whatever the source says. NOTICE.md carries the intended-use notice.

Releases

Packages

Used by

Contributors

Languages