Skip to content

docs(downloads): record usenet-only decision and dead torrent cleanup - #1500

Merged
Aviator-Coding merged 4 commits into
mainfrom
fm/homeops-downloads-usenet-only
Aug 31, 2026
Merged

docs(downloads): record usenet-only decision and dead torrent cleanup#1500
Aviator-Coding merged 4 commits into
mainfrom
fm/homeops-downloads-usenet-only

Conversation

@Aviator-Coding

Copy link
Copy Markdown
Owner

Intent

Commit to usenet-only downloads: remove the dead torrent path in the downloads stack per the captain's decision. Radarr's qBittorrent download client pointed at qbittorrent.downloads.svc.cluster.local, which has no pod/Service in the cluster (qbittorrent app directory was already removed from GitOps earlier); the client was disabled and every torrent indexer in Radarr was disabled, so it was harmless but implied a torrent path that doesn't exist. Deleted that dead qBittorrent download client (Radarr id 1) and Prowlarr's four definition-less torrent indexers (BitSearch id 1, TorrentGalaxyClone id 7, Isohunt2 id 81, iDope id 80), which Prowlarr's own IndexerNoDefinitionCheck health check flagged as broken and unusable. Before deleting anything, verified via kubectl and the Radarr/Prowlarr REST APIs that the client was truly disabled/dead and the indexers were truly definition-less and unused - not live or referenced anywhere in Git. After deleting, verified Radarr and Prowlarr health checks are clean, Radarr's SABnzbd download-client connection test passes, and SABnzbd itself is responsive, confirming the usenet path still works. These deletions are live API calls against Radarr's and Prowlarr's own databases (application runtime state), NOT GitOps - there was no committed manifest referencing qbittorrent or these indexers, so there is no Kubernetes YAML diff for the deletions themselves. The committed change only documents this: docs/media-stack.md now states explicitly that the downloads stack is usenet-only by deliberate decision, and a new decision record data/decisions-2026-08-30/downloads-usenet-only.md records the full evidence trail, the exact manual API steps taken (with IDs, endpoints, and auth secrets used), verification results, and reversibility notes (torrent support can be re-added later; this only removes state that falsely implied it already worked). Out of scope and untouched: the downloads stack's storage/shared-filesystem layout, sabnzbd configuration, other arr-app settings, and backups. The remaining disabled-but-valid torrent indexers in Prowlarr (e.g. 1337x, The Pirate Bay, Nyaa.si) were deliberately left alone since they are not definition-less, just unused.

What Changed

  • Documented the captain decision that the downloads stack is deliberately usenet-only in docs/media-stack.md, including that leftover Radarr/Prowlarr torrent state was removed via live app APIs (not GitOps) and that torrent support can still be re-added later.
  • Added data/decisions-2026-08-30/downloads-usenet-only.md with the full evidence trail: pre-delete verification, the Radarr qBittorrent client and definition-less Prowlarr indexer deletions (IDs/endpoints), post-delete health checks, SABnzbd path verification, out-of-scope items, and reversibility notes.
  • Aligned the Autobrr section in docs/media-stack.md with the same usenet-only decision and decision-record link.

Risk Assessment

✅ Low: Documentation-only change that records an already-executed live API cleanup; no Kubernetes or application config is modified in Git.

Testing

Re-ran all seven live checks against the real cluster via the provided KUBECONFIG; every check matched the usenet-only decision with no contradictions, evidence was written under the pipeline evidence dir, and a second dated re-verification section was committed on the branch.

Evidence: Full live re-verification transcript (2026-08-30T23:59:39Z)
=== TIMESTAMP 2026-08-30 23:59:39 UTC ===

=== 1. kubectl -n downloads get pods,svc | grep -i qbit ===
NO_QBIT_MATCH (expected)

=== downloads pods ===
NAME                                         READY   STATUS      RESTARTS        AGE
autobrr-6cd76b8d99-vfhf2                     1/1     Running     0               77s
bazarr-679bd89cdc-6w5dc                      1/1     Running     0               4d12h
downloads-janitor-29801370-8njwm             0/1     Completed   0               14h
lidarr-79f96c96f9-6vdrv                      1/1     Running     4 (2d16h ago)   4d13h
prowlarr-8cfc5f65d-hl4mh                     1/1     Running     1 (2d16h ago)   4d13h
radarr-85df77f767-5jl6q                      1/1     Running     5 (2d16h ago)   4d12h
readarr-7459b7d8d9-d7w46                     2/2     Running     12 (29h ago)    4d12h
reading-glasses-7448449dbf-jxx7q             1/1     Running     0               4d13h
reading-glasses-cache-prune-29800980-kv5q5   0/1     Completed   0               20h
sabnzbd-65d8f7b865-klqtw                     1/1     Running     0               4d13h
sonarr-5f76c4bf6c-pzv5q                      1/1     Running     6 (2d16h ago)   4d12h

