# Backend/Scraper Wiring Audit Notes

Use this when auditing Unspooled playback/backend connectivity, source buttons, or scraper integration.

## Durable wiring map

- Android app path for NexStream scraper streams:
  - `SystemAddonCatalog.nexstream_scraper`
  - `BuildConfig.NEXSTREAM_SCRAPER_URL`
  - Stremio addon routes: `/manifest.json`, `/stream/movie/:id.json`, `/stream/series/:id.json`
  - `StremioAddonClientImpl`
  - `AddonRepository.getStreamsForContent()`
  - `DebridEnricher`
  - `PlayerViewModel`
  - `PlaybackOrchestrator`
- `ProviderRegistry -> ScraperProvider -> DefaultAddonScrapers.ALL` may be stale/dead if `DefaultAddonScrapers.ALL` is empty. Do not assume this is the active runtime path; verify actual calls.
- Catalog backend fallback can hide backend outage. If `CATALOG_BACKEND_URL` is unreachable, home/catalog may still render from TMDB/local/native fallbacks. Audit both generated `BuildConfig` and runtime service health.

## Android TV URL pitfall

- `10.0.2.2` is emulator-only. It is wrong for a physical Android TV device.
- For LAN-hosted services on the user's server, prefer the LAN/Tailscale host in generated BuildConfig, then rebuild:
  - `NEXSTREAM_SCRAPER_URL=http://192.168.1.50:3091`
  - `CATALOG_BACKEND_URL=http://192.168.1.50:3090/api/` if that service exists
- Verify generated values after build by inspecting generated BuildConfig or Gradle output, not just source constants.

## Source button/playback audit

- Details screen source rows must play the exact stream represented by the focused/selected row.
- Watch for bugs where UI passes `streamIndex`/stream object but `PlayerViewModel` or `PlaybackOrchestrator` ignores it and always validates/plays ranked stream 0.
- Correct pattern:
  - source row callback passes selected stream or selected index
  - `PlayerViewModel` preserves preferred stream/index
  - `PlaybackOrchestrator.prepare()` validates preferred stream first
  - fallback candidates remain available if preferred source fails
- Direct non-magnet URLs should route to direct playback; magnet/infoHash streams should route through normal debrid resolution.

## NexStream scraper service checks

Run real endpoint checks before claiming scraper compatibility:

```bash
curl -fsS http://192.168.1.50:3091/health
curl -fsS http://192.168.1.50:3091/manifest.json
curl -fsS 'http://192.168.1.50:3091/stream/movie/tt0133093.json' | jq '{count:(.streams|length), first:(.streams[0].title // .streams[0].name)}'
```

Expected route shape:
- `/health` returns service status/version and scraper/debrid availability.
- `/manifest.json` returns valid Stremio addon manifest.
- `/stream/movie/:id.json` and `/stream/series/:id.json` return `{ streams: [...] }`.

## Scraper implementation pitfalls

- Avoid shallow-copying scraper config for request overrides. Clone nested config (`structuredClone` where available) so query overrides cannot mutate global scraper state.
- If cache endpoints exist, verify they do real work. `/cache/clear` should clear L1 memory and persistent/SQLite cache, not just return a placeholder response.
- If debrid provider env vars are configured, scraper config should enable corresponding server-side debrid cache checks. Empty keys should result in no server-side debrid providers, not fake health claims.
- Progressive cache cleanup must import and call its cache helpers explicitly; don't leave dynamic imports or missing imports in hot paths.

## Verification minimum

- Build Android APK:

```bash
cd ~/Unspooled
JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 ./gradlew :app:assembleDebug
```

- Check APK exists:

```bash
du -h app/build/outputs/apk/debug/app-debug.apk
```

- Check live scraper health and at least one stream endpoint.
- If Docker/container code was patched live, restart the container and re-query health/endpoints after restart.
