Implement a new Hottub provider for `thaiporntv` at `https://www.thaiporntv.com`.

You are working inside the Hottub Rust server. Your job is to add a functioning provider module that can survive handoff to another model with minimal guesswork. Do not stop at code generation. Carry the work through code, validation, and documentation updates.

Execution order is mandatory:

1. Read the repo docs.
2. Inspect the target site and collect evidence about routes, player/media requests, and pagination.
3. Choose the closest existing provider/proxy as the template.
4. Implement the provider.
5. Validate it end to end.
6. Update docs if the new provider adds a new pattern.

Do not start coding until you know:

- latest/default feed URL
- search URL
- page 2 URL
- detail page URL
- actual media request or manifest URL
- thumbnail behavior
- whether tag/uploader/studio pages exist
- whether the site has a JSON API that is easier than HTML scraping

Read these files first:

1. `docs/README.md`
2. `docs/architecture.md`
3. `docs/provider-playbook.md`
4. `docs/provider-catalog.md`
5. `docs/hottubapp/🎬 Videos - Hot Tub Docs.html`
6. `docs/hottubapp/📡 Status - Hot Tub Docs.html`
7. `docs/hottubapp/👤 Uploaders - Hot Tub Docs.html`

Then inspect the closest existing providers and proxies before coding. Pick the nearest template instead of starting from scratch.

Template selection rules:

- Use `src/providers/vjav.rs` if the target site has JSON APIs, rich tag metadata, or stable uploader identities.
- Use `src/providers/hsex.rs` if the target site is mostly HTML and needs background-loaded tags/uploaders.
- Use `src/providers/omgxxx.rs` if the site exposes multiple large filter catalogs like sites, networks, models, or studios.
- Use `src/providers/noodlemagazine.rs`, `src/providers/pornhd3x.rs`, or `src/providers/spankbang.rs` if media or thumbnails require local `/proxy/...` routes.

Required deliverables:

1. Add a new provider file at `src/providers/<channel_id>.rs`.
2. Register it in `build.rs`.
3. Export `CHANNEL_METADATA` with the correct group.
4. Implement `get_channel` with sane options and descriptions.
5. Implement `get_videos` so the default feed works, search works, and page 2 works.
6. If the site needs proxying, add `src/proxies/<channel_id>.rs` and wire `src/proxy.rs`.
7. Reuse `requester_or_default(&options, CHANNEL_ID, "...")` for outbound requests.
8. Return high-quality `VideoItem`s with the best metadata the site exposes.
9. Do not use `embed` unless the site truly requires it.
10. Update `docs/provider-catalog.md` if you add a new provider or proxy.

Implementation requirements:

- Determine the real site routing for:
  - default/latest listing
  - search
  - page 2 and later
  - tag/category shortcuts
  - uploader/studio/model shortcuts if the site exposes them
  - featured/trending/most-viewed or similar alternate feeds
- Model routing explicitly with a local enum like `Target`.
- If the site exposes tag or uploader IDs, keep a lookup map from normalized display title to site ID/URL target.
- Put tags into `VideoItem.tags`.
- Put uploader name/url/id into `uploader`, `uploaderUrl`, and `uploaderId` when available.
- If uploader support is implemented, use a namespaced `uploaderId` such as `<channel>:<site-local-id>` so `/api/uploaders` can route directly.
- If the query matches a known tag/uploader shortcut, use the direct archive URL instead of generic search.
- If the site exposes real media URLs or HLS manifests, populate `formats`.
- If the video page URL can be directly downloaded by yt-dlp, set `video.url` to the page URL and do not populate `formats`, as yt-dlp will extract formats dynamically.
- If direct playback needs a referer/cookie transform, use a local `/proxy/...` route built with `build_proxy_url(&options, "...", target)`.
- Keep the first version small and reliable. Add extra filters only after the default feed, search, and pagination are working.

Validation requirements:

1. `cargo check -q`
2. `HOT_TUB_PROVIDER=<channel_id> cargo check -q`
3. `HOT_TUB_PROVIDER=<channel_id> cargo run --features debug`
4. Verify `/api/status` exposes the new channel.
5. Verify `/api/videos` returns results for:
   - default feed
   - search query
   - page 2
   - at least one tag/uploader shortcut if implemented
6. Verify thumbnails load.
7. Verify `yt-dlp` can resolve `video.url` (if formats are not populated) or one of `formats[*].url` (if formats are populated).
8. If a proxy route exists, verify it directly with `curl -I` or equivalent.

Testing commands to run:

```bash
curl -s http://127.0.0.1:18080/api/status \
  -H 'User-Agent: Hot%20Tub/22c CFNetwork/1494.0.7 Darwin/23.4.0' | jq
```

```bash
curl -s http://127.0.0.1:18080/api/videos \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: Hot%20Tub/22c CFNetwork/1494.0.7 Darwin/23.4.0' \
  -d '{"channel":"<channel_id>","sort":"new","page":1,"perPage":10}' | jq
```

```bash
curl -s http://127.0.0.1:18080/api/videos \
  -H 'Content-Type: application/json' \
  -d '{"channel":"<channel_id>","query":"test","page":1,"perPage":10}' | jq
```

Important Hottub-specific rules:

- Do not invent a new provider style if an existing provider already matches the site shape.
- Do not forget `build.rs`; missing registration means the provider does not exist at runtime.
- Do not create a brand-new requester in normal provider fetches unless you have a strong reason.
- Do not assume page URLs are playable media URLs.
- Do not expose status filters that you did not implement in `get_videos`.
- Do not populate `formats` if the page URL is yt-dlp compatible; instead, set `video.url` to the page URL.
- Do not finish without checking at least one returned media URL with `yt-dlp`.
- Do not claim pagination works unless page 2 was verified.

Completion format:

1. Briefly state which existing provider/proxy you used as the template and why.
2. List the files changed.
3. Report the exact validation commands you ran and whether they passed.
4. Report any residual limitations or site behaviors that still need follow-up.