=== downloads svc ===
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
autobrr           ClusterIP   10.43.131.60    <none>        7474/TCP,9094/TCP   328d
bazarr            ClusterIP   10.43.194.71    <none>        6767/TCP            328d
lidarr            ClusterIP   10.43.112.226   <none>        8080/TCP            328d
prowlarr          ClusterIP   10.43.116.157   <none>        9696/TCP            328d
radarr            ClusterIP   10.43.70.133    <none>        7878/TCP            328d
readarr           ClusterIP   10.43.236.49    <none>        8787/TCP,9707/TCP   323d
reading-glasses   ClusterIP   10.43.64.138    <none>        80/TCP              224d
sabnzbd           ClusterIP   10.43.49.47     <none>        8080/TCP            328d
sonarr            ClusterIP   10.43.190.184   <none>        8989/TCP            328d

=== 2. Radarr GET /api/v3/downloadclient ===
[
    {
        "enable": true,
        "protocol": "usenet",
        "priority": 1,
        "removeCompletedDownloads": true,
        "removeFailedDownloads": true,
        "name": "SABnzbd",
        "fields": [
            {
                "order": 0,
                "name": "host",
                "label": "Host",
                "value": "sabnzbd.downloads",
                "type": "textbox",
                "advanced": false,
                "privacy": "normal",
                "isFloat": false
            },
            {
                "order": 1,
                "name": "port",
                "label": "Port",
                "value": 8080,
                "type": "textbox",
                "advanced": false,
                "privacy": "normal",
                "isFloat": false
            },
            {
                "order": 2,
                "name": "useSsl",
                "label": "Use SSL",
                "helpText": "Use secure connection when connection to Sabnzbd",
                "value": false,
                "type": "checkbox",
                "advanced": false,
                "privacy": "normal",
                "isFloat": false
            },
            {
                "order": 3,
                "name": "urlBase",
                "label": "URL Base",
                "helpText": "Adds a prefix to the Sabnzbd url, such as http://[host]:[port]/[urlBase]/api",
                "type": "textbox",
                "advanced": true,
                "privacy": "normal",
                "isFloat": false
            },
            {
                "order": 4,
                "name": "apiKey",
                "label": "API Key",
                "value": "********",
                "type": "textbox",
                "advanced": false,
                "privacy": "apiKey",
                "isFloat": false
            },
            {
                "order": 5,
                "name": "username",
                "label": "Username",
                "type": "textbox",
                "advanced": false,
                "privacy": "userName",
                "isFloat": false
            },
            {
                "order": 6,
                "name": "password",
                "label": "Password",
                "type": "password",
                "advanced": false,
                "privacy": "password",
                "isFloat": false
            },
            {
                "order": 7,
                "name": "movieCategory",
                "label": "Category",
                "helpText": "Adding a category specific to Radarr avoids conflicts with unrelated non-Radarr downloads. Using a category is optional, but strongly recommended.",
                "value": "movies",
                "type": "textbox",
                "advanced": false,
                "privacy": "normal",
                "isFloat": false
            },
            {
                "order": 8,
                "name": "recentMoviePriority",
                "label": "Recent Priority",
                "helpText": "Priority to use when grabbing movies that aired within the last 21 days",
                "value": -100,
                "type": "select",
                "advanced": false,
                "selectOptions": [
                    {
                        "value": -100,
                        "name": "Default",
                        "order": -100,
                        "dividerAfter": false
                    },
                    {
                        "value": -2,
                        "name": "Paused",
                        "order": -2,
                        "dividerAfter": false
                    },
                    {
                        "value": -1,
                        "name": "Low",
                        "order": -1,
                        "dividerAfter": false
                    },
                    {
                        "value": 0,
                        "name": "Normal",
                        "order": 0,
                        "dividerAfter": false
                    },
                    {
                        "value": 1,
                        "name": "High",
                        "order": 1,
                        "dividerAfter": false
                    },
                    {
                        "value": 2,
                        "name": "Force",
                        "order": 2,
                        "dividerAfter": false
                    }
                ],
                "privacy": "normal",
                "isFloat": false
            },
            {
                "order": 9,
                "name": "olderMoviePriority",
                "label": "Older Priority",
                "helpText": "Priority to use when grabbing movies that aired over 21 days ago",
                "value": -100,
                "type": "select",
                "advanced": false,
                "selectOptions": [
                    {
                        "value": -100,
                        "name": "Default",
                        "order": -100,
                        "dividerAfter": false
                    },
                    {
                        "value": -2,
                        "name": "Paused",
                        "order": -2,
                        "dividerAfter": false
                    },
                    {
                        "value": -1,
                        "name": "Low",
                        "order": -1,
                        "dividerAfter": false
                    },
                    {
                        "value": 0,
                        "name": "Normal",
                        "order": 0,
                        "dividerAfter": false
                    },
                    {
                        "value": 1,
                        "name": "High",
                        "order": 1,
                        "dividerAfter": false
                    },
                    {
                        "value": 2,
                        "name": "Force",
                        "order": 2,
                        "dividerAfter": false
                    }
                ],
                "privacy": "normal",
                "isFloat": false
            }
        ],
        "implementationName": "SABnzbd",
        "implementation": "Sabnzbd",
        "configContract": "SabnzbdSettings",
        "infoLink": "https://wiki.servarr.com/radarr/supported#sabnzbd",
        "tags": [],
        "id": 2
    }
]

