From 3fb4d01fea4b4619112b092a428f335e0cc49faf Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Feb 2026 06:29:22 +0000 Subject: [PATCH 1/2] fix: remove unused `included` field from WebhookPayload to prevent deserialization failures The `included` field in WebhookPayload was never accessed but was still deserialized. It used an internally-tagged serde enum (WebhookIncludedResource) with `#[serde(tag = "type")]` that could fail to deserialize if Patreon sent unexpected resource types or formats in the included array. This caused the entire webhook payload deserialization to fail with a 400 response, leading Patreon to disable the webhook after repeated failures. Since serde ignores unknown fields by default, removing the `included` field means the JSON key is simply skipped during deserialization. https://claude.ai/code/session_01B9n2M34zDHnx5NiAKS6R97 --- src/services/patreon/webhook_types.rs | 33 --------------------------- 1 file changed, 33 deletions(-) diff --git a/src/services/patreon/webhook_types.rs b/src/services/patreon/webhook_types.rs index fa5306c..e80c52d 100644 --- a/src/services/patreon/webhook_types.rs +++ b/src/services/patreon/webhook_types.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - use serde::Deserialize; /// Patreon webhook event types parsed from the `X-Patreon-Event` header. @@ -33,8 +31,6 @@ impl PatreonWebhookEvent { #[derive(Debug, Deserialize)] pub(crate) struct WebhookPayload { pub(crate) data: WebhookMemberData, - #[serde(default)] - pub(crate) included: Vec, } /// Member resource in the webhook payload (the primary `data` object). @@ -92,35 +88,6 @@ pub(crate) struct WebhookResourceRef { pub(crate) resource_type: String, } -/// Included resources in the webhook payload. -#[derive(Debug, Deserialize)] -#[serde(tag = "type")] -pub(crate) enum WebhookIncludedResource { - #[serde(rename = "user")] - User(WebhookIncludedUser), - #[serde(rename = "tier")] - Tier(WebhookIncludedTier), - #[serde(rename = "campaign")] - Campaign(WebhookIncludedCampaign), - #[serde(other)] - Other, -} - -#[derive(Debug, Deserialize)] -pub(crate) struct WebhookIncludedUser { - pub(crate) id: String, -} - -#[derive(Debug, Deserialize)] -pub(crate) struct WebhookIncludedTier { - pub(crate) id: String, -} - -#[derive(Debug, Deserialize)] -pub(crate) struct WebhookIncludedCampaign { - pub(crate) id: String, -} - #[cfg(test)] mod tests { use super::*; From 58b6dfbe34a7fbc521f897a3b2b0facb87cc9f1a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Feb 2026 06:35:38 +0000 Subject: [PATCH 2/2] fix: rename md-5 dependency and remove unused webhook type fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename md-5 to md5 via Cargo package alias so cargo-machete can trace the dependency. Remove unused fields (WebhookMemberData::id, WebhookResourceRef::resource_type) that exist in the JSON but are never read — serde silently ignores them during deserialization. https://claude.ai/code/session_01B9n2M34zDHnx5NiAKS6R97 --- Cargo.toml | 2 +- src/services/patreon/webhook_types.rs | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4ed3f9a..563a72d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ url = "2.5.8" aes-gcm = "0.10" hex = "0.4" hmac = "0.12" -md-5 = "0.10" +md5 = { package = "md-5", version = "0.10" } jsonwebtoken = { version = "10", features = ["rust_crypto"] } [dev-dependencies] diff --git a/src/services/patreon/webhook_types.rs b/src/services/patreon/webhook_types.rs index e80c52d..970d6db 100644 --- a/src/services/patreon/webhook_types.rs +++ b/src/services/patreon/webhook_types.rs @@ -36,7 +36,6 @@ pub(crate) struct WebhookPayload { /// Member resource in the webhook payload (the primary `data` object). #[derive(Debug, Deserialize)] pub(crate) struct WebhookMemberData { - pub(crate) id: String, pub(crate) attributes: WebhookMemberAttributes, #[serde(default)] pub(crate) relationships: WebhookMemberRelationships, @@ -84,8 +83,6 @@ pub(crate) struct WebhookCampaignRelationship { #[derive(Debug, Deserialize)] pub(crate) struct WebhookResourceRef { pub(crate) id: String, - #[serde(rename = "type")] - pub(crate) resource_type: String, } #[cfg(test)]