Capabilities and wiring
A capability is a named, contracted thing a service does: search indexers, take a torrent, serve the library to a player, say whether a person is who they claim to be. The stack’s wiring asks for capabilities rather than naming services, so putting a different service in one’s place is a single setting rather than a hunt for everything that pointed at the old one.
Three things called capability
Section titled “Three things called capability”The word is used for three different sets, and they never mix:
| Set | Where it is declared | What it says |
|---|---|---|
| Service capabilities | provides on a service |
What the service can be relied on to do |
| What lemonfiber offers a plugin | [requires] in plugin.toml |
Which extension a plugin needs this build to support |
| Kernel grants | grants on a service in the stack’s manifest |
What the kernel lets a container do |
This page is about the first. The second is at extension points, which lists what this build offers a plugin and refuses anything else. The third is never available to a plugin: a manifest has no field for it. The distinction is set out in the capability vocabulary contract.
Core names and a plugin’s own
Section titled “Core names and a plugin’s own”The vocabulary below holds seventeen core capabilities. A core name reads
area.verb, and a plugin may claim one only with a [[claim]] that binds every
probe the vocabulary declares for it, each proved against a recording — so a
claim is evidence, not a label. A plugin may also declare capabilities of its
own, written <plugin-id>:<name>; those are inert until something asks for
them.
How a link is settled
Section titled “How a link is settled”lemonfiber wiring lists every link in the stack, what it reaches and how it
was settled:
- outright — one service provides it, and there is nothing to decide;
- each — the link asked for every provider, not one;
- contested — several provide it and the link wants one. lemonfiber refuses to pick by install order, recency or precedence, and says so;
- chosen — you picked, and the ones not picked are named;
- unfilled — nothing provides it, and the command exits non-zero.
A plugin that claims a core capability can therefore make a link contested the
moment it is installed; lemonfiber plugin claims says so before it is.
Choosing what fills one
Section titled “Choosing what fills one”lemonfiber wiring fill media.serve navidrome --dry-runlemonfiber wiring fill media.serve navidromeThat is how one service stands in for another, and the only way. The choice is
a setting: it is recorded, it shows in lemonfiber history, and
lemonfiber undo puts it back. The rehearsal says what the change would leave
with nothing filling it before anything is written. Every flag is in
the command reference; refusals are the
WIRE codes.
The vocabulary
Section titled “The vocabulary”Read out of contract/capability-vocabulary.json at the revision this site
pins, which is also what lemonfiber plugin capabilities prints. A probe that
presents the operator’s credential cannot be answered on a machine holding
none, and is reported unproven there rather than failed.
Vocabulary generation 1
indexer.search
Runs a search across the indexers it holds and answers with what they returned.
Holds the operator's indexer accounts, accepts a search on their behalf, and answers with the releases those indexers returned. The accounts it holds, and the list of indexers they belong to, are not readable without the operator's credential.
Declared by: prowlarrnzbhydra2
What a claim is held to:
guarded— An anonymous caller is refused the indexers it holds, presenting nothing. An indexer account is an account somebody paid for. A service that would list them to the network has stopped satisfying this whether or not it still searches.indexers— It answers with the indexers it holds, with the operator's credential. Searching is what this is for, and the indexers it would search are the part that can be read without asking anything of a third party.
indexer.proxy
Fetches a page from an indexer that answers a browser rather than a client.
Fetches a page on another service's behalf when the site it comes from challenges a plain client. It holds nothing of the operator's and is reached only from inside the stack, so it answers an anonymous caller with its own name and version.
Declared by: flaresolverr
What a claim is held to:
identifies— It answers with its own name and version, presenting nothing. This is the one capability whose claimant deliberately holds no credential, so a refusal would be the wrong evidence. What it must show instead is that the thing behind the port is this and not an empty container.
download.usenet
Takes an NZB, fetches the articles it names, and reports where the finished files are.
Accepts an NZB from whatever asked for it, downloads what it names, and reports the path the finished files are at so a filer can move them. The queue and the provider account behind it are not readable without the operator's credential.
Declared by: sabnzbd
What a claim is held to:
guarded— An anonymous caller is refused the queue, presenting nothing. The queue names what the household is downloading and the account paying for it. A client that would answer that to the network has stopped satisfying this.queue— It answers with its queue, with the operator's credential. Reporting where a finished download is requires having a queue to report from, and the queue is the part that can be read without starting one.
download.torrent
Takes a torrent or a magnet, exchanges with peers, and reports where the finished files are.
Accepts a torrent or a magnet from whatever asked for it, exchanges data with that torrent's peers, and reports the path the finished files are at. The queue is not readable without the operator's credential, and what it exchanges leaves through whatever carries its traffic rather than by a route of its own.
Declared by: qbittorrent
What a claim is held to:
guarded— An anonymous caller is refused the queue, presenting nothing. A torrent client's queue is the one list in this stack whose disclosure has consequences outside the household, and the client is the only thing that can refuse it.queue— It answers with its queue, with the operator's credential. The same reason the Usenet client's queue is the readable half: it is what the service has to report from, and reading it starts nothing.
network.egress-guard
Carries another service's traffic out through a tunnel and stops it when the tunnel drops.
Carries the traffic of whatever is placed inside its network, out through a tunnel it dials, and stops carrying it the moment the tunnel is not up. It answers, from inside the stack, whether the tunnel is up — because a guard that cannot be asked is one nothing can prove is guarding.
Declared by: gluetun
What a claim is held to:
identifies— It answers whether the tunnel is up, presenting nothing. This is the one service whose failure has consequences outside the machine, and the failure it has is silent: a tunnel that dropped looks exactly like one that is up unless something asks.
library.curate
Holds a wanted list for one kind of media, asks for what is missing, and files what arrives.
Holds a list of what the household wants of one kind of media, asks an indexer for what is missing, hands the result to a download client, and files what arrives under the library's own naming. The wanted list is not readable without the operator's credential.
Declared by: sonarrradarrlidarrbindery
What a claim is held to:
guarded— An anonymous caller is refused the wanted list, presenting nothing. A curating service holds every key the stack was given and can be made to download anything. Its API answering the network at all is the failure; whether the list is interesting is beside the point.wanted— It answers with what it is holding, with the operator's credential. Holding a wanted list is the half of this that can be demonstrated without waiting for something to be released.
subtitles.fetch
Finds subtitles for what is already filed and puts them beside it.
Reads what the library already holds, finds subtitles for it in the languages the operator asked for, and writes them beside the media. Its own configuration and the provider accounts in it are not readable without the operator's credential.
Declared by: bazarr
What a claim is held to:
guarded— An anonymous caller is refused its configuration, presenting nothing. It holds subtitle-provider accounts and a path into the library. Neither is something the network may read.status— It answers with its own state, with the operator's credential. What it is configured to fetch, and for what, is the part that can be read without a provider being asked anything.
media.serve
Serves the filed library to a player, with its own catalogue of what it holds.
Holds a catalogue of what is in the library and serves it to a player over HTTP. The catalogue is not readable without a credential — a library server that answers an anonymous caller is publishing the household's collection to every device on the network.
Declared by: jellyfincalibre-web-automatedaudiobookshelfnavidrome
What a claim is held to:
guarded— An anonymous caller is refused the catalogue, presenting nothing. This is the probe the whole vocabulary is for. A media server bound to the household network that stops refusing this keeps answering its health probe, keeps appearing green, and has published somebody's library. Nothing else would notice.catalogue— It answers with the catalogue of what it holds, with the operator's credential. Serving a library means having a catalogue of it. A service that refuses everybody including the operator is not serving anything.
identity.source
Answers, for the services that ask, whether a person is who they say they are.
Holds the household's accounts and answers another service's question about whether a given person is one of them. It tells an anonymous caller enough to begin signing in — which server this is — and nothing about who has an account here.
Declared by: jellyfin
What a claim is held to:
identifies— It tells an anonymous caller which server this is, presenting nothing. Something has to be answerable before authentication, or nothing could ever authenticate. What that is is the server's identity, and it is the part with nothing of the household's in it.guarded— An anonymous caller is refused the accounts, presenting nothing. The line between the two probes is the whole of this capability: which server, to anybody; who is on it, to nobody.
request.intake
Takes a household member's request for something not yet held and hands it on.
Lets a member of the household ask for something the library does not have, decides whether they may, and hands the request to whatever acquires it. Its own state is answerable to anybody; what has been requested, and by whom, is not.
Declared by: seerr
What a claim is held to:
identifies— It answers with its own state, presenting nothing. This is the one service a household member reaches without being an operator, so it has a front door that answers before anybody signs in.guarded— An anonymous caller is refused the requests, presenting nothing. What a household asked for is the household's. A request list readable by the network is a list of what everybody in the house is waiting to watch.