=== 3. Radarr GET /api/v3/health ===
[
    {
        "source": "UpdateCheck",
        "type": "warning",
        "message": "New update is available: v6.4.2.10590",
        "wikiUrl": "https://wiki.servarr.com/radarr/system#new-update-is-available"
    }
]

=== 4. Prowlarr GET /api/v1/indexer (names/ids/enable) ===

=== 4b. full indexer JSON names only grep banned ===
BitSearch ABSENT
TorrentGalaxyClone ABSENT
Isohunt2 ABSENT
iDope ABSENT

=== 5. Prowlarr GET /api/v1/health ===
[
    {
        "source": "UpdateCheck",
        "type": "warning",
        "message": "New update is available: v2.6.2.5562",
        "wikiUrl": "https://wiki.servarr.com/prowlarr/system#new-update-is-available"
    }
]

=== 6. SABnzbd mode=version ===
{
    "version": "5.1.0"
}

=== 6b. SABnzbd mode=queue ===
{
    "queue": {
        "version": "5.1.0",
        "paused": false,
        "pause_int": "0",
        "paused_all": false,
        "diskspace1": "1475.38",
        "diskspace2": "2030.76",
        "diskspace1_norm": "1.4 T",
        "diskspace2_norm": "2.0 T",
        "diskspacetotal1": "1475.39",
        "diskspacetotal2": "2048.00",
        "speedlimit": "80",
        "speedlimit_abs": "503316480",
        "have_warnings": "14",
        "finishaction": null,
        "quota": "0 B",
        "have_quota": false,
        "left_quota": "0 B",
        "cache_art": "0",
        "cache_size": "0 B",
        "kbpersec": "0.00",
        "speed": "0",
        "mbleft": "0.00",
        "mb": "0.00",
        "sizeleft": "0 B",
        "size": "0 B",
        "noofslots_total": 0,
        "noofslots": 0,
        "start": 0,
        "limit": 0,
        "finish": 0,
        "status": "Idle",
        "timeleft": "0:00:00",
        "slots": []
    }
}

=== 7. Radarr downloadclient test id=2 forceTest ===
client2_summary:
{'id': 2, 'name': 'SABnzbd', 'enable': True, 'protocol': 'usenet', 'implementation': 'Sabnzbd'}
test_result:
{}
test_http_code:
200
test_body:
{}
Evidence: Second-pass summary (all seven checks)

1. NO_QBIT_MATCH 2. Radarr clients: only SABnzbd id=2 enable=true usenet 3. Radarr health: only UpdateCheck v6.4.2.10590 4. Prowlarr: BitSearch/TorrentGalaxyClone/Isohunt2/iDope ABSENT (ids 1/7/81/80 ABSENT) 5. Prowlarr health: IndexerNoDefinitionCheck gone; only UpdateCheck v2.6.2.5562 6. SABnzbd version 5.1.0, queue Idle 7. Radarr→SABnzbd test HTTP 200 {} Result: NO CONTRADICTIONS

Live re-verification second pass — 2026-08-30T23:59:39Z UTC
KUBECONFIG=/Users/coder/firstmate/projects/home-ops/kubeconfig

