Skip to main content

worldinterface_http_trigger/
registration.rs

1//! Webhook registration model.
2
3use serde::{Deserialize, Serialize};
4use worldinterface_core::flowspec::FlowSpec;
5
6use crate::types::WebhookId;
7
8/// A registered webhook that maps an HTTP path to a FlowSpec.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct WebhookRegistration {
11    /// Unique webhook identifier.
12    pub id: WebhookId,
13
14    /// The URL path that triggers this webhook (e.g., "github/push", "stripe/invoice").
15    /// Does not include the `/webhooks/` prefix -- that is added by the router.
16    pub path: String,
17
18    /// The FlowSpec to execute when the webhook fires.
19    pub flow_spec: FlowSpec,
20
21    /// Optional human-readable description.
22    #[serde(default, skip_serializing_if = "Option::is_none")]
23    pub description: Option<String>,
24
25    /// Unix timestamp (seconds) when the webhook was registered.
26    pub created_at: u64,
27}
28
29#[cfg(test)]
30mod tests {
31    use serde_json::json;
32    use worldinterface_core::flowspec::*;
33    use worldinterface_core::id::NodeId;
34
35    use super::*;
36
37    fn sample_registration() -> WebhookRegistration {
38        let node_id = NodeId::new();
39        WebhookRegistration {
40            id: WebhookId::new(),
41            path: "github/push".to_string(),
42            flow_spec: FlowSpec {
43                id: None,
44                name: Some("test".into()),
45                nodes: vec![Node {
46                    id: node_id,
47                    label: None,
48                    node_type: NodeType::Connector(ConnectorNode {
49                        connector: "delay".into(),
50                        params: json!({"duration_ms": 10}),
51                        idempotency_config: None,
52                    }),
53                }],
54                edges: vec![],
55                params: None,
56            },
57            description: Some("GitHub push handler".to_string()),
58            created_at: 1741200000,
59        }
60    }
61
62    #[test]
63    fn serialization_roundtrip() {
64        let reg = sample_registration();
65        let json = serde_json::to_string(&reg).unwrap();
66        let back: WebhookRegistration = serde_json::from_str(&json).unwrap();
67        assert_eq!(reg.id, back.id);
68        assert_eq!(reg.path, back.path);
69        assert_eq!(reg.description, back.description);
70        assert_eq!(reg.created_at, back.created_at);
71    }
72
73    #[test]
74    fn serialization_without_description() {
75        let mut reg = sample_registration();
76        reg.description = None;
77        let json = serde_json::to_string(&reg).unwrap();
78        let back: WebhookRegistration = serde_json::from_str(&json).unwrap();
79        assert_eq!(back.description, None);
80    }
81}