Bootstrap Castarr from NodeCast prototype

Imported the native TV app (Kotlin, ExoPlayer, embedded remote server, QR
pairing) plus CONTEXT.md and ADRs 0001-0005. Rename, Compose for TV UI and
the Dispatcharr integration follow as tracked issues.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 00:09:00 +02:00
commit 6c5fee849e
44 changed files with 2418 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
---
status: superseded by ADR-0003
---
# NodeCast is a companion to the nodecast-tv server, not standalone
The first cut of the native TV app parsed M3U playlists itself and needed no
backend. We decided to make it a thin companion instead: the TV app is the only
client of a nodecast-tv server, which owns sources, channels, EPG, favorites
and users. Rationale: those features already exist server-side and would
otherwise be rebuilt in the app; the household already runs the server.
Consequence: the app is not usable without a reachable nodecast-tv instance.
The app-side M3U parser is deliberately kept as a generic-source fallback so
M3U/XMLTV servers like ErsatzTV can be added later without rearchitecting.

View File

@@ -0,0 +1,12 @@
---
status: superseded by ADR-0003
---
# Long-lived device tokens via nodecast-tv fork
nodecast-tv issues JWTs with a 24h expiry, which would force the TV either to
store the user's password in plaintext or to re-prompt daily. We decided to
extend our nodecast-tv fork with non-expiring per-device tokens (API keys
scoped to a user, revocable server-side). The TV logs in once with credentials,
exchanges them for a device token, and never stores the password.
Consequence: the app requires the forked server until the feature is upstreamed.

View File

@@ -0,0 +1,16 @@
---
status: accepted
supersedes: ADR-0001, ADR-0002
---
# Dispatcharr as backend, app speaks Xtream API + XMLTV
ADR-0001 made the app a companion to nodecast-tv; grilling the ecosystem
(Dispatcharr, Threadfin, Tunarr, ErsatzTV) showed they all emit standard
outputs, while nodecast-tv is the only backend with a proprietary API. We
decided to drop nodecast-tv and use Dispatcharr as the backend: it owns
sources, aggregation, failover, EPG and stream profiles. The TV app talks the
Xtream API (channels, categories, EPG as JSON) plus XMLTV, with a generic
M3U/XMLTV fallback so Threadfin/Tunarr/ErsatzTV work too. The nodecast-tv
fork plans (device tokens, ADR-0002) are void; the app-side M3U parser stays
as the fallback path.

View File

@@ -0,0 +1,13 @@
---
status: accepted
---
# Fork Dispatcharr to add native OIDC (Authentik) for the web UI
Dispatcharr has no SSO (open upstream request: issue #806). A reverse-proxy
forward-auth setup would work without code changes, but we decided to fork
Dispatcharr (be-nj) and build real OIDC login (Authentik as IdP, auto user
creation, group mapping) into its Django backend and React UI, offered
upstream as a PR. Rationale: proxy-auth needs bypass rules for every client
endpoint (Xtream/M3U/HDHomeRun) and gives no in-app user identity. The TV app
is unaffected either way — it authenticates with Xtream credentials.

View File

@@ -0,0 +1,20 @@
---
status: accepted
---
# Multi-user app with full TV UI; login via OIDC Device Flow
The app's audience is every user of the household's Dispatcharr backend, each
on their own Google TV — not a single phone-controlled screen. Two consequences:
1. **Full TV UI** (Compose for TV): channel list, zapping and favorites are
operable with the D-pad alone. The QR-paired phone Remote stays as an
optional convenience, no longer the primary control.
2. **Login via OIDC Device Flow** against Authentik: the TV shows a QR/code,
the user confirms on their phone; the app then calls the Dispatcharr fork's
API with Bearer tokens. No Xtream credentials for the primary backend.
The generic M3U/XMLTV source type (ADR-0003) stays as a login-less fallback
for Threadfin/Tunarr/ErsatzTV. The fork scope now bundles: OIDC UI login,
Device Flow + Bearer API, per-user favorites, per-request stream profile
parameter.