1. kubectl -n downloads get pods,svc | grep -i qbit → NO_QBIT_MATCH
2. Radarr GET /api/v3/downloadclient → only SABnzbd id=2 enable=true protocol=usenet; no qBittorrent
3. Radarr GET /api/v3/health → only UpdateCheck warning v6.4.2.10590
4. Prowlarr GET /api/v1/indexer → 16 indexers; BitSearch/TorrentGalaxyClone/Isohunt2/iDope ABSENT (ids 1/7/81/80 ABSENT)
5. Prowlarr GET /api/v1/health → IndexerNoDefinitionCheck gone; only UpdateCheck v2.6.2.5562
6. SABnzbd mode=version → 5.1.0; mode=queue → Idle paused=false slots=[]
7. Radarr POST /api/v3/downloadclient/test?forceTest=true (client id 2) → HTTP 200 body {}

Result: NO CONTRADICTIONS with usenet-only decision.
Evidence: Prowlarr indexer list (redacted names/ids/enable/protocol)
[
  {
    "id": 45,
    "name": "1337x",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  },
  {
    "id": 13,
    "name": "altHUB",
    "enable": false,
    "protocol": "usenet",
    "implementation": "Newznab"
  },
  {
    "id": 84,
    "name": "EBookBay",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  },
  {
    "id": 5,
    "name": "Internet Archive",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  },
  {
    "id": 78,
    "name": "kickasstorrents.to",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  },
  {
    "id": 2,
    "name": "Knaben",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Knaben"
  },
  {
    "id": 3,
    "name": "LimeTorrents",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  },
  {
    "id": 12,
    "name": "Miatrix",
    "enable": true,
    "protocol": "usenet",
    "implementation": "Newznab"
  },
  {
    "id": 9,
    "name": "Nyaa.si",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  },
  {
    "id": 11,
    "name": "NZBFinder",
    "enable": true,
    "protocol": "usenet",
    "implementation": "Newznab"
  },
  {
    "id": 14,
    "name": "NZBgeek",
    "enable": true,
    "protocol": "usenet",
    "implementation": "Newznab"
  },
  {
    "id": 10,
    "name": "NzbNoob",
    "enable": false,
    "protocol": "usenet",
    "implementation": "Newznab"
  },
  {
    "id": 83,
    "name": "RuTracker.org",
    "enable": false,
    "protocol": "torrent",
    "implementation": "RuTracker"
  },
  {
    "id": 4,
    "name": "The Pirate Bay",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  },
  {
    "id": 82,
    "name": "Torrent Downloads",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  },
  {
    "id": 6,
    "name": "Uindex",
    "enable": false,
    "protocol": "torrent",
    "implementation": "Cardigann"
  }
]
Evidence: Updated decision record with second live re-verification section
# Decision: downloads stack is usenet-only

Date: 2026-08-30

## Decision

Commit the `downloads` namespace to usenet-only acquisition. Remove the dead
torrent path rather than leave it half-configured:

- Deleted Radarr's `qBittorrent` download client (id 1).
- Deleted Prowlarr's four definition-less torrent indexers: `BitSearch` (id 1),
  `TorrentGalaxyClone` (id 7), `Isohunt2` (id 81), `iDope` (id 80).

## Why

Radarr's qBittorrent download client pointed at
`qbittorrent.downloads.svc.cluster.local`, which has no pod and no Service in
the cluster - `qbittorrent` was already removed as a dead, unreferenced app
directory (see `docs/media-stack.md`, `kubernetes/components/volsync/Readme.md`
line ~384). The client was harmless only because it was `enable: false` and
every torrent indexer in Radarr was disabled, but its presence implied a
torrent path that did not actually exist and could silently be relied upon by
a future change.

