Skip to main content

orchestrator_config/config/
trigger.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4use crate::cli_types::ConcurrencyPolicy;
5
6/// Stored configuration for a Trigger resource.
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
8pub struct TriggerConfig {
9    /// Cron schedule (mutually exclusive with `event`).
10    #[serde(default, skip_serializing_if = "Option::is_none")]
11    pub cron: Option<TriggerCronConfig>,
12
13    /// Event source (mutually exclusive with `cron`).
14    #[serde(default, skip_serializing_if = "Option::is_none")]
15    pub event: Option<TriggerEventConfig>,
16
17    /// Action to take when the trigger fires.
18    pub action: TriggerActionConfig,
19
20    /// Concurrency policy.
21    #[serde(default)]
22    pub concurrency_policy: ConcurrencyPolicy,
23
24    /// Whether the trigger is suspended.
25    #[serde(default)]
26    pub suspend: bool,
27
28    /// History retention limits.
29    #[serde(default, skip_serializing_if = "Option::is_none")]
30    pub history_limit: Option<TriggerHistoryLimitConfig>,
31
32    /// Throttle settings.
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub throttle: Option<TriggerThrottleConfig>,
35}
36
37/// Stored cron schedule.
38#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
39pub struct TriggerCronConfig {
40    /// Standard 5-field cron expression.
41    pub schedule: String,
42    /// IANA timezone name; defaults to UTC.
43    #[serde(default, skip_serializing_if = "Option::is_none")]
44    pub timezone: Option<String>,
45}
46
47/// Stored event source configuration.
48#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
49pub struct TriggerEventConfig {
50    /// Event source type (e.g. `task_completed`, `task_failed`, `webhook`, `filesystem`).
51    pub source: String,
52    /// Optional filter conditions.
53    #[serde(default, skip_serializing_if = "Option::is_none")]
54    pub filter: Option<TriggerEventFilterConfig>,
55    /// Webhook-specific authentication configuration.
56    #[serde(default, skip_serializing_if = "Option::is_none")]
57    pub webhook: Option<TriggerWebhookConfig>,
58    /// Filesystem watcher configuration.
59    #[serde(default, skip_serializing_if = "Option::is_none")]
60    pub filesystem: Option<TriggerFilesystemConfig>,
61}
62
63/// Stored filesystem watcher configuration.
64#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
65pub struct TriggerFilesystemConfig {
66    /// Directories to watch (relative to Workspace root_path).
67    pub paths: Vec<String>,
68    /// Event types to subscribe to: "create", "modify", "delete".
69    #[serde(default, skip_serializing_if = "Vec::is_empty")]
70    pub events: Vec<String>,
71    /// Debounce window in milliseconds.
72    #[serde(default = "default_fs_debounce_ms")]
73    pub debounce_ms: u64,
74}
75
76fn default_fs_debounce_ms() -> u64 {
77    500
78}
79
80/// Webhook authentication configuration for per-trigger secret verification.
81#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
82pub struct TriggerWebhookConfig {
83    /// SecretStore reference for signature verification.
84    /// All values in the store are tried (supports key rotation).
85    #[serde(default, skip_serializing_if = "Option::is_none")]
86    pub secret: Option<TriggerSecretRef>,
87    /// Custom HTTP header name for the signature (default: `X-Webhook-Signature`).
88    #[serde(default, skip_serializing_if = "Option::is_none")]
89    pub signature_header: Option<String>,
90    /// CRD kind name for plugin lookup. When set, the daemon resolves the CRD's
91    /// plugins and executes interceptors/transformers in the webhook request path.
92    #[serde(default, skip_serializing_if = "Option::is_none")]
93    pub crd_ref: Option<String>,
94}
95
96/// Reference to a SecretStore for webhook secret resolution.
97#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
98pub struct TriggerSecretRef {
99    /// Name of the SecretStore to resolve.
100    pub from_ref: String,
101}
102
103/// Stored event filter.
104#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
105pub struct TriggerEventFilterConfig {
106    /// Match events from a specific workflow.
107    #[serde(default, skip_serializing_if = "Option::is_none")]
108    pub workflow: Option<String>,
109    /// CEL expression for event matching.
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub condition: Option<String>,
112}
113
114/// Stored action configuration.
115#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
116pub struct TriggerActionConfig {
117    /// Target workflow name.
118    pub workflow: String,
119    /// Target workspace name.
120    pub workspace: String,
121    /// Optional arguments passed to the created task.
122    #[serde(default, skip_serializing_if = "Option::is_none")]
123    pub args: Option<HashMap<String, Vec<String>>>,
124    /// Whether to start the task immediately (default true).
125    #[serde(default = "default_start")]
126    pub start: bool,
127}
128
129fn default_start() -> bool {
130    true
131}
132
133/// Stored history retention limits.
134#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
135pub struct TriggerHistoryLimitConfig {
136    /// Number of successful tasks to retain.
137    #[serde(default, skip_serializing_if = "Option::is_none")]
138    pub successful: Option<u32>,
139    /// Number of failed tasks to retain.
140    #[serde(default, skip_serializing_if = "Option::is_none")]
141    pub failed: Option<u32>,
142}
143
144/// Stored throttle configuration.
145#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
146pub struct TriggerThrottleConfig {
147    /// Minimum interval in seconds between trigger firings.
148    #[serde(default)]
149    pub min_interval: u64,
150}