Skip to content

feat: automatic debrid cleanup driven by ARR webhooks - #391

Closed
buzzromain wants to merge 9 commits into
sirrobot01:betafrom
buzzromain:pr/arr-webhook-cleanup
Closed

buzzromain wants to merge 9 commits into
sirrobot01:betafrom
buzzromain:pr/arr-webhook-cleanup

Conversation

@buzzromain

Copy link
Copy Markdown

Summary

Adds automatic debrid cleanup driven by Sonarr/Radarr webhooks: Decypharr tracks which files it manages for each configured Arr and, optionally, removes the underlying debrid torrent when that media is deleted upstream.

  • Webhook auto-registration: Decypharr registers its own webhook notification with each configured Arr instance at startup, and bootstraps import history for media imported before the webhook was active (or during downtime).
  • arr_refs tracking: managed file paths are indexed by infohash per Arr, updated on Download/Rename/FileDelete/SeriesDelete/MovieDelete events.
  • allow_delete option per Arr (default false, opt-in): when a tracked file is deleted in Sonarr/Radarr, the tracked-file reference is always dropped; the underlying debrid torrent is only removed if allow_delete is enabled for that Arr, and only once no other tracked file still references it.
  • Authenticated webhook endpoint: the incoming webhook is verified against the Arr's own configured API token (embedded in the registered URL), since the route can't sit behind session auth — Sonarr/Radarr can't do interactive login.
  • Folder-delete scoped per Arr: a SeriesDelete/MovieDelete only ever cleans up files tracked for the Arr it came from, even if library roots happen to overlap across two configured Arrs.

Changes

  • pkg/storage/arr_files.goarr_refs store: managed-path index, per-Arr scoping
  • pkg/server/webhook_arr.go — webhook handler, token-based auth (arrWebhookAuthorized)
  • pkg/manager/arr_cleanup.go — webhook registration, import-history bootstrap, delete/rename handling
  • pkg/arr/notification.go, history.go — webhook registration API, incremental history sync
  • internal/configallow_delete field; pkg/server/templates/config.html — UI checkbox
  • Docs: docs/src/content/docs/guides/arrs.mdx
  • Tests: pkg/server/webhook_arr_test.go, pkg/storage/arr_files_test.go

Configuration example

{
  "arrs": [
    {
      "name": "Sonarr",
      "host": "http://sonarr:8989",
      "token": "API_TOKEN",
      "allow_delete": true
    }
  ]
}

Decypharr registers its webhook in Sonarr/Radarr automatically at startup — no manual webhook configuration needed.

allow_delete: false does not mean "nothing happens" when media is
deleted in Sonarr/Radarr: HandleArrDelete calls DeleteArrFile
unconditionally, only the automatic debrid removal is gated on the
flag.
/webhooks/arr sits outside authMiddleware (Sonarr/Radarr can't do
session/basic auth on webhook connections), so arrName was resolved
straight from attacker-controlled input (query param, payload
instanceName, or header) with nothing tying a request to the ARR it
claimed to be from. Combined with HandleArrDelete's DownloadId
fallback, an unauthenticated request naming any configured ARR with
allow_delete on could delete any known infohash's debrid torrent.

RegisterArrWebhooks now embeds the ARR's own API token in the
registered URL, and handleArrWebhook rejects any request whose token
doesn't match that ARR's configured one.
FindArrFilesByFolder matched any tracked file under the given folder
regardless of which ARR it belonged to. With overlapping library roots
across two configured ARRs (shared parent folder, symlinked structure),
a legitimate SeriesDelete/MovieDelete from one ARR could sweep up and
delete the other ARR's tracked files when allow_delete is on — media
it has no knowledge of or authority over.
@buzzromain

Copy link
Copy Markdown
Author

Combined with #390 into a single PR: #392

@buzzromain buzzromain closed this Aug 12, 2026
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