Separately, Prowlarr's own `IndexerNoDefinitionCheck` health check flagged
`BitSearch`, `TorrentGalaxyClone`, `Isohunt2`, and `iDope` as having no
working indexer definition ("Indexers have no definition and will not work
... Please remove and (or) re-add to Prowlarr"). These four were disabled,
torrent-protocol, and structurally broken regardless of the qBittorrent
decision.

## Evidence gathered before deletion (verify-before-delete)

- `kubectl -n downloads get pods,svc`: no `qbittorrent` pod or Service exists.
- Radarr `GET /api/v3/downloadclient`: qBittorrent client (id 1) had
  `"enable": false`; SABnzbd (id 2) had `"enable": true` and was the only
  enabled client.
- Prowlarr `GET /api/v1/health` (before deletion): reported
  `IndexerNoDefinitionCheck` error naming exactly these four indexers.
- Prowlarr `GET /api/v1/indexer`: confirmed all four as `protocol: torrent`,
  `enable: false`.
- No GitOps manifest anywhere in `kubernetes/` references qbittorrent, any of
  the four indexer names, or their download-client/indexer IDs - this
  configuration lives entirely in each app's own Postgres-backed database,
  reached only through its REST API.

## What changed and how (manual/live API steps - NOT GitOps)

This is entirely runtime application state, not committed manifests, so there
is no Kubernetes YAML diff for the deletions themselves:

- `DELETE /api/v3/downloadclient/1` against Radarr (`radarr.downloads.svc`),
  authenticated with the API key from Kubernetes Secret `radarr-secret`
  (`RADARR__AUTH__APIKEY`). Response: 200.
- `DELETE /api/v1/indexer/{1,7,81,80}` against Prowlarr
  (`prowlarr.downloads.svc`), authenticated with the API key from Secret
  `prowlarr-secret` (`PROWLARR__AUTH__APIKEY`). Response: 200 for each.

Anyone reproducing or rolling back this change must use the same app APIs
(or the web UI) - there is nothing to `git revert` for the deletions
themselves. Only the documentation update in `docs/media-stack.md` is a Git
change.

## Verification after deletion

- Prowlarr `GET /api/v1/health`: `IndexerNoDefinitionCheck` error is gone;
  only the routine "new update available" notice remains.
- Radarr `GET /api/v3/health`: clean (only the routine update notice).
- Radarr `GET /api/v3/downloadclient`: only SABnzbd (id 2) remains.
- Radarr `POST /api/v3/downloadclient/test` against the SABnzbd client:
  200, empty body (success).
- SABnzbd `GET /api?mode=queue` and `mode=version`: responsive, healthy
  (v5.1.0), confirming the usenet path itself was never touched and still
  works.
- Prowlarr `GET /api/v1/indexer`: the remaining list contains no BitSearch,
  TorrentGalaxyClone, Isohunt2, or iDope entries; all other indexers
  (usenet and torrent) are untouched.

## Explicitly out of scope (not touched)

- Storage layout / shared-filesystem question for `downloads`.
- sabnzbd configuration.
- Any other arr-app settings.
- Backups.
- The remaining disabled torrent indexers in Prowlarr that DO have working
  definitions (e.g. `1337x`, `The Pirate Bay`, `Nyaa.si`, etc.) - those were
  left alone since they are not "definition-less," they are simply unused.

## Reversibility

Deploying qBittorrent (or another torrent client) later remains entirely
possible: add its app directory back under `kubernetes/apps/base/downloads/`
and `kubernetes/apps/main/downloads/`, then re-add the download client in
Radarr and any indexers wanted in Prowlarr. Nothing about this change removes
that option; it only removes state that falsely implied the option was
already exercised.

## Re-verification (post-commit, no-mistakes pipeline)

Date/time: 2026-08-30T23:57:33Z (UTC) / 2026-08-30 19:58 EDT

Fresh live checks against the cluster from the no-mistakes fix step, using
`KUBECONFIG=/Users/coder/firstmate/projects/home-ops/kubeconfig`. These are
independent of the original verification section above and re-prove the
deletions still hold in application runtime state.

**Result: no contradictions.** Every check matches the original post-delete
state. No qBittorrent pod/Service, no deleted Radarr client, none of the four
deleted Prowlarr indexers, clean health (routine update notices only), and
SABnzbd still healthy on the usenet path.

1. **No qbittorrent in-cluster**
   - `kubectl -n downloads get pods,svc` listed Running pods for autobrr,
     bazarr, lidarr, prowlarr, radarr, readarr, reading-glasses, sabnzbd,
     sonarr (plus completed CronJobs) and matching Services.
   - `grep -i qbit` over that listing: **no matches** (no pod, no Service).

2. **Radarr download clients** (`GET /api/v3/downloadclient`, API key from
   Secret `radarr-secret` / `RADARR__AUTH__APIKEY`, port-forward
   `svc/radarr 17878:7878`)
   - List contains **exactly one** client: SABnzbd id **2**,
     `enable: true`, `protocol: usenet`, `implementation: Sabnzbd`,
     host `sabnzbd.downloads:8080`.
   - **No** qBittorrent entry (id 1 remains deleted).

3. **Radarr health** (`GET /api/v3/health`)
   - Clean except routine notice only:
     `UpdateCheck` warning — "New update is available: v6.4.2.10590".
   - No download-client or indexer errors.

4. **Prowlarr indexers** (`GET /api/v1/indexer`, API key from Secret
   `prowlarr-secret` / `PROWLARR__AUTH__APIKEY`, port-forward
   `svc/prowlarr 19696:9696`)
   - 16 indexers total. **None** of BitSearch, TorrentGalaxyClone, Isohunt2,
     or iDope are present (ids 1 / 7 / 81 / 80 remain deleted).
   - Deliberately-retained disabled torrent indexers still present, e.g.
     `1337x` (id 45, enable false), `The Pirate Bay` (id 4, enable false),
     `Nyaa.si` (id 9, enable false).
   - Enabled usenet indexers still present: Miatrix (12), NZBFinder (11),
     NZBgeek (14).

5. **Prowlarr health** (`GET /api/v1/health`)
   - `IndexerNoDefinitionCheck` error is **gone**.
   - Clean except routine notice only:
     `UpdateCheck` warning — "New update is available: v2.6.2.5562".

6. **SABnzbd usenet path** (API key from Secret `sabnzbd-secret` /
   `SABNZBD_API_KEY`, port-forward `svc/sabnzbd 18080:8080`)
   - `GET /api?mode=version&output=json` → `{"version": "5.1.0"}`.
   - `GET /api?mode=queue&output=json` → `status: Idle`, `paused: false`,
     `noofslots_total: 0`, empty slots. Responsive and healthy.

7. **Radarr → SABnzbd connection test**
   - `POST /api/v3/downloadclient/test?forceTest=true` with the body of
     download client id 2 (SABnzbd).
   - HTTP **200**, empty JSON body `{}` (Servarr success shape).

## Re-verification (post-commit, no-mistakes pipeline — second live pass)

Date/time: 2026-08-30T23:59:39Z (UTC)

Second independent live pass from the no-mistakes test/fix step after the
user confirmed cluster reachability via
`KUBECONFIG=/Users/coder/firstmate/projects/home-ops/kubeconfig`. Distinct
from both the original post-delete verification and the 23:57:33Z
re-verification above; full command transcript saved outside Git as
pipeline evidence.

**Result: no contradictions.** Runtime state still matches the usenet-only
decision. No qBittorrent pod/Service, no Radarr qBittorrent client, none of
the four deleted definition-less Prowlarr indexers, clean health (routine
update notices only), SABnzbd healthy, and Radarr→SABnzbd connection test
still passes.

1. **No qbittorrent in-cluster**
   - `kubectl -n downloads get pods,svc | grep -i qbit` → **NO_QBIT_MATCH**.
   - Running pods: autobrr, bazarr, lidarr, prowlarr, radarr, readarr,
     reading-glasses, sabnzbd, sonarr (+ completed CronJobs).
   - Services: same set; **no** `qbittorrent` Service.

2. **Radarr download clients** (`GET /api/v3/downloadclient`, API key from
   Secret `radarr-secret` / `RADARR__AUTH__APIKEY`, port-forward
   `svc/radarr 17878:7878`)
   - Exactly one client: SABnzbd id **2**, `enable: true`,
     `protocol: usenet`, `implementation: Sabnzbd`, host `sabnzbd.downloads`,
     port `8080`, category `movies`.
   - **No** qBittorrent entry (deleted id 1 still absent).

3. **Radarr health** (`GET /api/v3/health`)
   - Only routine `UpdateCheck` warning: "New update is available:
     v6.4.2.10590".
   - No download-client, indexer, or connection errors.

4. **Prowlarr indexers** (`GET /api/v1/indexer`, API key from Secret
   `prowlarr-secret` / `PROWLARR__AUTH__APIKEY`, port-forward
   `svc/prowlarr 19696:9696`)
   - 16 indexers total.
   - BitSearch / TorrentGalaxyClone / Isohunt2 / iDope: **ABSENT** (string
     search and ids 1 / 7 / 81 / 80 all absent).
   - Retained disabled torrent indexers still present: `1337x` (45),
     `The Pirate Bay` (4), `Nyaa.si` (9), plus others left deliberately.
   - Enabled usenet indexers still present: Miatrix (12), NZBFinder (11),
     NZBgeek (14).

5. **Prowlarr health** (`GET /api/v1/health`)
   - `IndexerNoDefinitionCheck` **gone**.
   - Only routine `UpdateCheck` warning: "New update is available:
     v2.6.2.5562".

6. **SABnzbd usenet path** (API key from Secret `sabnzbd-secret` /
   `SABNZBD_API_KEY`, port-forward `svc/sabnzbd 18080:8080`)
   - `mode=version` → `{"version": "5.1.0"}`.
   - `mode=queue` → `status: Idle`, `paused: false`, `noofslots_total: 0`,
     empty slots; responsive.

7. **Radarr → SABnzbd connection test**
   - `POST /api/v3/downloadclient/test?forceTest=true` with download client
     id 2 body.
   - HTTP **200**, body `{}` (Servarr success).
- Outcome: 🔧 1 issue found → auto-fixed ✅ across 2 runs (6m38s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

🔧 **Test** - 1 issue found → auto-fixed ✅
  • ⚠️ This sandbox has no kubeconfig/cluster access, so Radarr download-client list, Prowlarr indexer/health, SABnzbd queue/version, and the post-delete connection test could not be re-run live. Git-side intent checks all pass (docs-only commit; media-stack usenet-only statement; decision record with IDs/endpoints/verify/reversibility; downloads overlay has sabnzbd and no qbittorrent). Live runtime deletions remain proven only by the author-recorded trail in data/decisions-2026-08-30/downloads-usenet-only.md—re-check on-cluster if you need independent confirmation those API deletes still hold.
  • git diff --name-only 4f7fe33ed080bacf055b30e63db366fec6c07972..HEAD (docs-only: decision record + media-stack)
  • Semantic parse of kubernetes/apps/main/downloads/kustomization.yaml resources (sabnzbd present, qbittorrent/cross-seed absent)
  • Path checks: kubernetes/apps/base/downloads/qbittorrent and kubernetes/apps/main/downloads/qbittorrent.yaml absent; sabnzbd present
  • rg over kubernetes/ for qbittorrent/BitSearch/TorrentGalaxyClone/Isohunt2/iDope (only historical volsync Readme prose)
  • Decision-record contract check: required sections, DELETE endpoints/IDs, secrets, post-delete verification, out-of-scope (1337x/TPB/Nyaa), reversibility
  • docs/media-stack.md overview contains deliberate usenet-only decision text and link to decision record
  • kubectl cluster-info / API reachability (unreachable; no kubeconfig)

🔧 Fix: Document live usenet-only re-verification evidence
✅ Re-checked - no issues remain.

  • export KUBECONFIG=/Users/coder/firstmate/projects/home-ops/kubeconfig
  • kubectl -n downloads get pods,svc | grep -i qbit → NO_QBIT_MATCH
  • kubectl -n downloads get pods / get svc → sabnzbd present, no qbittorrent
  • port-forward svc/radarr 17878:7878; GET /api/v3/downloadclient → only SABnzbd id 2 enable true
  • GET /api/v3/health (Radarr) → only routine UpdateCheck warning
  • port-forward svc/prowlarr 19696:9696; GET /api/v1/indexer → BitSearch/TorrentGalaxyClone/Isohunt2/iDope and ids 1/7/81/80 absent
  • GET /api/v1/health (Prowlarr) → IndexerNoDefinitionCheck gone; only UpdateCheck
  • port-forward svc/sabnzbd 18080:8080; GET /api?mode=version → 5.1.0; mode=queue → Idle
  • POST /api/v3/downloadclient/test?forceTest=true (Radarr client id 2) → HTTP 200 {}
  • appended and committed second re-verification section in data/decisions-2026-08-30/downloads-usenet-only.md (c7b5f282)
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

…moval

Deleted Radarr's dead qBittorrent download client and Prowlarr's four
definition-less torrent indexers (BitSearch, TorrentGalaxyClone, Isohunt2,
iDope) via their own APIs - live application state, not GitOps, so there is
no manifest diff for the deletions themselves. Documents the decision, the
verify-before-delete evidence, and the manual API steps taken.
Independent cluster pass after confirming KUBECONFIG reachability:
no qbittorrent, Radarr only SABnzbd, four definition-less Prowlarr
indexers still gone, health clean, SABnzbd and connection test OK.
@github-actions

Copy link
Copy Markdown

Automated recommendation: APPROVE

Analysis engine: pr-review-local@http://litellm.ai.svc.cluster.local:4000/v1 (openai)

Recommendation

Approve. This is a documentation-only PR that records a deliberate architectural decision (usenet-only downloads) and the evidence trail for a live API cleanup that has already been performed. It introduces no Kubernetes manifests, no configuration changes, and no runtime risk.

Change-by-Change Findings

data/decisions-2026-08-30/downloads-usenet-only.md (new file)

  • Decision clarity: The decision is stated explicitly: the downloads stack is usenet-only by deliberate captain decision, not by accident.
  • Evidence trail: The document provides a thorough, reproducible evidence trail: pre-delete verification (no qBittorrent pod/Service, qBittorrent client disabled, four definition-less indexers flagged by Prowlarr health check), the exact API calls made (with IDs and endpoints), and post-delete verification (clean health checks, SABnzbd connection test passes).
  • Reversibility: Clearly documented that torrent support can be re-added later by deploying qBittorrent and re-adding indexers. This removes the "illusion" of half-working state without closing the door on future options.
  • Re-verification: Includes two independent post-commit re-verification passes, demonstrating diligence and reducing the risk of "I did it wrong" errors.
  • No secrets in diff: The document references API keys from Kubernetes Secrets (radarr-secret, prowlarr-secret, sabnzbd-secret) but does not include the actual key values. This is compliant with the "no plaintext secrets" rule.

docs/media-stack.md (modified)

  • Alignment: The main media stack documentation is updated to reflect the usenet-only decision and links to the new decision record.
  • Autobrr section: Correctly notes that Autobrr's torrent-side integrations are unused until torrent support is deliberately re-added.
  • Consistency: The change is minimal (3 additions, 1 deletion) and directly supports the new decision record.

Standards Compliance

  • No plaintext secrets: The diff contains no literal tokens, passwords, API keys, or private keys. References to secrets are via Kubernetes Secret names only. Pass.
  • Documentation conventions: The decision record follows the repo's pattern of dated decision files in data/decisions-YYYY-MM-DD/. The main docs are updated to reference it. Pass.
  • No Kubernetes manifests changed: No Flux, Kustomize, Helm, or other manifest files are modified, so no Flux/Kustomize conventions (schema comments, layout, naming, healthChecks, etc.) are applicable. N/A.
  • No networking changes: No Cilium policies, Gateway API resources, or network configurations are modified. N/A.
  • No GitHub Actions changes: No workflows are modified. N/A.
  • No Talos/Renovate changes: No machine configs or Renovate configuration files are modified. N/A.

Tool Harness Findings

Tool harness is disabled.

Unknowns or Needs Verification

  • The PR body states that the live API deletions were already performed against the cluster. This review cannot verify the runtime state changes (only the documentation diff is available), but the extensive evidence trail in the decision record and the two re-verification passes provide strong confidence that the deletions were performed correctly and the usenet path remains functional.
  • The decision record references specific API keys from Kubernetes Secrets. While the keys themselves are not in the diff, reviewers with cluster access could verify that the referenced Secrets (radarr-secret, prowlarr-secret, sabnzbd-secret) exist and are properly configured as ExternalSecrets (per repo standards). This is a low-risk verification given the documentation-only nature of the PR.

@Aviator-Coding
Aviator-Coding merged commit a26bfb2 into main Aug 31, 2026
2 checks passed
Aviator-Coding added a commit that referenced this pull request Aug 31, 2026
* fix(sabnzbd): remove dead cross-seed integration

cross-seed was retired from the cluster on 2026-08-23 (dead, unreferenced
app directory) and the downloads stack committed usenet-only on
2026-08-30 (#1500), but sabnzbd's HelmRelease, ExternalSecret, and
xseed.sh post-processing script were never cleaned up.

Confirmed the integration was already fully inert before removing it:
sabnzbd.ini's script_dir is unset and no category names xseed.sh, so it
has never been invoked - zero matches for xseed/cross-seed across 5+
months of rotated sabnzbd logs, and every history entry shows script:
None. The ExternalSecret was still syncing fine (Ready=True), just
pulling a now-pointless 1Password credential.

Removes the XSEED_HOST/XSEED_PORT env vars, the scripts persistence
mount and its configMapGenerator/kustomizeconfig plumbing, the xseed.sh
script itself, and the ExternalSecret's XSEED_APIKEY entry. Verified
live pre-merge (suspend/patch/resume) that sabnzbd still downloads and
post-processes cleanly, and that Sonarr imports the result, with no
XSEED env var or scripts mount present.

* no-mistakes(document): Drop stale sabnzbd scripts mount note
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant