Add a read-only LAN probe for validating the design

Tautulli stays local-network-only, so nothing off the LAN can check this
design against real data. tools/probe.py closes that gap from the inside:
GET requests only, standard library only, credentials redacted from all
output including error messages.

It answers open questions 1-4 in one run — Tautulli's coverage horizon,
the finished/partial/abandoned split across real plays, whether successive
plays are being grouped, library shapes and sizes, multi-version items,
and path roots by size. It also runs the pms_identifier cross-check from
section 4.11.

tools/mockserver.py mocks both APIs so the probe is testable without a live
server. Verified against it: the happy path, Tautulli absent, Tautulli
unreachable, Tautulli erroring, Plex unreachable, and an identifier
mismatch. Credential redaction confirmed in every error path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GVbG48GAXfCZatcmX123Ra
This commit is contained in:
Jess Hallsworth 2026-09-07 04:57:38 +00:00
parent 74dfc4dab8
commit 2c1033e4a7
No known key found for this signature in database
4 changed files with 626 additions and 5 deletions

View file

@ -305,7 +305,10 @@ the ingest is designed to be slow and steady rather than parallel and aggressive
### 4.8 Tautulli — the watch-history source
Tautulli runs at `http://192.168.1.100:8181` (on Isis) and has been logging every
playback on Loki since the day it was installed. Its database is independent of Plex's:
playback on Loki since the day it was installed. **It stays LAN-only and is not published
externally** — which costs nothing here, since MediaShelf runs on Nox on the same network.
The practical consequence is that design validation happens on the LAN: see
`tools/probe.py` (§13.1). Its database is independent of Plex's:
clearing Plex's history, or Plex pruning its own, does not touch it. That makes it a
deeper and more durable record than anything Plex exposes.
@ -1154,6 +1157,31 @@ The single most important test is idempotency: a scanner that double-counts size
duplicates history events produces a report that looks plausible and is wrong, which is
worse than one that crashes.
### 13.1 Validating the design before writing the app
Both Plex and Tautulli are LAN-only, so nothing outside the network can check this design
against real data. `tools/probe.py` closes that gap: a dependency-free, **read-only**
script run from anywhere on the LAN that issues GET requests only and answers the open
questions in §15 directly —
- Tautulli's coverage horizon, and therefore how much of the library gets `pre_history`
- the finished / partial / abandoned split across a sample of real plays, which is the
assumption the `rejection` component rests on
- whether successive-play grouping is actually happening, so the session-merge logic
(§4.9) can be checked against reality
- real library shapes: movie counts, season counts, total sizes, multi-version items
- path roots and their sizes, which decides whether grouping by physical vault is worth
building
It also does the `pms_identifier` cross-check from §4.11 and reports whether it passes.
Its output is safe to share — credentials are redacted from every message, including
error messages, which is verified by test. `--dump` writes a full item inventory to JSON
for offline analysis, and prints the twenty largest never-watched items as a first taste
of what the real report will look like.
`tools/mockserver.py` mocks both APIs so the probe can be exercised without touching a
live server; it is a test fixture, not part of the application.
---
## 14. Roadmap
@ -1247,14 +1275,15 @@ door is open to a combined view across Plex and Jellyfin without a migration.
### Still open
**Questions 14 are all answered by one run of `tools/probe.py` on the LAN (§13.1).**
1. **When was Tautulli installed?** This sets `history_coverage_since` and therefore how
many older items get the `pre_history` flag. If it went in recently, a large slice of
the library will look never-watched on the first report and the flag is doing real
work; if it has been running for years, it barely matters. A single
`get_history&order_dir=asc&length=1` answers it.
work; if it has been running for years, it barely matters.
2. **Is *Group Successive Play History* on in Tautulli's settings?** MediaShelf requests
`grouping=0` and does its own merging (§4.9), so it should not matter — but confirming
the setting on the first run rules out a whole class of double-counting bug.
it on the first run rules out a whole class of double-counting bug.
3. **Multiple Plex libraries of the same kind** — are there several movie sections (Movies,
Kids, Documentaries)? The design handles it, but the seed views and default charts get
more useful if the real shape is known.
@ -1262,4 +1291,5 @@ door is open to a combined view across Plex and Jellyfin without a migration.
physical vault, which matters when the goal is freeing a *specific* array (vault 2)
rather than space in general.
5. **Registry or image upload?** (§11.2) Setting up a registry is the better long-term
answer but is a piece of infrastructure that doesn't exist yet.
answer but is a piece of infrastructure that doesn't exist yet. Not answerable by the
probe — this one is a preference.