Household request flow
Rendered from spec at76d46f3 (2026-10-25) · its source · Edit this page
Status: Accepted · Audience: Household · Area: D — Content & household
Purpose
Let everyone else in the home ask for something and then watch it, without ever encountering lemonfiber.
This is the only feature whose primary audience is not the operator. For a partner, a housemate, or a teenager, the product is Seerr and Jellyfin — they will never see a terminal, a form, or a diagnostic. Their entire experience is: search for something, tap request, and later it’s there.
If that experience is poor, the operator hears about it constantly, and the whole stack is judged a failure regardless of how well it’s engineered.
Behaviour
One account, one place to ask
A household member signs in with their Jellyfin account — the same credentials that let them watch. Seerr authenticates against Jellyfin (D1), so there is no second registration.
The loop is closed for the requester
The failure mode to avoid is the request disappearing into silence. From the requester’s side:
| Stage | They see |
|---|---|
| Requested | Confirmation that it was received |
| Approved / declined | The outcome, and a reason if declined |
| Processing | That it’s being worked on |
| Available | That it’s ready, and where to watch it |
Seerr sends these. lemonfiber’s job is to ensure it’s configured to, because the default of silence is what generates “did you get my request?” — which is precisely the interruption the operator installed this to avoid.
What can be requested reflects what’s actually configured
Requesting television is meaningless if Sonarr isn’t running. The request surface reflects the active configuration, so a household member is never offered something the stack cannot deliver.
Failures are communicated, not swallowed
A request that can’t be fulfilled — nothing available, repeated download failure, too new — must reach the requester. Silence is read as being ignored, and the requester’s next move is to ask the operator in person.
The operator sees household activity
Pending requests, and anything failing to fulfil, surface in lemonfiber’s dashboard. The operator shouldn’t need to open Seerr to know something needs attention.
A second request is refused, not merged
The request service holds one request per thing, by the person who asked first. A second person asking is told it is already coming rather than being added to it, so there is no list of requesters to notify when it lands — they find it there, the way they would find anything else in the library.
This was written the other way round, as deduplication with every requester notified on availability. Nothing in the stack keeps a second requester to notify, and lemonfiber cannot add one: it does not handle requests, it configures the service that does. A requirement no part of the product can be held to is one that reads as met by nobody looking, so it says what actually happens instead.
What is preserved is the part that matters to the person asking: they are answered rather than left wondering, and they are not made to wait on a request that silently went nowhere.
The household never touches lemonfiber
No lemonfiber account, no lemonfiber URL, no awareness that it exists. The boundary is deliberate: household members should be unable to affect the stack’s operation even accidentally.
A member searches and asks on their own account
A member’s own session searches and asks through the core, which checks their allowance and their limits before the request reaches the request service. A search offers only what that member may watch and ask for, and each title says whether it is here, already asked for, or may be asked for. The session is the member’s media-server account (D6); there is still no lemonfiber account.
States
Per request:
| State | Meaning |
|---|---|
submitted |
Received, awaiting decision |
auto-approved |
Approved under policy (D7) |
approved |
Approved by the operator |
declined |
Refused, with a reason |
processing |
Handed to an *arr, being acquired |
available |
In the library and playable |
failed |
Could not be fulfilled; reason communicated |
partially-available |
Some of a series present |
Edge cases
| Situation | Behaviour |
|---|---|
| Requested item already in the library | Say so immediately and link to it, rather than accepting a redundant request. |
| Item not yet released | Accept and mark as awaiting release, with the date. Don’t fail something that simply hasn’t happened yet. |
| Nothing available at the configured quality | Communicate that specifically — not a generic failure. The operator may want to relax the preset. |
| Request fails repeatedly | Notify the requester and surface to the operator. Don’t retry silently forever. |
| Requester exceeds quota | Explain the limit and when it resets (D7). |
| Series requested where some seasons exist | Support partial requests; don’t force re-acquiring what’s present. |
| Requester lacks permission for that content type | The option shouldn’t be offered. Never offer then refuse. |
| Household member removed | Their requests remain visible to the operator with the requester marked as removed. |
| Seerr unreachable | Surface as a service failure to the operator. The household simply can’t request — an outage, but not data loss. |
| Two people request the same thing | The second is refused as already requested, and told so. They watch it when it lands, like anyone else. |
| Item available but Jellyfin hasn’t scanned | Trigger a scan before marking available, so “ready” is true when stated. |
| Requester has no notification target | Status is visible in Seerr regardless; the loop closes on next visit. |
Acceptance criteria
| ID | Requirement |
|---|---|
| D4-R1 | Household members MUST authenticate with their Jellyfin account; no separate registration MAY be required. |
| D4-R2 | Requesters MUST be informed at submission, decision, and availability. |
| D4-R3 | A request that cannot be fulfilled MUST communicate that to the requester with a reason. |
| D4-R4 | The request surface MUST offer only content types the active configuration can deliver. |
| D4-R5 | Content already in the library MUST be reported as such rather than accepted as a request. |
| D4-R6 | Unreleased content MUST be accepted and marked awaiting release, not failed. |
| D4-R7 | “Nothing available at the configured quality” MUST be communicated to the operator distinctly from a generic failure. A member is told it has not been found yet, in the core’s household sentence (G4-R16). |
| D4-R8 | Pending and failing requests MUST surface in lemonfiber’s dashboard. |
| D4-R9 | Household members MUST NOT require any lemonfiber account or access. |
| D4-R10 | A request for something already requested MUST NOT create a second request, and the person asking MUST be told it is already on its way. |
| D4-R11 | Partial series requests MUST be supported without re-acquiring existing content. |
| D4-R12 | A library scan MUST complete before a request is reported available. |
| D4-R13 | Content a requester lacks permission for MUST NOT be offered. |
| D4-R14 | Repeated fulfilment failure MUST stop retrying silently and MUST notify both requester and operator. |
| D4-R15 | A member’s search, and every list of titles offered to a member to ask for, MUST be answered by the core under that member’s limits, and MUST NOT offer a title the member may not watch or ask for (D8-R8, D8-R9). Each title MUST say whether it is here, already asked for, or may be asked for (D4-R5, D4-R10). |
| D4-R16 | A member MUST be able to ask for a title through lemonfiber’s web API on their own session. The core MUST check the member’s allowance and limits before the request reaches the request service, and MUST answer with what became of it in the household’s words (G4-R16). |
| D4-R17 | A member’s search MUST be answered one page at a time, in an order that holds from one page to the next, each page carrying where the next begins until there is none, so a client loads the next as the member reaches it; no title MUST appear on two pages of one search. |
| D4-R18 | Which kinds of title a member’s search covers MUST be the kinds the stack can deliver now (D4-R4), decided by the core and said in its answer; the member MUST NOT be offered a kind to choose. |
| D4-R19 | A title a member’s search finds with no certification MUST have its certification looked up by the core before it is offered, and where none is found it MUST be treated as unrated under that member’s unrated policy (D8-R5), never as allowed. |
| D4-R20 | A member’s ask MUST be an action of the web API, rehearsed before it is sent so the member is told what it would leave of their allowance and whether it waits for approval, and sent with an Idempotency-Key so a retry after no answer asks once (ARCH-R165); request.intake MUST carry the search and the ask as operations of its own. |
| D4-R21 | Every request a member or the operator reads MUST name the title it asks for, a request still awaiting approval included: where no library holds the title yet, the core MUST name it from the request service’s own record of that title. A request neither can name MUST still be shown and decidable, and MUST NOT make the rest of the reading unreadable. |
Related
- D6 Household identity — how members get accounts
- D7 Approval & quotas — the decision policy
- D8 Parental controls — what each member may request
- D1 Service auto-wiring — the Jellyfin identity connection
- G6 Client apps — where they watch